背景
Effective Java 中文版(原书第3版)的163页用到Stream.iterate(TWO, BigInteger::nextProbablePrime)用于生成素数流,引起我对这个函数的兴趣,一方面是它如何使用参数一来生成大于参数一的素数,另一方法是好奇BigInteger竟可以提供素数生成,再也不用手写素数判定方法了。
打开Intellij查看Stream.iterate源码,发现灰色的@Contract(pure=true) @NotNull。这行灰色字符既复制不了,也没有import过。鼠标放在@符号上,提示“External and inferred annotations”。好奇它们的作用,于是探求。
总结
在百度搜索@Contract(pure=true) @NotNull,点开文章1,它是讲解这两个注解的含义的,讲的不错,原来这两个注解是jetbrains的。
参考文章2导入包,并编写类,仿造Stream.iterate使用Objects.requireNonNull,点击类方法左边提示的@符号,选择insert,@Contract就被加到方法上了,并且可看到import了。
但我的疑惑是,为啥别人的类中该注解是灰色的,没有import。当我点击Stream.iterate的@符号弹出选项,提示我可以Edit method contract of iterate,点击它后发现我可以编辑contract且要保存到某个路径。于是隐隐觉得,灰色是因为是外部存储的注解。
文章3讲了如何分析及推断Nullable,分析时可选是否为其加上注解。我的2018版code下没有analyze,与code平级的analyze下有infer nullity,遂选之,效果是为我的参数自动加了@NotNull注解并import了。18版没有看到仅分析不自动加注解的选项,而文章3是21版。考虑安装license太难得到,所以就不升级版本了。文章3讲到的Inlay Hints显示的效果就是灰色的@Contract注解,但我的18版本没有该配置处,所以无法验证。但通过上面的过程,大概了解了工具是可以帮我们推断出来参数、返回值是否非空,方法是否是幂等。我们可以自己主动analyze代码并选择是否将推断的判空注解注释到变量上。应该也可以将其存到外部文件,以依赖包提供的时候,供查看方便,非功能性注解,仅增强可读性,为灰,不import。
文章4很直白地说出了我的理解。
讲真,如果你的接口提供给它人使用,你的api包里可以使用"外部注释"增强可读性,即使是内部代码,我觉得使用这些注解也能提高可读性,是可取的。
文章5解答了@Contract和@NotNull都可以表达相同意思时,该如何选择的问题。
待做
在实践中验证外部配置注解的情况下,无用代码是否能被提示出来,还是说要显示加注解。
无用代码指的是方法一注解表明若入参为null则返回null,方法二调用方法一时传的是null(null字面量,非运行时对象引用为null,因此可以编译期发现),接着将返回值作空判别。显示判别是无意义的,本就是空。
https://blog.csdn.net/howeres/article/details/119875169
JetBrains注解@NotNull/@Nullable/@Contract ↩︎https://www.w3cschool.cn/intellij_idea_doc/intellij_idea_doc-u4jy2ems.html
IntelliJ IDEA怎么使用@Contract注释 ↩︎https://www.jetbrains.com/help/idea/inferring-nullity.html
Infer nullity ↩︎ ↩︎ ↩︎https://www.w3cschool.cn/intellij_idea_doc/intellij_idea_doc-map52eov.html
IntelliJ IDEA外部注释的使用 ↩︎https://stackoverflow.com/questions/31473060/when-to-use-contractnull-fail-and-when-to-use-notnull
When to use @Contract(“null -> fail”) and when to use @NotNull ↩︎