【问题标题】:What are the differences between null analysis annotations packages?空分析注释包之间有什么区别?
【发布时间】:2016-08-25 18:00:50
【问题描述】:

Which @NotNull Java annotation should I use? 的问题已经过时并且有点基于意见。从那以后,Java 8 和更新的 IDE 一起出现了。

虽然 Java 8 允许通过集成 JSR 308类型注释,但它不附带任何注释。来自JSR 308 Explained: Java Type Annotations by Josh Juneau

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

仅考虑提供至少某种@CanBeNull@CannotBeNull 的解决方案,我发现以下信息(可能是错误的):

有些用于静态代码分析,有些用于运行时验证。

上述选项之间的实际区别是什么?是否有(将有)一个标准,还是每个人都可以编写自己的分析框架?

【问题讨论】:

    标签: java standards code-analysis nullable non-nullable


    【解决方案1】:

    除了你提到的之外,还有其他一些无效性分析;例如,IntelliJ 包含一个nullness analysis

    以下是有关空值分析的一些关键问题:

    • 它是在编译时工作还是在运行时工作?编译时分析给程序员提前警告潜在的错误。通过运行时分析,您的程序仍然会崩溃,但它可能会更早地崩溃或带有更多信息的错误消息。

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

    • 分析的精确度如何?它多久遭受一次错误警报,或者在程序实际正确时发出警告?它多久会错过警报,或者没有通知您程序中的真正错误?

    • 工具是否内置在 IDE 中?如果是这样,它可能更容易使用。如果没有,任何程序员都可以使用它,而不仅仅是使用该特定 IDE 的程序员。

    您提到的三个工具都在编译时工作。 FindBugs 是一个 bug 查找器,其他的是验证器。 Checker Framework 具有更好的精度,但其他两个具有更好的 IDE 集成。 FindBugs 不适用于 Java 8 类型注释 (JSR 308);其他两个都支持 Java 8 和 pre-Java-8 注释。所有这些工具都在程序员的工具箱中占有一席之地。哪一个适合您取决于您​​的需求和目标。

    回答您的其他一些问题:

    FindBugs 的注解使用javax 域,因为它的设计者希望Oracle 将FindBugs 用作Java 标准(!)。从未发生过。你说得对,javax 的使用让很多人误以为它是官方的或受 Oracle 青睐的,但事实并非如此。

    是否有(将要)一个标准,还是每个人都可以编写自己的分析框架?

    目前,Oracle 希望社区尝试创建和使用各种分析框架。他们觉得他们还没有充分理解各种方法的优缺点来创建一个标准。他们不想过早地创建一个包含有缺陷的方法的标准。他们对未来制定标准持开放态度。

    【讨论】:

    • 您能解释一下“更好的精度”(比什么更好)是什么意思吗?您是指与@Raw 等附加注释的集成吗?否则,我会认为精度与 Eclipse 的差异主要是一种工具或另一种工具可能存在的错误问题(并且有望修复)。
    • Re IDE 集成:Eclipse 的分析是 ecj 的一部分,ecj 是集成在 Eclipse IDE 中的编译器。这并不妨碍任何人在 IDE 之外使用 ecj(及其分析)。
    • 更好的精度:Eclipse 的 nullness 分析缺少 Checker Framework 支持的许多功能,例如处理映射键、部分初始化的对象、方法前置和后置条件等等。这些对于在不降低精度的情况下对实际代码进行实际验证至关重要。如果您只对发现错误而不是验证感兴趣,那么这些功能就不那么重要了。
    • 我们是否同意 Checker Framework 增加的精度本质上是由于除了 @NonNull@Nullable 之外还支持更多注释?我认为应该添加这些信息,因为问题只提到了这两个基本注释。
    • 这是一个内容丰富且完整的答案,解释了应该查看哪些参数来区分这些工具并将它们应用于指定的工具。谢谢。
    【解决方案2】:

    您收集的信息已经描述了它:

    基于类型注释 (JSR 308) 的静态分析确实比以前的方法强大得多。

    两组注释使用 JSR 308,都是为了执行静态分析(也可以认为是高级类型检查)。促进这些注释的两个工具的核心本质上是兼容的(并且每个工具也可以使用另一个的注释)。 我所知道的差异主要在两个方面:

    • IDE 集成。
    • 未注释类型的解释。在严格的世界中,每种类型要么是非空的,要么可以为空,所以如果一个注解缺失,它可以被默认解释为非空。或者,底层类型系统可以使用“legacy types”的概念,在需要“未经检查的转换”时发出警告(类似于泛型类型和原始类型的组合)。据我所知,Checkers 框架采用严格的方法,而 Eclipse 允许您在 @NonNullByDefault 策略和承认“遗留类型”之间进行选择(为了迁移)。

    据我所知,目前没有人计划投资于这些注释的标准化。

    【讨论】:

    • 您对未注释类型的评论具有误导性。 Checker 框架可容纳未注释的代码,并提供对遗留类型的灵活处理。它允许关于库的最佳情况或最坏情况假设,使默认值可以为空或非空,启用或禁用警告,在不修改其源代码的情况下注释第三方库等等 - 所有这些都具有良好 -定义的语义。
    • @mernst 我当然不想误导任何人。我只是根据我的知识回答。显然,这些知识已经过时了。对此感到抱歉。
    猜你喜欢
    • 1970-01-01
    • 2019-09-13
    • 2019-07-03
    • 2022-01-21
    • 2012-11-10
    • 2019-01-25
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    相关资源
    最近更新 更多