一、类型信息
1. 类型信息
1. 传统的RTTI: Run-Time Type Identification
2. 反射机制
2. Class对象
- 每当编写并且编译了一个新类,就会产生一个Class对象(保存在一个同名的.class文件中)
- 为了生成这个类的对象,运行这个程序的jvm,会使用叫做“类加载器”的子系统
- 所有的类都是在对其第一次使用时,动态加载到JVM中:构造器也是类的静态方法,即使在构造器之前并没有使用static关键字
- 当程序创建第一个对类的静态成员的引用的时候,就会加载这个类
- 因此,java程序在它开始运行之前,并非被完全加载,其各个部分是在必需的时候才能加载
1. 类加载器首先检查这个类的Class对象是否已经加载
2. 如果尚未加载,默认的类加载器就会根据类名查到.class文件
3. 在这个类的字节码被加载时,它们接受验证,以确保其没有被破坏,并且不包含不良代码
4. 一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象
- ClassForName(""): 根据类名获得一个类的Class对象的引用, 全限定包名
- getClass(): 根据具体的实例获得一个类的Class对象的引用
- 如果获得了Class对象的引用,就可以用来创建其对象
获取到了类的 Class对象,可以获取到这个类的很多信息
- 类的子类,父类,接口
- 类中的方法,类的构造器
- 类上的注解,类名
package com.erick;
import java.lang.annotation.Annotation;
public class Demo07 {
public static void main(String[] args) {
method01();
}
private static void method01() {
try {
Class<?> demo01 = Class.forName("com.erick.Demo01");
Object obj = demo01.getDeclaredConstructor().newInstance();
System.out.println("names: " + obj.getClass().getSimpleName());
Annotation[] annotations = demo01.getAnnotations();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 获取 Class对象的三种方式
1. 加载: 由类加载器执行,查找字节码。 通常在classpath所制定的路径中查找,但这并非是必须的
并从这些字节码中创建一个Class 对象
2. 链接: 在链接阶段,将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类
创建的,对其他类的所有的引用
3. 初始化: 如果该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化块
初始化被延迟到了对静态方法(构造器隐式的静态的),或者非常数静态域进行首次引用才执行
package com.erick;
import java.util.ArrayList;
public class Demo07 {
public static void main(String[] args) {
method01();
}
private static void method01() {
try {
Class<?> clazz = Class.forName("com.erick.Demo01");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ArrayList<String> list = new ArrayList<>();
Class<? extends ArrayList> aClass = list.getClass();
Class<ArrayList> arrayListClass = ArrayList.class;
}
}
4. 泛化的Class引用
- Class引用表示的就是它所指向的对象的确切类型,而该对象就是Class类的一个对象
- 在这里用到了泛型语法
- Class 对象引入了泛型
ArrayList<String> list = new ArrayList<>();
Class<? extends ArrayList> aClass = list.getClass();
ArrayList arrayList = aClass.getDeclaredConstructor().newInstance();
二、反射
- Class类和java.lang.reflect类库一起对反射的概念进行了支持
- 类库包含 Field, Method, Constructor类,每个类都实现了Member接口
- 这些类型的对象是JVM在运行时创建的,用来表示未知类中对应的成员
- 在运行时打开和检查 .class文件
三、空对象
四、接口和类型信息
- 在代码中,尽量不要去使用反射去获取别人类中的private或者protected的方法
- 如果出现问题,那就是自讨苦吃