java源码分析-注解AnnotatedElement接口

概述

在我们讲解注解的运行时处理器时写过这样一段代码:

 //通过Class对象拿到getPersonInfo方法对象Method
Method method = clazz.getDeclaredMethod("getPersonInfo", null);
System.out.println(method.getName());
//根据Method获取到该方法上的注解
MyPersonAnnotation declaredAnnotations = method.getDeclaredAnnotation(MyPersonAnnotation.class);
System.out.println(declaredAnnotations);

​ 其中通过调用Method对象的getAnnotation(MyPersonAnnotation.class)获取该方法上的注解信息,这是典型的通过反射来获取信息的。有个问题,注解和反射是怎么关联上的呢?

​ 其实先要弄明白其中的原理,关键点就在AnnotatedElement接口中。AnnotatedElement接口表示当前运行的虚拟机中一个可以被注解的元素,它提供了一些抽象方法,允许通过反射读取到被注解的元素上的注解信息。

​ 我们看一下这个接口的类图:

通过上图我们知道:

子接口

  • AnnotatedType:被注解的类型;
  • AnnotatedTypeVariable:被注解的类型变量;
  • AnnotatedArrayType:被注解的数组类型;
  • AnnotatedParamerizedType:被注解的参数化类型;
  • AnnotatedWildcardType:被注解的通配类型;
  • GenericDeclaration:通用声明,用于表示声明类型元素,如:类、方法、构造器等;

实现类

  • AccessibleObject:可访问的对象,如:方法、构造器、属性等;
  • Class:类;
  • Constructor:构造器;
  • Executable:可执行的,如构造器和方法;
  • Field:字段属性;
  • Method:方法;
  • Package:包;
  • Parameter:参数;

方法

AnnotatedElement源码如下:

public interface AnnotatedElement {default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {return getAnnotation(annotationClass) != null;}<T extends Annotation> T getAnnotation(Class<T> annotationClass);Annotation[] getAnnotations();default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {/** Definition of associated: directly or indirectly present OR* neither directly nor indirectly present AND the element is* a Class, the annotation type is inheritable, and the* annotation type is associated with the superclass of the* element.*/T[] result = getDeclaredAnnotationsByType(annotationClass);if (result.length == 0 && // Neither directly nor indirectly presentthis instanceof Class && // the element is a classAnnotationType.getInstance(annotationClass).isInherited()) { // InheritableClass<?> superClass = ((Class<?>) this).getSuperclass();if (superClass != null) {// Determine if the annotation is associated with the// superclassresult = superClass.getAnnotationsByType(annotationClass);}}return result;}default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {Objects.requireNonNull(annotationClass);// Loop over all directly-present annotations looking for a matching onefor (Annotation annotation : getDeclaredAnnotations()) {if (annotationClass.equals(annotation.annotationType())) {// More robust to do a dynamic cast at runtime instead// of compile-time only.return annotationClass.cast(annotation);}}return null;}default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {Objects.requireNonNull(annotationClass);return AnnotationSupport.getDirectlyAndIndirectlyPresent(Arrays.stream(getDeclaredAnnotations()).collect(Collectors.toMap(Annotation::annotationType,Function.identity(),((first,second) -> first),LinkedHashMap::new)),annotationClass);}Annotation[] getDeclaredAnnotations();
}

(1)isAnnotationPresent方法

default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {return getAnnotation(annotationClass) != null;}

如果指定类型的注解出现在当前元素上,则放回true,否则将返回false;注意defalut关键字,使得接口中的方法可以有一些默认的实现。

(2)getAnnotation方法:

<T extends Annotation> T getAnnotation(Class<T> annotationClass);

如果在当前元素上存在参数所指定类型(annotationClass)的注解,则返回对应的注解,否则将返回null。

(3)getAnnotations方法

Annotation[] getAnnotations();

用于获取这个元素上的所有注解,并以数组形式放回。如果该元素上没有注解,那么将返回一个长度为0的数组。

调用该方法获取到的数组可以自由地修改,并且不会对返回给其他调用者的数组产生影响。

(4)getAnnotationsByType方法

default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {T[] result = getDeclaredAnnotationsByType(annotationClass);if (result.length == 0 && // Neither directly nor indirectly presentthis instanceof Class && // the element is a classAnnotationType.getInstance(annotationClass).isInherited()) { // InheritableClass<?> superClass = ((Class<?>) this).getSuperclass();if (superClass != null) {// Determine if the annotation is associated with the// superclassresult = superClass.getAnnotationsByType(annotationClass);}}return result;}

获取与该元素相关联的注解。如果没有与此元素相关联的注解,则返回值是长度为0的数组。这个方法与getAnnotation(Class)的区别在于,该方法检测其参数是否为可重复的注解类型(也就是是否被@Repeatable),如果是,则尝试通过“looking through”容器注解来查找该类型的一个或多个注解。

(5)getDeclaredAnnotation方法

default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {Objects.requireNonNull(annotationClass);// Loop over all directly-present annotations looking for a matching onefor (Annotation annotation : getDeclaredAnnotations()) {if (annotationClass.equals(annotation.annotationType())) {// More robust to do a dynamic cast at runtime instead// of compile-time only.return annotationClass.cast(annotation);}}return null;}

获取直接出现在这个元素上的注解。这种方法忽略了继承的注解。如果在此元素上没有直接存在的注解,则返回值是长度为0的数组。

java源码分析-注解AnnotatedElement接口相关推荐

  1. java 源码分析_Java 源代码编译成 Class 文件的过程分析

    原标题:Java 源代码编译成 Class 文件的过程分析 在上篇文章< Java三种编译方式:前端编译 JIT编译 AOT编译 >中了解到了它们各有什么优点和缺点,以及前端编译+JIT编 ...

  2. 【Java源码分析】Java8的HashMap源码分析

    Java8中的HashMap源码分析 源码分析 HashMap的定义 字段属性 构造函数 hash函数 comparableClassFor,compareComparables函数 tableSiz ...

  3. 【Java源码分析】LinkedHashSet和HashSet源码分析

    类的定义 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, ...

  4. Java源码分析之HashMap(JDK1.8)

    一.HashMap概述 HashMap是常用的Java集合之一,是基于哈希表的Map接口的实现.与HashTable主要区别为不支持同步和允许null作为key和value.由于HashMap不是线程 ...

  5. 坦克大战java源码分析(上)

    坦克大战源码分析 一.mytank07.java文件分析 注:至上而下将不懂的语句.结构体含义.代码作用等作出解释: 1.包的使用 package com.haiding.tank_7; 包语句的语法 ...

  6. 【Java源码分析】Java8的ArrayList源码分析

    Java8的ArrayList源码分析 源码分析 ArrayList类的定义 字段属性 构造函数 trimToSize()函数 Capacity容量相关的函数,比如扩容 List大小和是否为空 con ...

  7. python打蛇_hprose for java源码分析-1 初识

    1.1初识 hprose是个开源RPC框架.支持语言 JAVA, C#,C++,Python,PHP等一系列语言.这里着重分析下hprose for java源码. 可以到https://github ...

  8. Java源码分析 AbstractList的迭代器实现(Itr和ListItr)

    Itr和ListItr的简介 AbstractList的有两个内部类实现了迭代器,一个内部类Itr实现了Iterator接口,一个内部类ListItr实现了ListIterator接口,后者其实就是前 ...

  9. java源码分析之ArrayList

    ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素.灵活的设置数组的大小...... 认真阅读本文,我相信一定会对你有帮助.比如为什么Arra ...

  10. Java源码分析:深入探讨Iterator模式

    http://tech.ccidnet.com/art/3539/20060712/618391_1.html java.util包中包含了一系列重要的集合类.本文将从分析源码入手,深入研究一个集合类 ...

最新文章

  1. 设计模式之Protocol实现代理模式
  2. FPGA+DSP SRIO通信(一)——DSP端参数设置(通道)
  3. mysql百万级分页优化
  4. 硬盘的原理以及SQL Server如何利用硬盘原理减少IO
  5. oracle错误:1067进程意外终止
  6. C# DES加密类,16位的加密。
  7. apt-get与dpkg常用命令
  8. 手机端开发深度学习应用
  9. web前端开发初学者十问集锦(3)
  10. zookeeper核心面试问题及解答
  11. Design System 中的 Design Token
  12. apache.commons.beanutils javabean转MapStirng,String对象
  13. 管理感悟:代码审查做哪些事情?
  14. TCP安全测试指南-魔兽3找联机0day
  15. 无权更改wlan网络android,Jami | F-Droid - Free and Open Source Android App Repository
  16. 视频教程-数据结构实战完全手册-C/C++
  17. 51单片机的中断源入口地址是程序存储器空间的5个单元
  18. 渠道商用假量冒充真实用户:开发者求给条活路
  19. Battle Mages (魔法之战,精灵传说)修改器
  20. 华为技术官又出神作,鸿蒙操作系统完整文档笔记现已疯传

热门文章

  1. 珍惜生命,战胜自己,活出精彩
  2. python-字符串练习1
  3. 一种简单的PCB加温电路设计
  4. Datastage数据装载报错:Consumed more than 1000000 bytes looking for record delimiter
  5. 智能手环APP软件开发
  6. 使用Python计算前10000个质数表
  7. 跟任何人都聊得来---最受世界500强企业欢迎的沟通课(一)
  8. 华为智慧屏的四大核心功能
  9. React Native布局实践:开发京东客户端首页(四)——首页功能按钮及控件封装
  10. mysql 常见问题处理_mysql常见问题处理