java源码分析-注解AnnotatedElement接口
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接口相关推荐
- java 源码分析_Java 源代码编译成 Class 文件的过程分析
原标题:Java 源代码编译成 Class 文件的过程分析 在上篇文章< Java三种编译方式:前端编译 JIT编译 AOT编译 >中了解到了它们各有什么优点和缺点,以及前端编译+JIT编 ...
- 【Java源码分析】Java8的HashMap源码分析
Java8中的HashMap源码分析 源码分析 HashMap的定义 字段属性 构造函数 hash函数 comparableClassFor,compareComparables函数 tableSiz ...
- 【Java源码分析】LinkedHashSet和HashSet源码分析
类的定义 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, ...
- Java源码分析之HashMap(JDK1.8)
一.HashMap概述 HashMap是常用的Java集合之一,是基于哈希表的Map接口的实现.与HashTable主要区别为不支持同步和允许null作为key和value.由于HashMap不是线程 ...
- 坦克大战java源码分析(上)
坦克大战源码分析 一.mytank07.java文件分析 注:至上而下将不懂的语句.结构体含义.代码作用等作出解释: 1.包的使用 package com.haiding.tank_7; 包语句的语法 ...
- 【Java源码分析】Java8的ArrayList源码分析
Java8的ArrayList源码分析 源码分析 ArrayList类的定义 字段属性 构造函数 trimToSize()函数 Capacity容量相关的函数,比如扩容 List大小和是否为空 con ...
- python打蛇_hprose for java源码分析-1 初识
1.1初识 hprose是个开源RPC框架.支持语言 JAVA, C#,C++,Python,PHP等一系列语言.这里着重分析下hprose for java源码. 可以到https://github ...
- Java源码分析 AbstractList的迭代器实现(Itr和ListItr)
Itr和ListItr的简介 AbstractList的有两个内部类实现了迭代器,一个内部类Itr实现了Iterator接口,一个内部类ListItr实现了ListIterator接口,后者其实就是前 ...
- java源码分析之ArrayList
ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素.灵活的设置数组的大小...... 认真阅读本文,我相信一定会对你有帮助.比如为什么Arra ...
- Java源码分析:深入探讨Iterator模式
http://tech.ccidnet.com/art/3539/20060712/618391_1.html java.util包中包含了一系列重要的集合类.本文将从分析源码入手,深入研究一个集合类 ...
最新文章
- 设计模式之Protocol实现代理模式
- FPGA+DSP SRIO通信(一)——DSP端参数设置(通道)
- mysql百万级分页优化
- 硬盘的原理以及SQL Server如何利用硬盘原理减少IO
- oracle错误:1067进程意外终止
- C# DES加密类,16位的加密。
- apt-get与dpkg常用命令
- 手机端开发深度学习应用
- web前端开发初学者十问集锦(3)
- zookeeper核心面试问题及解答
- Design System 中的 Design Token
- apache.commons.beanutils javabean转MapStirng,String对象
- 管理感悟:代码审查做哪些事情?
- TCP安全测试指南-魔兽3找联机0day
- 无权更改wlan网络android,Jami | F-Droid - Free and Open Source Android App Repository
- 视频教程-数据结构实战完全手册-C/C++
- 51单片机的中断源入口地址是程序存储器空间的5个单元
- 渠道商用假量冒充真实用户:开发者求给条活路
- Battle Mages (魔法之战,精灵传说)修改器
- 华为技术官又出神作,鸿蒙操作系统完整文档笔记现已疯传