一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
原理介绍
可以不更改源码情况下控制程序,改配置文件
- 反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都实用。
- 加载完类之后,在堆中就产生了一个Class类型的对象,一个类只有一个Class对象,这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构。
作用
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时得到任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理!
缺点
解释执行,执行速度慢
【优化】Method和Field,Constructor对象都有setAccessible方法,此方法可以启动和禁用安全检查,提高反射效率,true取消检查,false执行检查
String classAllPath = "com.hspedu.Car";
//1 . 获取到Car类 对应的 Class对象
//<?> 表示不确定的Java类型
Class<?> cls = Class.forName(classAllPath);
Field[] fields = cls.getFields();
for (Field f : fields) {
System.out.println(f.getName());//名称
}
获取Class类对象的方式
//1. Class.forName
String classAllPath = "com.hspedu.Car"; //通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1);
//2. 类名.class , 应用场景: 用于参数传递
Class cls2 = Car.class;
System.out.println(cls2);
//3. 对象.getClass(), 应用场景,有对象实例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println(cls3);
类加载
- 静态加载:编译时加载相关的类,如果没有则报错,依赖性强
- 动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性![](https://p3-
加载时机
- new 对象
- 子类被加载
- 调用类中静态成员
- 反射
类加载五个阶段
加载阶段
该阶段JVM主要将字节码从不同数据源转化为二进制字节流加载到内存,并生成一个代表该类的java.lang.Class对象
验证阶段
- 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
- 文件格式验证,元数据验证,字节码验证和符号引用验证
- 可以考虑使用Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间
准备阶段
JVM在该阶段对静态变量,分配内存并默认初始化,对应的数据类型的默认初始化值,如 0,null,false。这些变量所使用的内存都将在方法区中进行分配