Reputation:
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?
Upvotes: 0
Views: 2757
Reputation: 8117
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:
javacheck
command is as described in the Checker Framework Manual.javacheck
commands because the first one makes the annotations available on the classpath for the second one.@SuppressWarnings("subtyping")
annotation on the Foo
class might not be needed, depending on your actual code. (This is a toy example.)Upvotes: 2