简体   繁体   中英

How to allow only classes annotated with some annotation in method parameters in Java?

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?

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 the Foo 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM