The difference between annotationType and getClass in Annotation

Introduction to the original question:

 //In the Java language, through Class The Class object obtained by the forname (classname: String) method is Class <? >
 //How can I make it a class? extends Annotation>

 package com.github.unscientificjszhai.unscientificcourseparser.core.processor;
 ​
 import javax.annotation.processing.*;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.tools.Diagnostic;
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
 import java.util.Set;
 import java.util.TreeSet;
 ​
 /**
  * Annotation processor. Used to process annotations at compile time and generate a class scanner.
  *
  * @author UnscientificJsZhai
  */
 public class ParserBeanProcessor extends AbstractProcessor {
 ​
     private Messager messager;
     private Filer filer;
 ​
     private final ArrayList<Element> elements = new ArrayList<>();
     private final Class<? extends Annotation> annotationClass;
 ​
     public ParserBeanProcessor() throws ClassNotFoundException {
         Class<?> annotationClass = Class.forName("com.github.unscientificjszhai.unscientificcourseparser.core.parser.ParserBean");
         this.annotationClass = (Class<? extends Annotation>) annotationClass;
     }
 ​
     @Override
     public synchronized void init(ProcessingEnvironment processingEnv) {
         super.init(processingEnv);
         messager = processingEnv.getMessager();
         filer = processingEnv.getFiler();
     }
 ​
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (roundEnv.processingOver()) {
             FileGenerator.generateJavaFile(filer, elements);
         } else {
             Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotationClass);
             for (Element element : elements) {
                 messager.printMessage(Diagnostic.Kind.NOTE, element.getSimpleName().toString());
                 this.elements.add(element);
             }
         }
         return true
     }
 }

Background:

The return value of annotationType() is class <? Extensions annotation > type

 public Class<? extends Annotation> annotationType()
The annotationType method returns class <? > Generic, where? Is a subclass of Annotation

The return value of getClass() is class <? >

There are three ways to get class objects

  1. Class.forName("com.how2j.java.Annotation")

    1. DBUtil.class

      1. new DBUtil().getClass()

In a JVM, there is only one class object in a class. Therefore, the class objects extracted by the above three methods are the same.

Note: to be exact, only one class object exists under a ClassLoader and a class. Usually, there is only one ClassLoader under a JVM.

summary

When getting annotations in the JDK, all the annotations returned are Annotation types, as follows (intercepted from the JDK source code)

 public <A extends Annotation> A getAnnotation(Class<A> annotationClass)

After obtaining the Annotation instance, you can obtain the relevant Class through getClass (inherited from Object) and annotationtype (method in the Annotation interface). The following describes the difference between the two. The following is my own inference, not a conclusion obtained by browsing the source code.

Comparison between getClass and annotationType

Test code:

 package com.how2j.java.Annotation.GetClass;
 ​
 import com.how2j.java.Annotation.DBUtil;
 import com.how2j.java.Annotation.JDBCConfig;
 ​
 import java.lang.annotation.Annotation;
 ​
 public class GetClassAndAnnotationType {
     public static void main(String[] args) throws ClassNotFoundException {
 //        JDBCConfig a = JDBCConfig.class.getAnnotation(JDBCConfig.class);
 //        JDBCConfig a = (JDBCConfig) new DBUtil();
 //        JDBCConfig a = DBUtil.class.getAnnotation(JDBCConfig.class);
         JDBCConfig a = Class.forName("com.how2j.java.Annotation.DBUtil").getAnnotation(JDBCConfig.class);
         Class<? extends Annotation> b = a.annotationType();
         Class<?> c = a.getClass();
         JDBCConfig d = b.getAnnotation(JDBCConfig.class);
         JDBCConfig e = c.getAnnotation(JDBCConfig.class);
         System.out.println(d == e);
     }
 }
 ​

Test results:

 

As can be seen from the figure:

1. getClass() obtains a proxy class. Through this proxy class, you can obtain the annotated attributes on the class

2. annotationType() obtains the annotation itself. Through this interface, you can obtain the annotation on the annotation. For example, you can obtain the JDBC config annotation information on DBUtil through annotationType

Inference:

Annotation is a special interface that defines the attributes that annotation instances (annotation information on the Class obtained through getAnnotation) can have. It also has Class attribute.

The annotation instance obtained by getAnnotation method has its own type. It is the implementation class of JDK using proxy technology to implement annotation (annotation is a special interface), not the annotation type itself

reference resources:

The difference between annotationType and getclass in Annotation_ shuxiaohua's blog - CSDN blog

Appendix:

DBUtil

 
//package com.how2j.java.Annotation;
 //
 //import java.sql.Connection;
 //import java.sql.DriverManager;
 //import java.sql.SQLException;
 //
 //public class DBUtil {
 //    static String ip = "127.0.0.1";
 //    static int port = 3306;
 //    static String database = "test";
 //    static String encoding = "UTF-8";
 //    static String loginName = "root";
 //    static String password = "admin";
 //    static{
 //        try {
 //            Class.forName("com.mysql.jdbc.Driver");
 //        } catch (ClassNotFoundException e) {
 //            e.printStackTrace();
 //        }
 //    }
 //
 //    public static Connection getConnection() throws SQLException {
 //        String url = String.format("jdbc:mysql://%s:%d/%s?characterEncoding=%s", ip, port, database, encoding);
 //        return DriverManager.getConnection(url, loginName, password);
 //    }
 //    public static void main(String[] args) throws SQLException {
 //        System.out.println(getConnection());
 //    }
 //}
 ​
 package com.how2j.java.Annotation;
 ​
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 ​
 @JDBCConfig(ip = "127.0.0.1", database = "test", encoding = "UTF-8", loginName = "root", password = "admin")
 public class DBUtil {
     static {
         try {
             Class.forName("com.mysql.cj.jdbc.Driver");
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         }
     }
 ​
     public static Connection getConnection() throws SQLException, NoSuchMethodException, SecurityException {
         JDBCConfig config = DBUtil.class.getAnnotation(JDBCConfig.class);
 ​
         String ip = config.ip();
         int port = config.port();
         String database = config.database();
         String encoding = config.encoding();
         String loginName = config.loginName();
         String password = config.password();
 ​
         String url = String.format("jdbc:mysql://%s:%d/%s?characterEncoding=%s", ip, port, database, encoding);
         return DriverManager.getConnection(url, loginName, password);
     }
 ​
     public static void main(String[] args) throws NoSuchMethodException, SecurityException, SQLException {
         Connection c = getConnection();
         System.out.println(c);
     }
 ​
 }

JDBCConfig

 
package com.how2j.java.Annotation;
 ​
 import java.lang.annotation.*;
 ​
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.TYPE;
 ​
 /**
  * @author hjn
  */
 @Target({METHOD,TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @Inherited
 @Documented
 public @interface JDBCConfig {
     String ip();
     int port() default 3306;
     String database();
     String encoding();
     String loginName();
     String password();
 }
 ​

Keywords: Java Annotation annotations

Added by billiondevil on Thu, 13 Jan 2022 16:13:55 +0200