比 Java 更强大的 kotlin.Deprecated

举报
yechaoa 发表于 2022/05/30 23:45:19 2022/05/30
【摘要】 我们都知道 Java 有一个java.lang.Deprecated注解,用来将一个 API 标记为“废弃”,或者说“不建议使用”。比如 String 类就有一个被标记为 Deprecated的构造函数:...

我们都知道 Java 有一个java.lang.Deprecated注解,用来将一个 API 标记为“废弃”,或者说“不建议使用”。比如 String 类就有一个被标记为 Deprecated构造函数

@Deprecated
public String(byte ascii[], int hibyte) {
    this(ascii, hibyte, 0, ascii.length);
}

  
 
  • 1
  • 2
  • 3
  • 4

Java 还提供了一个 @deprecated 的文档标签,用于提供相关信息。

这个注解存在几个缺陷:

  • 无法禁止使用废弃的 API,单单一个编译警告不可能阻止划水程序员;
  • 无法提供足够的信息,为什么这个 API 被废弃了?需要用哪个 API 代替?毕竟文档注释不是强制性的。

对于这个问题,Kotlin 的解决方案是 kotlin.Deprecated 注解,它比 java.lang.Deprecated更强大、更人性化。

kotlin.Deprecated的声明如下:

@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS)
@MustBeDocumented
public annotation class Deprecated(
    val message: String,
    val replaceWith: ReplaceWith = ReplaceWith(""),
    val level: DeprecationLevel = DeprecationLevel.WARNING
)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • @Target 表示 Deprecated可以用在类、函数、属性、注解类、构造函数、getter、setter 和类型别名上;
  • @MustBeDocument表示Deprecated是个公开的 API,必需包含在 API 文档里。

我们重点看三个参数:

第一个参数很简单,String 类型的 message,需要在这里说明废弃的原因。

@Deprecated("this function is deprecated!")
fun oldAdd(a: Int, b: Int) {
    println(a + b)
}

fun main(args: Array<String>) {
    oldAdd(1, 2)
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

比如我们定义了上面的函数 oldAdd,用 Deprecated 标注一下,如果调用这个函数,就会出现编译警告:

Warning:(7, 5) Kotlin: ‘oldAdd(Int, Int): Unit’ is deprecated. this function is deprecated!

我们定义 Deprecated 时给的 this function is deprecated! 出现在了警告信息里,让我们排查问题方便不少。

第三个参数是DeprecationLevel这个枚举里定义的三个废弃级别之一,在使用了 Deprecated API 的地方给出不同级别的警告 :

public enum class DeprecationLevel {
    WARNING,
    ERROR,
    HIDDEN
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • WARNING:默认选项,编译依然会成功,但会出现编译警告;
  • ERROR:编译错误,相当于禁止使用这个 API;
  • HIDDEN:隐藏,无法调用这个 API。

我们把上面的代码改一下,加上自定义的废弃级别:

@Deprecated(
    "this function is deprecated!",
    ReplaceWith(""), // 无法省略
    level = DeprecationLevel.ERROR
)
fun oldAdd(a: Int, b: Int) {
    println(a + b)
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

再编译就会出现编译错误,编译直接失败:

Error:(11, 5) Kotlin: Using ‘oldAdd(Int, Int): Unit’ is an error. this function is deprecated!

如果换成HIDDEN

Error:(11, 5) Kotlin: Unresolved reference: oldAdd

找不到这个函数了……

最后是第二个参数,需要是 ReplaceWith 类型,它是一个注解类型(因为注解的参数只能是基本类型、String 和注解类型)。声明如下:

@Target()
@Retention(BINARY)
@MustBeDocumented
public annotation class ReplaceWith(val expression: String, vararg val imports: String)


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • expression 是要替换成的代码段,智能替换参数;
  • imports 是需要额外 import 的依赖。

定义一个函数newAdd,放进new包里:

package new

fun newAdd(a: Int, b:Int) {
    println("$a + $b = ${a + b}")
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

然后修改一下oldAdd 函数:

@Deprecated(
    "this function is deprecated!",
    ReplaceWith("newAdd(a, b)", "new.newAdd")
)
fun oldAdd(a: Int, b: Int) {
    println(a + b)
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这样,我们在 IDEA 里就可以按 Alt + Enter 一键替换:
在这里插入图片描述
替换时会自动匹配参数,并导入 imports 中定义的依赖:
在这里插入图片描述

原文链接:https://zhuanlan.zhihu.com/p/32890550

文章来源: blog.csdn.net,作者:yechaoa,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/yechaoa/article/details/109162427

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。