英文:
How to allow only classes annotated with some annotation in method parameters in Java?
问题
假设我有一个注解 @MyAnnotation
和两个类:
@MyAnnotation
class Foo {
}
class Bar {
}
以及一个需要类作为参数的方法:
someMethod(Class<?> klass)
是否有可能限制 someMethod
方法的参数只能是带有 @MyAnnotation
注解的类?我的意思是:
someMethod(Foo.class) // 必须可行
someMethod(Bar.class) // 编译错误
如果可以,如何实现?
英文:
Let's suppose I have annotation @MyAnnotation
and two classes:
@MyAnnotation
class Foo {
}
class Bar {
}
and some method that needs class as parameter
someMethod(Class<?> klass)
Is it possible to restrict someMethod
parameter only to classes that are annotated with @MyAnnotation
? I mean:
someMethod(Foo.class) //Must work
someMethod(Bar.class) //Compiler error
If yes, how to do that?
答案1
得分: 3
是的,这是可能的。
作为一般规则,如果使用注解来表示属性,您将需要使用注解处理器。
以下是使用Checker Framework的完整示例。
文件SO61029446.java
:
public class SO61029446 {
void someMethod(Class<? extends @MyAnnotation Object> klass) {}
void client() {
someMethod(Foo.class); // 必须正常工作
someMethod(Bar.class); // 编译错误
}
}
@MyAnnotation
@SuppressWarnings("subtyping")
class Foo {}
class Bar {}
文件MyAnnotation.java
:
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownMyAnnotation.class)
@interface MyAnnotation {}
@DefaultQualifierInHierarchy
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf({})
@interface UnknownMyAnnotation {}
现在,运行这些命令(在安装了Checker Framework之后):
javacheck MyAnnotation.java
javacheck -g SO61029446.java -processor org.checkerframework.common.subtyping.SubtypingChecker -Aquals=MyAnnotation,UnknownMyAnnotation SO61029446.java
第二个命令的输出为:
SO61029446.java:11: error: [argument.type.incompatible] incompatible types in argument.
someMethod(Bar.class); // 编译错误
^
found : @UnknownMyAnnotation Class<@UnknownMyAnnotation Bar>
required: @UnknownMyAnnotation Class<? extends @MyAnnotation Object>
编译器对非法调用提出了投诉,但允许了合法调用,正如您所要求的。
一些建议:
javacheck
命令如Checker Framework手册中所述。- 有两个
javacheck
命令,因为第一个命令使得注解在第二个命令的类路径上可用。 Foo
类上的@SuppressWarnings("subtyping")
注解可能不需要,这取决于您的实际代码。(这只是一个示例。)- Slaw的答案以“不,这是不可能的。”开头,这是错误的。Slaw用不同的方法在没有使用注解的情况下解决了问题,这在某些方面是不错的(因为它仅使用Java编译器而没有额外的工具),但它并没有回答关于使用注解的问题。
英文:
Yes, this is possible.
As a general rule, if a property is expressed using an annotation, you will need to use an annotation processor.
Here is a full example that uses the Checker Framework.
File SO61029446.java
:
public class SO61029446 {
void someMethod(Class<? extends @MyAnnotation Object> klass) {}
void client() {
someMethod(Foo.class); // Must work
someMethod(Bar.class); // Compiler error
}
}
@MyAnnotation
@SuppressWarnings("subtyping")
class Foo {}
class Bar {}
File MyAnnotation.java
:
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownMyAnnotation.class)
@interface MyAnnotation {}
@DefaultQualifierInHierarchy
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf({})
@interface UnknownMyAnnotation {}
Now, run these commands (after installing the Checker Framework):
javacheck MyAnnotation.java
javacheck -g SO61029446.java -processor org.checkerframework.common.subtyping.SubtypingChecker -Aquals=MyAnnotation,UnknownMyAnnotation SO61029446.java
The output of the second command is:
SO61029446.java:11: error: [argument.type.incompatible] incompatible types in argument.
someMethod(Bar.class); // Compiler error
^
found : @UnknownMyAnnotation Class<@UnknownMyAnnotation Bar>
required: @UnknownMyAnnotation Class<? extends @MyAnnotation Object>
The compiler has complained about the illegal invocation but has permitted the legal invocation, just as you requested.
A few notes:
- The
javacheck
command is as described in the Checker Framework Manual. - There are two
javacheck
commands because the first one makes the annotations available on the classpath for the second one. - The
@SuppressWarnings("subtyping")
annotation on theFoo
class might not be needed, depending on your actual code. (This is a toy example.) - Slaw's answer starts with first sentence "No, this is not possible.", which is incorrect. Slaw's different approach to solving the problem without annotations is not a bad one (in some ways it's better because it uses just the Java compiler without any additional tool), but it does not answer this question about using annotations.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论