反射最近学习路线:AOP原理 -> JDK 动态代理 -> java 反射
真是人生无常,大肠包小肠呀~~
定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
这个定义看了n遍,每次都是???(小朋友你是否有很多问号?)
最近又看了书、文章、视频,有了新的理解,码下来。。万一对你有用
知识储备(面试高频):
- 类加载机制
- jvm内存模型
举个简单说下:
Panda p = new Panda(); Konfu k = new Kongfu();
- JVM去磁盘拉取class文件,加载到内存方法区,
- 为该类生成一个对应的Class对象,通过该Class对象就能访问JVM中类
- 调用类的构造方法创建对象,放入堆内存
学习反射一定会看到,创建class对象的三种方式:
- Class.forName("类的权限定");
- 类名.class Panda.class
- 对象.getClass()p.getClass()
那么这个Class类到底是个什么类呢,
官方解释: 类的类
- 上图已经体现出来了,JVM加载类到内存,会为该类生成一个class对象,唯一的
- 这写class对象抽象出来的类型就是Class类
就是你new一堆panda对象p1、p2、 p3,这些对象的类是Panda
jvm加载类的时候给每个类创建了一个class对象,这些对象的类都是Class
- 所以上面三个方法获取的都是类文件在内存中对应的唯一的class实例,接收类型都是Class
- 这个实例中包含类的全部信息,Method、Constructor、Field等
- Class类提供了丰富的API获取类的内部信息
定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
再看这句话我觉就很好理解了,
-
任何一个类,都可以通过类名.class 和 Class.forName("类的权限定名") 获取到JVM创建的该类唯一的Class实例,从而获取类的内部结构和信息
-
任何一个对象,都可以通过对象名.getClass()获取到JVM创建的该类唯一的Class实例,从而获取类的内部结构和信息
-
平时都是根据类new个对象,在堆里面搞事情,操作的都是副本
-
现在是反过来了,通过类或对象直接拿到方法区里类的孤本结构和信息
Class类 API感觉也不太好解释
//获取全部public修饰的构造器 Constructor>[] getConstructors() //获取全部public修饰的方法 Method[] getMethods() //获取全部public修饰的成员变量 Field[] getFields()
- 搞一个类
- 一个私有属性name
- 一个公有属性age
- 一个私有无参构造
- 一个公有有参构造
- 一个无参info方法
- 一个有参info方法
public class Panda {
private String name;
public int age;
private Panda() {}
public Panda(String name) {
System.out.println("有参构造器。。" + name);
}
public void info() {
System.out.println("无参info方法。。");
}
public void info(String name) {
System.out.println("有参info方法。。" + name);
}
class Inner {}
}
- 验证API
- getDeclaredConstructors();获取所有构造函数
- getConstructors(); 获取所有public的构造器
- getMethods();获取所有public的方法
- getDeclaredMethod("name"); 获取指定方法
- getFields(); 获取所有public修饰的属性
- getDeclaredFields();获取所有属性
- getDeclaredField("name");获取指定属性名属性
- getDeclaredClasses(); 获取全部内部类
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {
//通过类名.class反射获取Panda类对应的class实例
Class apiClass = Panda.class;
//获取所有构造函数
Constructor>[] declaredConstructors = apiClass.getDeclaredConstructors();
System.out.println("declaredConstructors:");
for (Constructor> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//public修饰构造函数
Constructor>[] constructors = apiClass.getConstructors();
System.out.println("constructors:");
for (Constructor> constructor : constructors) {
System.out.println(constructor);
}
//所有public方法
Method[] methods = apiClass.getMethods();
System.out.println("methods:");
for (Method method : methods) {
System.out.println(method);
}
//获取指定名称方法 - 无参
System.out.println("declaredMethod:"+apiClass.getDeclaredMethod("info"));
//获取指定名称方法 - 指定参数类型
System.out.println("declaredMethod:"+apiClass.getDeclaredMethod("info",String.class));
//获取所有public修饰的属性
System.out.println("fields:");
Field[] fields = apiClass.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
//获取所有属性
System.out.println("declaredFields:");
Field[] declaredFields = apiClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
//获取指定属性名属性
System.out.println("declaredField:"+apiClass.getDeclaredField("name"));
//获取内部类
Class>[] declaredClasses = apiClass.getDeclaredClasses();
System.out.println("declaredClass:");
for (Class> declaredClass : declaredClasses) {
System.out.println(declaredClass);
}
Class> pandaClassApi$Inner = Class.forName("PandaClassApi$Inner");
System.out.println("declaringClass:"+pandaClassApi$Inner);
System.out.println(pandaClassApi$Inner.getPackage());
System.out.println(pandaClassApi$Inner.getSuperclass());
}



