我正在查看Checker Framework提供的中央maven存储库中的自定义批注jdk-8的.jar文件的字节码。
在那里,我注意到Object.class和Class.class文件中存在一些无效的Java代码。当我在Eclipse中加载jar时,它是带有以下语法的注释:
@jdk.Profile+Annotation(value=(int) 1)
public class java.lang.Object {
Run Code Online (Sandbox Code Playgroud)
现在,据我所知,此注释名称是无效的Java。但是,我假设这可能对编译器有意义(类似于编译器分配给匿名类的名称)。我不确定是什么,也无法在网上搜索中找到任何有关它的信息。因此,查询。
任何帮助表示赞赏。
java.lang.annotation.ElementType.TYPE_USEJDK8 中添加的Checkers Framework引用。当我在JDK7下使用它时,我收到以下警告:
unknown enum constant java.lang.annotation.ElementType.TYPE_USE
这是一个合理的警告,但是对于我认为无害的情况如何抑制它?
我想用@Nullable-annotation(来自Java Checker Framework)注释一个完全限定的类名,例如:
class Demo {
private transient @Nullable org.apache.lucene.search.Query cached_results;
// ...
}
Run Code Online (Sandbox Code Playgroud)
但是这会导致错误:
scoping construct cannot be annotated with type-use annotation: @checkers.nullness.quals.Nullable
Run Code Online (Sandbox Code Playgroud)
如何注释完全限定的类名?
当Checker Framework的Nullness Checker遇到未初始化的字段时,将生成错误。
[ERROR] /home/glts/src/example/src/main/java/BookRepositoryImpl.java:[39,7]
error: [initialization.fields.uninitialized] the constructor does not initialize fields: em
Run Code Online (Sandbox Code Playgroud)
现在,通过依赖注入注入一些字段是一种常见的模式:
@Repository
public class BookRepositoryImpl implements BookRepository {
@PersistenceContext
private EntityManager em;
@Override
@Nullable
public Book findById(int id) {
return em.find(Book.class, id);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
在这里,@javax.persistence.PersistenceContext注释确保在构建存储库em后将保留对EntityManager实例的引用。
更一般地,在这些情况下,应用程序框架保证字段被初始化并且在使用时不为空–但是Checker框架不知道这一点。
到目前为止,我发现一种解决方法是将字段注入转换为构造函数注入(@Inject)。但是,在上面的示例中,这不是选项。
有没有一种方法可以告诉Checker Framework注入了一个字段,因此正确地初始化了该字段并且该字段为非null,而没有简单地抑制这些错误?
Checker 框架可以与 Error Prone 一起使用吗?据我所知,它们在编译时检查方面具有重叠的目的,但它们并不做所有相同的事情。我使用 gradle,但我怀疑这两个插件是否可以同时使用(事实上有一个未解决的错误)。如果在命令行上手动执行此操作,我如何在一次javac调用中针对文件运行检查器和易出错的操作?
考虑一个方法,例如ConcurrentHashMap的compute方法:
public V compute(
K key,
BiFunction<? super K,? super V,? extends V> remappingFunction)
Run Code Online (Sandbox Code Playgroud)
我想对此进行注释,以便使用检查器框架进行可空性检查:
public @Nullable V compute(
K key,
BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction);
Run Code Online (Sandbox Code Playgroud)
但这不太正确:我希望能够推断它返回? extends @NonNull V以避免在我知道remappingFunction从不返回的情况下进行空检查null,例如:
@NonNull V value = map.compute(key, (k, v) -> {
if (v == null) {
return new V();
}
v.increment();
return v;
});
Run Code Online (Sandbox Code Playgroud)
可以这样表达吗?
我想我应该尝试一下检查框架,但我得到了很多这样的东西
/Users/calebcushing/IdeaProjects/ppm/scaf/src/main/java/com/xenoterracide/scaf/Config.java:22: warning: [type.anno.before.modifier] write type annotation @NonNull() immediately before type, after modifiers [abstract]
abstract Map<String, SkeletonConfiguration> getTemplates();
Run Code Online (Sandbox Code Playgroud)
对于这段代码
/Users/calebcushing/IdeaProjects/ppm/scaf/src/main/java/com/xenoterracide/scaf/Config.java:22: warning: [type.anno.before.modifier] write type annotation @NonNull() immediately before type, after modifiers [abstract]
abstract Map<String, SkeletonConfiguration> getTemplates();
Run Code Online (Sandbox Code Playgroud)
这似乎是我应该写的建议
@Nullable
abstract String getWorkdir();
Run Code Online (Sandbox Code Playgroud)
但这违背了JLS,有什么办法可以禁用它吗?
Java 8类型注释(JSR 308)允许类型检查器执行静态代码分析。例如,Checker Framework可以通过注释检查可能的无效性@NonNull。
各种项目定义了自己的NonNull注释,例如:
org.checkerframework.checker.nullness.qual.NonNulledu.umd.cs.findbugs.annotations.NonNulljavax.annotation.Nonnulljavax.validation.constraints.NotNulllombok.NonNullorg.eclipse.jdt.annotation.NonNull对于此类注释,我希望它@interface具有@Retention(RetentionPolicy.CLASS),因为在运行时通常不需要它们。最重要的是,代码在相应的库上没有任何运行时依赖项。
虽然org.eclipse.jdt.annotation.NonNull采用这种方法,但其他大多数NonNull注释(如javax.annotation.Nonnull(JSR 305)及其org.checkerframework.checker.nullness.qual.NonNull本身)也具有@Retention(RetentionPolicy.RUNTIME)。RetentionPolicy.RUNTIME这些注释中是否有任何特殊原因?
澄清:Checker Framework支持注释中的注释,以实现向后兼容。但是,在Java 8中使用它们只是为了避免运行时依赖性,这似乎是一个肮脏的技巧。