我可以将方法标记为不支持Kotlin调用者,但不能标记为Java调用者吗?

时间:2018-10-31 11:30:46

标签: java kotlin

我想以对Kotlin调用者有用的方式扩展API,但对Java调用者无效。因此,我想鼓励Kotlin用户切换到新方法,而不必打扰Java用户。我们有一个庞大的代码库,它混合了Java和Kotlin,不会在不久的将来成为100%Kotlin。

是否可以添加仅在Kotlin中显示而不在Java中显示的@Deprecate标签或类似标签?

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

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

即使禁用了日志记录,也会在每次调用时创建该字符串。修复logger API以分别使用格式字符串和参数的做法将是一项重大且具有破坏性的更改。但是,Kotlin的可为null的类型可以为我们提供一个非常便宜的解决方案:

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

仅在所有Kotlin代码中将get().替换为getNullable()?.的情况。但是我不想在Java代码中使用getNullable(),因为存在NullPointerException的风险。因此,理想情况下,最好在Kotlin中弃用旧的Log.get方法,而不在Java中弃用。

2 个答案:

答案 0 :(得分: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,对吗?

答案 1 :(得分:1)

有两个部分

  • 隐藏Kotlin调用者的方法
  • 隐藏Java调用程序中的方法

要从Java调用程序隐藏方法,可以使用@JvmSynthetichere上的更多内容。 要从Kotlin调用者中隐藏方法,我找不到直接执行该方法的方法,但是根据建议here,您可以使用@JvmName为该方法提供一个好的名称,并在实际的{ {1}}名称

所以现在类看起来像

fun