这个问题的意思是:null分析注释包之间有哪些区别?

4

这个问题我应该使用哪个@NotNull Java注释?已经过时且有些基于观点。自那时以来,Java 8和更新的IDE已经出现。

虽然Java 8通过整合JSR 308允许类型注释,但它本身并没有提供任何注释。来自Josh Juneau的《解释JSR 308:Java类型注释》的内容:

JSR 308, Java类型注释已经作为Java SE 8的一部分被纳入。
...
编译器检查器可以编写来验证带注释的代码,通过在代码不满足某些要求时生成编译器警告来强制执行规则。Java SE 8没有提供默认的类型检查框架,但可以编写自定义注释和处理器进行类型检查。还有许多可下载的类型检查框架,可以用作Java编译器的插件,以检查并强制执行已注释的类型。类型检查框架包括类型注释定义和一个或多个可插拔模块,与编译器一起用于注释处理。

只考虑提供至少某种类型的@CanBeNull和@CannotBeNull解决方案,我找到了以下信息(可能不准确): 一些用于静态代码分析,一些用于运行时验证。
以上选项之间的实际区别是什么?是否存在(即将出现)标准,还是打算让每个人编写自己的分析框架?
2个回答

5
您所收集的信息已经基本描述了它:
基于类型注释的静态分析(JSR 308)确实比以前的方法更加强大。使用JSR 308的两组注释都是为了进行静态分析(也可以被视为高级类型检查)。在核心部分,这两个工具推广这些注释本质上是兼容的(每个工具也可以消耗另一个工具的注释)。我所知道的区别主要有两个方面:
1. IDE集成。 2. 对未注释类型的解释。在“严格的世界”中,每种类型都是非空的还是可空的,因此如果缺少注释,则默认情况下可能会被解释为非空。或者,底层类型系统可以使用“遗留类型”的概念,在需要“不受检查的转换”时引发警告(类似于通用类型和原始类型的组合)。据我所知,Checkers Framework采用严格的方法,而Eclipse让您选择@NonNullByDefault策略并承认“遗留类型”(为了迁移)。
另外据我所知,目前没有人计划对这些注释进行标准化投资。

你对未注释类型的评论是误导性的。Checker框架可以适应未注释的代码,并提供对遗留类型的灵活处理。它允许对库进行最佳或最差情况的假设,使默认值可为空或非空,启用或禁用警告,对第三方库进行注释而不修改其源代码等等 - 并且所有这些都具有明确定义的语义。 - mernst
@mernst 我当然不想误导任何人。我只是尽我所知回答了问题。显然我的知识已经过时了。对此我感到抱歉。 - Stephan Herrmann

5
除了你提到的那些,还有其他一些空值分析存在;例如,IntelliJ 包含一个 nullness analysis
以下是一些关于空值分析需要问的关键问题:
  • 这个工具是在编译时还是运行时起作用? 编译时分析可以提前警告程序员可能存在的错误。使用运行时分析,您的程序仍然会崩溃,但可能会更早地崩溃或提供更详细的错误消息。

  • 它是验证器还是错误查找器? 验证器提供正确性保证:如果该工具没有报告任何潜在错误,则程序在运行时不会遭受给定错误。错误查找器报告一些问题,但如果它没有报告任何问题,则您的程序可能仍然有误。验证器通常需要程序员进行更多的工作,包括注释程序。错误查找器可以要求更少的开始使用工作,因为它可以在未注释的程序上运行(尽管在这种情况下可能不会产生非常好的结果)。

  • 分析的精度如何? 它多久会出现误报警告,即在程序实际上是正确的情况下发出警告?它多久会错过警报,即未能通知您程序中的真正错误?

  • 工具是否内置于IDE中? 如果是,则使用起来可能更容易。如果不是,它可以被任何程序员使用,而不仅仅是使用特定IDE的程序员。

你提到的这三个工具都是在编译时运行的。FindBugs是一个缺陷查找器,而另外两个则是验证器。Checker Framework的精度更高,但其他两个在IDE集成方面更好。FindBugs不支持Java 8类型注释(JSR 308);其他两个都支持Java 8和Java 8之前的注释。所有这些工具都有它们在程序员工具箱中的位置;哪一个适合你取决于你的需求和目标。
回答你的其他问题:
FindBugs的注释使用javax域,因为其设计者希望Oracle将FindBugs作为Java标准采纳(!)。但这从未发生过。你是对的,使用javax会让很多人误以为它是官方或Oracle所青睐的,但实际上并非如此。
“是否会有标准,还是打算让每个人编写自己的分析框架?”

目前,Oracle希望社区尝试创建和使用各种分析框架。他们认为自己还不了解各种方法的利弊,无法创建标准。他们不想过早地创建一个将有缺陷方法奉为圭臬的标准。他们未来可能会创建一个标准。


你能解释一下你所说的“更好的精度”是什么意思吗(比什么更好)?你是指与其他注释,如@Raw集成吗?否则,我认为精度方面与Eclipse的差异大多是由于其中一个工具可能存在的错误(并且希望可以修复)。 - Stephan Herrmann
关于IDE集成:Eclipse的分析是ecj的一部分,这是集成在Eclipse IDE中的编译器。这并不妨碍任何人在IDE之外使用ecj(及其分析)。 - Stephan Herrmann
更好的精度:Eclipse的nullness分析缺少许多Checker Framework支持的功能,例如处理映射键、部分初始化对象、方法前置和后置条件等等。这些对于实际验证现实世界代码而言是必不可少的,以避免低精度。如果您只关心错误查找而不是验证,则这些功能并不那么重要。 - mernst
我们可以认为,Checker Framework 增加的精度实质上是由于支持更多注释,除了 @NonNull@Nullable 之外吗?我认为应该添加这些信息,因为问题只提到了这两个基本注释。 - Stephan Herrmann
这是一个非常详细和完整的答案,解释了应该关注哪些参数来区分这些工具,并将其应用于指定的工具。谢谢。 - user1803551
@StephanHerrmann 我筛选了使用 至少 @NonNull@Nullable 的解决方案,因此像 Lombok 这样的东西被“取消资格”。如果有任何支持超过这两个的东西都可以。然而,我希望在回答的结尾看到惯常的免责声明,因为回答者正在/为 Checker Framework 工作。 - user1803551

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接