反射
反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。
例如idea中输入对象名,可以提示出方法和属性,就是通过反射实现的。
1、反射第一步:加载类,将类的字节码文件加载到内存中,然后获取类的字节码: Class对象,然后去 Class对象中获取其他信息。拿到class对象相当于拿到了类,可以进行类的一系列操作,如:获取类的名字、所在包、创建此类的对象,调用对象的方法,获取对象的属性,调用类方法等…。
2、获取类的构造器:Constructor对象,Constructor对象中封装了类中的构造方法的各种信息。
3、获取类的成员变量:Field对象
4、获取类的成员方法:Method对象
- 反射第一步:加载类,获取类的字节码:class对象
- 类的字节码文件只有一份,所以通过这三种方式获取的对象是同一个。
- 通过类的字节码对象获取类的构造器
存在这样一个类:
获取构造方法
- 获取全部构造器:
- 获取指定构造器,根据形参类型获取:
- 使用构造器初始化对象并返回
存在这样一个类:
通过构造器创建对象
- setAccessible()方法可以令访问控制符失效,破坏了封装性。
- 从字节码对象中获取成员变量
存在这样一个类:
获取成员变量:
对成员变量进行赋值和取值:
- 通过字节码对象获取类的成员方法
存在这样一个Cat类,类中的方法如下:
获取方法
执行方法
反射的作用和应用场景
反射的作用
注解
注解就是java代码里的特殊标记,比如:@Override、@Test等,作用是:让其他程序根据注解信息来决定怎么执行该程序。
注意: 注解可以用在类上、构造器上、方 法上、成员变量上、参数上、等位置处。
自定义注解
说明:
-
属性类型:可以是任意的java类型,包括枚举类型
-
属性名后面一定要加()
-
public(可省略):注解属性的修饰符一定是public,所以可以省略public
-
default(可省略):default后面接默认值,可不写默认值。
-
特殊属性value:
-
如果注解中只有一个value属性,使用注解时,value名称可以不写!!
-
如果注解中既有value属性,又有其他属性,且其他属性有默认值。使用注解时,如果其他属性使用默认值,则value名称也可以不写。
-
实例1:
实例2:
使用注解
实例1:
说明:
- 在使用注解时一定要给没有默认值的属性赋值
- 若属性的类型为数组,为该属性赋值时,使用{}来表示数组。
实例2:
说明:
- 因为@MyTest2的属性只有一个value,所以使用@MyTest2时,属性名value可以省略
注解的原理
对MyTest1注解生成的MyTest1.class进行反编译,可以得到如下
- 注解本质是一个接口,Java中所有注解都是继承了Annotation接口的。
- @注解(…):其实就是一个实现类对象,实现了该注解以及Annotation接口。
元注解
元注解指的是修饰注解的注解
@Target
用法:
实例1:
MyTest3注解只能用在类、接口和成员方法上
@Retention
用法:
实例1:
注解的解析
什么是注解的解析?
- 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。
如何解析注解?
-
指导思想:要解析谁上面的注解,就应该先拿到谁。
-
比如要解析类上面的注解,则应该先获取该类的Class对象,再通过class对象解析其上面的注解。
-
比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。
-
Class、Method、Field、 Constructor都实现了AnnotatedElement接口,它们都拥有解析注解的能力。
解析注解的案例
需求:
- 自定义注解
- 使用注解
- 解析类上的注解
- 解析方法上的注解
注解的应用场景
需求与分析:
- 自定义注解
- 定义若干方法
- 模拟junit程序