How do annotations like @Override work internally in Java?

前端 未结 6 861
粉色の甜心
粉色の甜心 2020-12-02 03:56

Can anybody explain to me how annotations work internally in java?

I know how we can create custom annotations by using java.lang.annotation library in java. But I s

6条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-02 04:45

    Besides what others suggested, I recommend you write a customized annotation and its processor from scratch to see how annotation works.

    In my own, for example, I have written an annotation to check whether methods are overloaded in compile time.

    Firstly, create an annotation named Overload. This annotation is applied to method so I annotate it with @Target(value=ElementType.METHOD)

    package gearon.customAnnotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    @Target(value=ElementType.METHOD)
    public @interface Overload {
    
    }
    

    Next, create corresponding processor to handle elements annotated by defined annotation. For method annotated by @Overload, its signature must appear more than one time. Or the error is printed.

    package gearon.customAnnotation;
    
    import java.util.HashMap;
    import java.util.Map.Entry;
    import java.util.Set;
    
    import javax.annotation.processing.AbstractProcessor;
    import javax.annotation.processing.RoundEnvironment;
    import javax.annotation.processing.SupportedAnnotationTypes;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.TypeElement;
    import javax.tools.Diagnostic.Kind;
    
    @SupportedAnnotationTypes("gearon.customAnnotation.Overload")
    
    public class OverloadProcessor extends AbstractProcessor{
    
        @Override
        public boolean process(Set annotations, RoundEnvironment roundEnv) {
            // TODO Auto-generated method stub
            HashMap map = new HashMap();
    
            for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){
                String signature = element.getSimpleName().toString();
                int count = map.containsKey(signature) ? map.get(signature) : 0;
                map.put(signature, ++count);
            }
    
            for(Entry entry: map.entrySet()){
                if(entry.getValue() == 1){
                    processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() +  " has not been overloaded");
                }
            }
            return true;
        }
    }
    

    After packaging annotation and its process into a jar file, create a class with @Overload and use javac.exe to compile it.

    import gearon.customAnnotation.Overload;
    
    public class OverloadTest {
        @Overload
        public static void foo(){
        }
    
        @Overload
        public static void foo(String s){
    
        }
    
        @Overload
        public static void nonOverloadedMethod(){
    
        }
    } 
    

    Since nonOverloadedMethod() has not actually been overloaded, we will get the output like below:

提交回复
热议问题