Annotation中annotationType和getClass的区别

原问题介绍:

 //在Java语言中,通过Class.forName(className:String)方法获得的Class对象是Class<?>
 //我怎么才能让它变成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;
 ​
 /**
  * 注解处理器。用于在编译期处理注解生成一个类扫描器。
  *
  * @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
     }
 }

背景介绍:

annotationType()的返回值为 Class<? extends Annotation>类型

 public Class<? extends Annotation> annotationType()
 annotationType方法返回Class<?>泛型,其中?是Annotation的子类

而getClass()的返回值为Class<?>

获取类对象有3种方式

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

    1. DBUtil.class

      1. new DBUtil().getClass()

在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。

注: 准确的讲是一个ClassLoader下,一种类,只会有一个类对象存在。通常一个JVM下,只会有一个ClassLoader。

概述

JDK中获取注解时,返回的都是Annotation类型,如下(截取自JDK源码)

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

当获取到Annotation的实例后,可以通过getClass(从Object继承而来)和annotationType(Annotation接口中的方法)获取到相关的Class。下面阐述一下两者的区别,以下内容为自己的推断,并不是通过翻阅源码获得的结论。

getClass与annotationType对比

测试代码:

 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);
     }
 }
 ​

测试结果:

 

从图中可以看出:

1、getClass()获取到的是一个代理类,通过该代理类,可以获取到类上注解的属性

2、annotationType()获取到的是注解本身,通过该接口可以实现获取注解上的注解,比如:上面通过annotationType可以获取到DBUtil上的JDBCConfig注解信息

推论:

注解是一类特殊的接口,其定义了注解实例(通过getAnnotation获取的类上面的注解信息)能够拥有的属性,它本身也有Class属性。

getAnnotation方法获取到的注解实例有自己的类型,它是JDK利用代理技术实现了注解(注解是一类特殊的接口)的实现类,并不是注解类型本身

参考:

 Annotation中annotationType和getclass的区别_shuxiaohua的博客-优快云博客

附录:

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();
 }
 ​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值