我已经看到了JSR305与JSR308(Java Type Anotations)的问题 - 这将成为标准吗?我理解JSR 308和JSR 305之间的区别.
我也明白,在这个时候,308是针对Java 7,305不是,我很好奇305的整体状态.
具体来说,我在我的一些项目中使用Google Collections和JSR-305(与Guice最佳实践倡导者的方式类似)并且想知道是否有更多"未来方向" - 我应该使用的友好方法代替.我打算在JSR-305小组上询问这个问题,但该小组没有太多活动,我只是想知道这里是否有人有更多信息.
到目前为止,我们一直在使用Findbugs JSR-305注释(com.google.code.findbugs:jsr305),包括工具支持(Sonar,Eclipse,Findbugs,...)在内的一切工作正常.
但是我们的理解是Java 9中的Jigsaw将打破JSR-305注释(不允许在两个模块中使用一个包).这在JavaOne 2015上得到了证实.Oracle的推理是JSR-305从未发生过,JSR-250必须支持这些注释.
我们正在寻找可以在Java 8和Java 9中工作的JSR-305注释的替换.如果历史是任何指南,Java 9 GA和Java 8 EOL之间的时间将相当短,我们想修复我们的任何不兼容性提前编码.从理论上讲,我们可以升级JDK的注释模块,但是在我们的工具链中执行此操作似乎需要做很多工作.
annotations static-analysis jsr305 java-platform-module-system java-9
我的问题是后续这一块.
在过去的FindBugs版本中,可以使用@DefaultAnnotation(Nonnull.class)
或@DefaultAnnotationForFields(Nonnull.class)
表示应将包中的所有字段视为@Nonnull
.在FindBugs的(2.0)的当前版本@DefaultAnnotation
和@DefaultAnnotationForFields
已被弃用,并且我们都应该使用JSR-305来代替.但JSR-305似乎并未涵盖(现已弃用)FindBugs注释所涵盖的所有内容.
该javadoc的确实表明了一些替代品:
@ParametersAreNonnullByDefault
.这(显然)仅适用于参数,而不适用于成员字段.@CheckReturnValue
,当应用于类型或包时.同样,这不适用于成员字段.@TypeQualifierDefault
.也许这可以做我想要的,但我不明白它是如何工作的,除了一些神秘的javadoc之外,我无法找到任何有关其用法或意图的文档或示例.我认为这将有助于我创建自己的注释,但我能确定所有工具(FindBugs,Eclipse等)都能正确地解释这个新注释(甚至根本不能)吗?该javadoc中没有提供关于如何处理其弃用任何提示.
因此,使用当前版本的FindBugs和/或JSR-305,我应该如何表明特定包中(甚至某个类)中的所有成员字段都应该被视为@Nonnull
?它甚至可能吗?
似乎有两种不同的JSR用于注释.
JSR-305:软件缺陷检测的注释 (附加资源)
JSR-308:Java类型的注释 (附加资源)
两者似乎都面向静态代码分析.
你知道吗:
在对文件@ParametersAreNonnullByDefault
说,认为:
此注释可以应用于包,类或方法,以指示默认情况下该元素中的方法参数是非空的,除非...
我不认为方法的返回类型/值是它的参数.它只是它的签名的一部分,所以这对我来说有点模棱两可.
正如Joachim Sauer在他的回答的评论部分中为我指出的那样,名称@ParametersAreNonnullByDefault
(参数)应该清楚地表明这个注释不适用于方法的返回类型/值.我是盲人!:)谢谢Joachim!
鉴于此,我只能说@EverythingIsNonnullByDefault
应该存在于某个地方.:)
注意:我正在谈论的那些注释是由JSR305指定的.
我有最新的Findbugs(1.3.9), 当一些用@Nonnull注释的字段被赋值为null时,它会正确地发现错误.
但是,在我的项目中,"非空逻辑"是默认情况.我会说 只有5%的情况才明确允许null.
因此,用@Nonnull注释95%的字段会非常不方便.我更愿意用@Nullable注释那些5%的字段.
我尝试使用@Nonnull注释整个包,它不会改变任何东西.
那么,以某种方式可以指定默认逻辑?
在查找stackoverflow的信息时,我看到了一个类似于我的问题,但这里没有真正的答案.
我需要将我的maven项目从番石榴11.0.2迁移到番石榴14或更高版本(我需要RangeSet).我用依赖更新了我的maven pom:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
然后我运行maven构建,并得到此错误:
[ERROR] xxx.java: cannot find symbol
[ERROR] symbol : class Nonnull
[ERROR] location: package javax.annotation
Run Code Online (Sandbox Code Playgroud)
我仔细看了一下,这个注释是用JSR305提供的,其上依赖于guava 11.0.2,因为mvn存储库会报告它.
我觉得奇怪的是,番石榴14还依赖于JSR305作为mvn存储库报告.
如果我将JSR依赖项添加到我的pom,那么编译运行正常:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
<scope>provided</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)
但是,如果guava已经依赖它,为什么我必须将此依赖项添加到我的pom中?这看起来更像是一种解决方法,而不是解决方案,我更愿意理解并使事情变得清晰.
感谢您的参与.
我正在开发人员使用不同IDE的环境中工作 - Eclipse,Netbeans和IntelliJ.我正在使用@Nonnull注释(javax.annotation.Nonnull)来指示方法永远不会返回null:
@Nonnull
public List<Bar> getBars() {
return bars; // this.bars is a final, initialized list
}
Run Code Online (Sandbox Code Playgroud)
如果他们执行以下操作之一,我希望其他开发人员收到警告:
IntelliJ支持第一种方案.第二个不是; 客户端不会被警告不需要检查null.
我们无论如何都计划转向收集集合的克隆而不是集合本身,所以最好忘记@Nonnull而是这样做:
public List<Bar> getBars() {
return new ArrayList<Bar>(bars);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
为了澄清,我不打算为此更改IDE.我想知道上面提到的IDE是否支持我上面描述的内容 - 或者,如果有充分理由说明为什么它不受支持.
我明白了不要太依赖合同.但是,如果我用最后一段中的样式编写getBars()(返回列表的克隆),那么例如IntelliJ会标记任何代码的警告
if (foo.getBars() == null) { ... }
Run Code Online (Sandbox Code Playgroud)
如果您选择遵循此警告并删除空检查,则您似乎同样依赖于不更改的getBars()实现.但是,在这种情况下,您似乎依赖于实现细节而不是显式合同(与@Nonnull的情况一样).
编辑#2:
我不关心执行速度,空检查确实非常快.我担心代码可读性.考虑以下:
选项A:
if ((foo.getBars() == null || foo.getBars().size() < MAXIMUM_BARS) &&
(baz.getFoos() == null || baz.getFoos().size() < MAXIMUM_FOOS)) {
// do something
}
Run Code Online (Sandbox Code Playgroud)
选项B:
if (foo.getBars().size() < MAXIMUM_BARS &&
baz.getFoos().size() < MAXIMUM_FOOS) { …
Run Code Online (Sandbox Code Playgroud)