Java 程序在计算机有三个阶段:
一、反射机制
1. Java Reflection
① 反射机制允许程序在执行期借助于
Reflection API 取得任何类的内部信息
(比如成员变量,构造器,成员方法等),
并能操作对象的属性及方法。[反射在
设计模式和框架底层都会用到]
② 加载完类之后,在堆中就产生了一个
Class 类型的对象(一个类只有一个Class
对象),这个对象包含了类的完整结构信
息,通过这个对象得到类的结构,所以,
形象的称之为:反射
p 对象 ---> 类型 Person 类
Class 对象 cls ---> 类型 Class类
2. Java 反射机制可以完成
① 在运行时判断任意一个对象所属的类
② 在运行时构造任意一个类的对象
③ 在运行时得到任意一个类所具有的成员
变量和方法
④ 在运行时调用任意一个对象的成员变量
和方法
⑤ 生成动态代理
3. 反射相关的主要类
① java.lang.Class:代表一个类,Class 对象
表示某个类加载后在堆中的对象
② java.lang.reflect.Method:代表类的方法,
Method 对象表示某个类的方法
③ java.lang.reflect.Field:代表类的成员变量,
Field 对象表示某个类的成员变量
④ java.lang.reflect.Constructor:代表类的构
造方法,Constructior 对象表示构造器
这些类在 java.lang.reflection
4. 反射优点和缺点
① 优点:可以动态的创建和使用对象(也是框
架底层核心),使用灵活,没有反射机制,
框架技术就失去底层支撑
② 缺点:使用反射级别是解释执行,对执行
速度有影响
5. 反射调用优化-关闭访问检查
① Method 和 Field、Constructor 对象都有
setAccessible() 方法
② setAccessible 作用是启动和禁用访问安全
检查的开关
③ 参数值为 true 表示反射的对象在使用时取
消访问检查,提高反射的效率
参数值为 false 则表示反射的对象执行访问
检查
二、Class 类
① Class 也是类,因此也继承 Object 类
② Class 类对象不是 new 出来的,而是系统
创建的
③ 对于某个类的 Class 类对象,在内存中只有
一份,因为类只加载一次
④ 每个类的实例都会记得自己是由哪个 Class
实例所生成
⑤ 通过 Class 对象可以完整地得到一个类的完
整结构,通过一系列 API
⑥ Class 对象是存放在堆的
⑦ 类的字节码二进制数据,是放在方法区的,
有的地方称为类的元数据(包括 方法代码,变
量名,方法名,访问权限等等)
2. Class 类的常用方法
//1 . 获取到 Car 类 对应的 Class 对象
//<?> 表示不确定的 Java 类型
Class<?> cls = Class.forName(classAllPath);
//2. 输出 cls
System.out.println(cls); //显示 cls 对象, 是哪个类的 Class 对象
System.out.println(cls.getClass());//输出 cls 运行类型 java.lang.Class
//3. 得到包名
System.out.println(cls.getPackage().getName());//包名
//4. 得到全类名
System.out.println(cls.getName());
//5. 通过 cls 创建对象实例
Car car = (Car) cls.newInstance();
System.out.println(car);//car.toString()
//6. 通过反射获取属性 brand
Field brand = cls.getField("brand");
System.out.println(brand.get(car));//宝马
//7. 通过反射给属性赋值
brand.set(car, "奔驰");
System.out.println(brand.get(car));//奔驰
//8 我希望大家可以得到所有的属性(字段)
System.out.println("=======所有的字段属性====");
Field[] fields = cls.getFields();
for (Field f : fields) {
System.out.println(f.getName());//名称
3. 获取 Class 类对象
① 前提:
已知一个类的全类名,且该类在类路径下,可
通过 Class 类的静态方法 forName() 获取,可
能抛出 ClassNotFoundException
实例:
Class cls1 = Class.forName("java.lang.Cat");
应用场景:
多用于配置文件,读取类全路径,加载类
② 前提:
若已知具体的类,通过类的 class 获取,该方
式最为安全可靠,程序性能最高
实例:
Class cls2 = Cat.class;
应用场景:
多用于参数传递,比如通过反射得
到对应构造器对象
③ 前提:
已知某个类的实例,调用该实例的 getClass()
方法获取 Class 对象
实例:
Class clazz = 对象.getClass();//运行类型
应用场景:
通过创建好的对象,获取 Class 对象
④ 其他方式
ClassLoader cl = 对象.getClass().getClassLoader();
Class clazz4 = cl.loadClass("类的全类名");
⑤ 基本数据(int,char,boolean,float,double,
byte,long,short)
按如下方式得到 Class 类对象:
Class cls = 基本数据类型.class
⑥ 基本数据类型对应的包装类,可以通过.TYPE 得到
Class 类对象
Class cls = 包装类.TYPE
4.哪些类型有Class 对象
三、类加载
反射机制是 Java 实现动态语言的关键,也就是
通过反射实现类动态加载
① 静态加载:编译时加载相关的类,如果没有则
报错,依赖性太强
② 动态加载:运行时加载需要的类,如果运行时
不用该类,即使不存在该类,则不报错,降低了
依赖性
2.类加载时机
当创建对象时(new) //静态加载
② 当子类被加载时,父类也加载 //静态加载
③ 调用类中的静态成员时 //静态加载
④ 通过反射 //动态加载
Class.forName("com.test.Cat");
3.类加载过程图
4.类加载各阶段完成任务
5.加载阶段
6. 连接阶段--验证
7. 连接阶段--准备
8. 连接阶段--解析
虚拟机将常量池内的符号引用替换为直接引用的过程
9. 初始化 (Initialization)
四、反射获取类的结构信息
java.lang.Class 类
java.lang.reflect.Field 类
java.lang.reflect.Method 类
java.lang.reflect.Constructor 类
五、通过反射创建对象
六、通过反射访问类中的成员