简体   繁体   English

我可以使用 Java 注释来定义编译时检查吗?

[英]Can I use Java annotations to define compile time checks?

For example, I wanted to create the annotation @Out to target parameters.例如,我想为目标参数创建注释 @Out。 Then I would somehow use the compiler to check if the parameter value is set before the function returns.然后我会以某种方式使用编译器检查是否在函数返回之前设置了参数值。 Is this possible?这可能吗?

Also was thinking about a @Immutable annotation that would not allow any method not annotaded with @Const to be invoked or access to any public fields.还考虑了一个 @Immutable 注释,它不允许调用任何未使用 @Const 注释的方法或访问任何公共字段。 (compile time and probably runtime?) (编译时间和可能的运行时间?)

So far I have this:到目前为止,我有这个:

//I'm assuming Class retention is a subset of Runtime retention
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Out
{
    //no idea what to go in here.
}

this is the other annotation.这是另一个注释。 again, I have no complete definition for it:同样,我没有完整的定义:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Immutable
{

}

I think I can begin to devise a strategy to implement that at runtime using reflection, but I wanted to instruct the compiler or pre-processor to check that stuff for me instead, so my annotations would have zero overhead.我想我可以开始设计一种策略,在运行时使用反射来实现它,但我想指示编译器或预处理器为我检查这些东西,所以我的注释将有零开销。

This is one of those things that you think "if this could've been done, it would already be out there, and if it is, where can I grab it".这是您认为“如果可以做到这一点,它已经在那里,如果可以,我在哪里可以抓住它”的那些事情之一。

Edit : After further thought about @Const and @Immutable and after remembering java passes pointers to objects by value, I expanded the definition of @Const , got rid of @Immutable , and altered the definition of @Out , as follows bellow:编辑:在进一步考虑@Const@Immutable并记住 java 按值传递指向对象的指针之后,我扩展了@Const的定义,摆脱了@Immutable ,并更改了@Out的定义,如下所示:

/**
* When Applied to a method, ensures the method doesn't change in any
* way the state of the object used to invoke it, i.e., all the fields
* of the object must remain the same, and no field may be returned,
* unless the field itself is marked as {@code @Const}. A method 
* annotated with {@code @Const} can only invoke other {@code @Const}
* methods of its class, can only use the class's fields to invoke
* {@code @Const} methods of the fields classes and can only pass fields
* as parameters to methods that annotate that formal parameter as
* {@code @Const}.
*
* When applied to a formal parameter, ensures the method will not
* modify the value referenced by the formal parameter. A formal   
* parameter annotated as {@code @Const} will not be aliased inside the
* body of the method. The method is not allowed to invoke another 
* method and pass the annotated parameter, save if the other method 
* also annotates the formal parameter as {@code @Const}. The method is 
* not allowed to use the parameter to invoke any of its type's methods,
* unless the method being invoked is also annotated as {@code @Const}
* 
* When applied to a field, ensures the field cannot be aliased and that
* no code can alter the state of that field, either from inside the   
* class that owns the field or from outside it. Any constructor in any
* derived class is allowed to set the value of the field and invoke any
* methods using it. As for methods, only those annotated as
* {@code @Const} may be invoked using the field. The field may only be
* passed as a parameter to a method if the method annotates the 
* corresponding formal parameter as {@code @Const}
* 
* When applied to a local variable, ensures neither the block where the
* variable is declared or any nested block will alter the value of that 
* local variable. The local variable may be defined only once, at any
* point where it is in scope. Only methods annotated as
* {@code @Const} may be invoked using this variable, and the variable 
* may only be passed as a parameter to another method if said method
* annotates its corresponding formal parameter as {@code @Const}
*
*/
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD,
ElementType.LOCAL_VARIABLE})
@Inherited
public @interface Const
{

}

now the @Out :现在@Out

/**
* The formal parameter annotated with {@code @Out} must be undefined in 
* the scope of the caller, and it's the responsibility of the method to
* define it. If allowNull is true, the parameter can be explicitly set
* to null in the body of the method.
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.PARAMETER)
public @interface Out
{
    boolean allowNull() default false;
}

Edit: I'm trying to implement this as an eclipse plugin, but I'm completely lost reading the manual.编辑:我正在尝试将其实现为 Eclipse 插件,但我完全迷失了阅读手册。 I wrote a plugin with the basic logic for accessing the AST and visiting methods and fields.我编写了一个插件,其中包含访问 AST 和访问方法和字段的基本逻辑。 I then made a bunch of dummy annotations that my plugin should detect, then I try to print the results, but I'm not even sure what to expect.然后我做了一堆我的插件应该检测到的虚拟注释,然后我尝试打印结果,但我什至不确定会发生什么。 My plugin is a "Incremental Build" plugin.我的插件是一个“增量构建”插件。 Here's the code for it, If someone could take a look and just explain a few things to me.这是它的代码,如果有人可以看一下并向我解释一些事情。 I'm completely lost in this API.我完全迷失在这个 API 中。

https://github.com/Starless2001/Plugin-for-Eclipse https://github.com/Starless2001/Plugin-for-Eclipse

The javac compiler supports user-definable plugins, called annotation processors, that accomplish exactly what you want. javac 编译器支持用户可定义的插件,称为注解处理器,可以完全满足您的需求。 You can think of annotations as language extensions.您可以将注释视为语言扩展。

The definition public @interface Immutable { ... } defines the syntax: the @Immutable annotation that you can write in your program.定义public @interface Immutable { ... }定义了语法:您可以在程序中编写的@Immutable注释。 The annotation processor (the compiler plug-in) defines the semantics: it enforces the semantic rules and issues compiler warnings when your program violates the rules.注释处理器(编译器插件)定义语义:它强制执行语义规则并在您的程序违反规则时发出编译器警告。

One framework that makes it easy to write such annotation processors is the Checker Framework , and it contains definitions for annotations like @NonNull and @Immutable . Checker Framework是一个使编写此类注释处理器变得容易的框架,它包含诸如@NonNull@Immutable等注释的定义。 Here are two tutorials about how to use the Checker Framework to validate code: tutorial 1 , tutorial 2 .这里有两个关于如何使用 Checker Framework 来验证代码的教程:教程 1教程 2

Ordinary Java annotation processing is invoked on each declaration, such as classes, fields, methods, and method parameters, and ordinary Java gives the annotation processor no access to the program's full AST.对每个声明(例如类、字段、方法和方法参数)调用普通 Java 注释处理,而普通 Java 使注释处理器无法访问程序的完整 AST。 You can think of the Checker Framework as a library that extends the power of Java annotation processing.您可以将 Checker Framework 视为扩展 Java 注释处理功能的库。 It gives you access to the full AST of each class, and it lets you define rules for every statement in your program.它使您可以访问每个类的完整 AST,并允许您为程序中的每个语句定义规则。 Thus, your annotation processor can issue warnings when a statement invokes a non- @Const method on an @Immutable object.因此,当语句调用@Immutable对象上的非@Const方法时,您的注释处理器可能会发出警告。

Your annotation processor should be modular, working one class at a time.您的注释处理器应该是模块化的,一次工作一个类。 The annotation processor has access to the AST of the current class, plus the signatures, including annotations, of all classes that it uses.注释处理器可以访问当前类的 AST,以及它使用的所有类的签名,包括注释。 Annotation processing gives you that information (but not to the whole project's AST all at once).注释处理为您提供了该信息(但不是一次提供整个项目的 AST)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在编译时执行java注释 - Enforcing java annotations at compile time Java - 在不允许使用@NotNull或@Nullable注释时在编译时检测NPE的最佳方法 - Java - best way to detect NPE at compile time when not allowed to use @NotNull or @Nullable annotations Java是否允许在编译时进行不可变性检查? - Does Java allow immutability checks at compile-time? Java:使用注释在编译时生成自定义Java代码 - Java: Generate custom Java code at compile time using annotations 我可以使用自定义注释对 Java 类进行分类吗? - Can I use custom annotations to classify Java classes? 如何使用带有eclipse的注释和Java来使程序编译? - How can I make my program compile using annotations with eclipse and working with java? Java中的注释会导致编译时传递依赖吗? - Do annotations in Java result in compile-time transitive dependencies? Java运行时保留批注-在编译时需要批注类,但在运行时不需要吗? - Java runtime retention annotations - annotation class required at compile time but not at runtime? 修改java类以在编译时包含特定注释 - Modify java classes to include specific annotations at compile time 在Java 5中,注释类型的编译时间检查如何更改? - How is the compile time check of the type of annotations changed in Java 5?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM