【问题标题】:Can I mark a method as deprecated for Kotlin callers, but not for Java callers?我可以将 Kotlin 调用者的方法标记为已弃用,但 Java 调用者不可以吗?
【发布时间】:2020-09-09 14:07:14
【问题描述】:

我想以一种对 Kotlin 调用者有用但对 Java 调用者有用的方式扩展 API。因此,我想鼓励 Kotlin 用户切换到新方法,而不会打扰 Java 用户。我们有一个混合了 Java 和 Kotlin 的大型代码库,而且短期内不会是 100% Kotlin。

有没有办法添加一个@Deprecate 标签或类似的标签,它只出现在 Kotlin 中,而不是 Java 中?

如果您对具体细节感兴趣,我们有一个Log 接口,它采用格式化字符串,如下所示:

Log.get().info("Log message with some $expensive $things to $format")

该字符串是在每次调用时创建的,即使日志记录被禁用。修复记录器 API 以分别获取格式字符串和参数将是一个巨大且具有破坏性的变化。然而,Kotlin 的可空类型可以为我们提供一个非常便宜的解决方案:

Log.getNullable()?.info("This $expensive $format should be skipped if there's no logger")

只是在所有 Kotlin 代码中将 get(). 替换为 getNullable()?. 的情况。但我不想在 Java 代码中使用getNullable(),因为存在NullPointerException 的风险。所以旧的 Log.get 方法应该在 Kotlin 中被理想地弃用,但在 Java 中不应该被弃用。

【问题讨论】:

  • Log.get() 返回什么,这怎么可能为空?您是否只是为了防止调用类中发生某些事情而使其为空? (这似乎有点奇怪)
  • Log.get() 返回一个 Logger 对象(但请注意,由于遗留原因,不是标准的 java.util.logging.Logger)。它总是返回一个有效的Logger,但在某些构建配置中,日志消息将被丢弃,因此格式化字符串所花费的时间被浪费了。这大多很便宜,但并非总是如此。所以是的,我想返回 null 以停止调用者格式化字符串。
  • 能否请您展示当前的Log 是如何实现的?或者它是什么(对象?同伴?)?另外:getNullable 现在是如何定义的?

标签: java kotlin


【解决方案1】:

假设一个类Log,其方法在companion object中定义,例如:

class Log {
  companion object {
    @JvmStatic
    fun get() : String = TODO()
    @JvmStatic
    fun getNullable() : String? = TODO()
  }
}

删除@JvmStatic 怎么样?还是创建一个扩展函数?

fun Log.Companion.getNullable() : String? = TODO()
class Log {
  companion object {
    @JvmStatic
    fun get() : String = TODO()
  }
}

扩展函数在 Java 中通常不像在 Kotlin 中那样容易访问。两者,删除 @JvmStatic 或扩展函数都需要 Java 代码中的以下内容:Log.Companion.getNullable 而不是 Log.getNullable... 也许这对您来说也可以,而不是弃用它。

即使我的猜测是错误的,扩展功能也可能满足您的需求。

关于仅针对 Kotlin 弃用方法...我认为这不起作用,但这是另一种解决方法。只需重命名方法并在方法上使用@JvmName("get"),例如:

@JvmStatic
@JvmName("get")
fun dont_ever_use_this_method_again_in_Kotlin() : String = TODO()

这将允许来自 Java 的Log.get,但不允许来自 Kotlin。而且我认为我们可以同意没有人会在 Kotlin 中调用 Log.dont_ever_use_this_method_again_in_Kotlin,对吧?

【讨论】:

  • 很有趣...只是通过弃用伴生对象来玩耍...这在 Java 中没有给我任何错误,但它显示了 Kotlin 方面的弃用:-)
  • 是的,我绝对想对 Java 调用者隐藏新方法,这是一个很好的方法。但我的问题是如何弃用/隐藏 Kotlin 调用者的旧方法。
  • 哇,弃用伴生对象!好主意,我试试看!
  • 这对我来说闻起来像一个错误......在查阅 javadoc 时,显示了弃用...... :-/
  • 好的...有一些东西让您永远不要再调用 Kotlin 中的方法 ;-) @JvmName 可能会成功...(这只是一种解决方法...但那是getNullable()?到,对吧?;-))
【解决方案2】:

这有两个部分

  • 对 Kotlin 调用者隐藏方法
  • 对 Java 调用者隐藏方法

为了对 Java Caller 隐藏方法,可以使用@JvmSynthetic;更多关于它here。 为了向 Kotlin Caller 隐藏方法,我找不到直接的方法,但正如 here 建议的那样,您可以使用 @JvmName 为该方法提供一个好名称,并在实际 fun 名称中添加一条弃用消息/p>

所以现在这个类看起来像

class Log {
    companion object {
        @JvmStatic
        @JvmName("get")
        fun dont_dare_using_this_from_kotlin_use_getNullable_instead(): String = TODO()

        @JvmSynthetic
        fun getNullable(): String = TODO()
    }
}

【讨论】:

    猜你喜欢
    • 2017-02-15
    • 2023-04-05
    • 2021-04-14
    • 2016-06-25
    • 2010-09-19
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多