Java反射与注解的深度解析【2020最新版】

大千世界,茫茫人海,相识就是一种缘分。若此篇文章对您有帮助,点个赞或点个关注呗!

一、反射机制

1.1、反射机制的定义

  在运行状态中,对于任意一个类,都能够获取类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;

1.2、反射机制的功能

  1. 在运行时判定任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时判定任意一个类所具有的成员变量和方法
  4. 在运行时调用任意一个对象的方法
  5. 生成动态代理

1.3、反射机制的作用

  1. 动态获取在当前Java虚拟机中的类、接口或者对象信息
  2. 解除两个类之间的耦合性,即在未得到依赖类的情况下,自身应用可以通过编译
  3. 动态依赖注入(即需要某一类对象时动态生成类实例,并设置到被依赖的类中),减少编译时的内存开销

1.4、反射机制的实现原理

  运行时,通过ClassLoader查找到需要调用的类时,就会加载它并根据.class文件内记载的类型信息产生一个与该类相联系的独一无二的Class对象,该Class对象记载了该类的字段,方法等信息,以后jvm要产生该类的实例,就是根据内存中存在的该Class类所记载的信息来进行。

1.5、获取Class对象的三种方式

  1. 使用Class类的静态方法: Class.forName(String name);
  2. 类的语法:T.class,代表了与其匹配的Class对象;
  3. 使用类的实例化的getClass方法: obj.getClass();

1.6、java.lang.Class类

1.6.1、获取类的构造器java.lang.reflect.Constructor

  • public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0;
  • public Constructor getConstructor(Class<?>… parameterTypes) 返回指定public构造器,参数为构造器参数类型集合;
  • public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有;
  • public Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回任意指定的构造器;
  • Constructor重要的方法newInstance(Object …initargs) 实例化类;

1.6.2、获取类的成员变量java.lang.reflect.Field

  • public Field[] getFields() 获取所有的public成员变量;
  • public Field getField(String name) 获取任意public成员变量;
  • public Field[] getDeclaredFields() 获取所有的成员变量;
  • public Field getDeclaredField(String name) 获取任意指定名字的成员变量;
  • public void setAccessible(boolean flag) 设置私有属性是否可访问;
  • Field 重要方法set(Object obj, Object value) 字段设置为指定的新值。

1.6.3、获取类的方法java.lang.reflect.Method

  • public Method[] getMethods() 获取所有的共有方法的集合;
  • public Method getMethod(String name,Class<?>… parameterTypes) 获取指定公有方法;
  • public Method[] getDeclaredMethods() 获取所有的方法;
  • public Method getDeclaredMethod(String name,Class<?>… parameterTypes) 获取任意指定方法;
  • Method重要方法invoke(Object obj ,Object…parmasType) 执行对象的方法,第一个参数为类实例对象,第二个参数:对象方法的参数。

1.6.4、Class类的实例化方法

  newInstance()

1.6.5、获取类的全名

  getName()

1.6.6、获取类的简称

  getSimpleName()

1.6.7、获取类的包名

  getPackage()

1.7、反射的性能分析

反射机制是一种程序自我分析的能力。用于获取一个类的类变量,构造函数,方法,修饰符。
优点: 运行期类型的判断,动态类加载,动态代理使用反射,反射提高了Java程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类;反射是其它一些常用语言,如C、C++、Fortran 或者Pascal等都不具备的。
缺点: 性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多,因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。使用反射会模糊程序内部逻辑:程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。

二、注解

2.1、基本概念

2.1.1、什么是注解

  java提供了一种元程序中的元素关联任何信息或者任何元数据的用途和方法;Annotation是JDK5.0后引入的,它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译检查。

2.1.2、Annotation的成员

  在Annotation类型中以无参的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。

2.1.3、基本规则

  Annotation能被用来为某个程序元素(类,方法,成员变量等)关联任何的信息。Annotation不能影响程序代码的执行,无论增加、删除Annotation,代码都始终如一的执行。

2.2、什么是元数据metadata

2.2.1、根据所起的作用元数据分为

  1. 编写文档:通过代码里标识的元数据文档生成文档;
  2. 代码分析:通过代码里的标识的元数据对代码进行分析;
  3. 编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查;
  • 第一,元数据以标签的形式存在与java代码中;
  • 第二,元数据描述的信息是类型安全的,即元数据内部的字段都是有明确类型的;
  • 第三,元数据需要的编译器之外的工具额外的处理用来生成其他的程序部件;
  • 第四,元数据可以只存在于java源代码级别,亦可以存在于编译之后的class文件内部;

2.3、Annotation和Annotation类型

  jdk5.0的新语法,他的行为十分类似public、final这样的修饰符每个Annotation具有一个名字和成员个数>=0每个成员具有被称为name=value对的名字和值,name=vlaue装载了Annotation的信息。

2.4、注解的分类

根据注解参数个数分类:

  1. 标记注解
  2. 单值注解
  3. 完整注解

根据使用方法和用途分类:

  1. JDK内置系统注解(@Override :用于修饰此方法覆盖了父类的方法、@Deprecated :用于修饰已经过时的方法、@SuppressWarnnings:用于通知编译器禁止特定的编译警告 )
  2. 元注解
  3. 自定义注解

2.5、系统内置标准注解

2.5.1、@Override

  限定重写父类方法,@Override是一个标记注解类型,它被用来做标注方法。它说明了被标注的方法重写了父类的方法,起到了断言的作用。如果用在没有覆盖父类方法的方法时 编译器会给出一个编译错误!

2.5.2、@Deprecated

  标记已过时。同样是是一个标记注解,当一个类型或成员使用@Deprecated修饰的话,编译器将不鼓励使用被标注的程序元素,而且这种修饰带有"延续性"。

2.5.3、@SuppressWarnnings

  抑制编译器警告,常被用于有选择的关闭编译器对类、方法、成员变量等的警告。@SuppressWarnnings不是一个标记注解。它有一个String[]的成员这个成员的值为被禁止的警告名。
常见参数:

  1. deprecation:使用了不赞成使用的类或方法时警告;
  2. unchecked:执行了未检查的转换时警告;
  3. fallthrough:当switch程序块直接通往下一种而没有break时警告;
  4. path:在路径、源文件路径等重有不存在的路径时警告;
  5. serial:当序列化的类上缺少seriaVersionUID定义时的警告;
  6. finally:任何finally字句不能正常完成时的警告;
  7. all:关于以上所有的警告

2.6、元注解meta-annotation

@Target:
作用:用于描述注解的适用范围(即:被描述的注解可以用在什么地方);
取值(ElementType)有:

  • OCNSTRUCTOR:用于描述构造器
  • FIELD:用于描述域
  • LOCAL_VARIABLE:用于描述局部变量
  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述参数
  • TYPE:用于描述类、接口或enum声明

@Retention:
作用:表示需要在什么级别保存该注解信息,用于描述注解的生命周期(即 :被描述的注解在什么范围有效);
取值(RetentionPoicy)有:

  • SOURCE:在源文件中有效(即源文件保留);
  • CLASS:在class文件中有效(即class保留);
  • RUNTIME:在运行时有效(即运行时保留);

@Documented:
作用:Documented是一个标记注解,没有成员,用于描述其他类型的annotation应该被作为被标注的程序成员的公共API,因此可以被javadoc此类的工具文档化。
@Inherited:
作用:Inherited 元注解是一个标记注解,阐述了某个被标记的注解是被继承的。如果一个使用了@Inherited修饰的注解类型被用于一个class,则这个注解将比用于class的子类。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

能先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值