一、反射的作用
反射在框架学习的使用中特别多,即通过外部文件配置,在不修改源码的情况下来控制程序,这是符合设计模式ocp原则(开闭原则:不修改源码也可以拓展功能)。
二 Java reflection
1、反射机制允许程序在执行期间借助于reflection api取得任何类的内部信息(如成员变量,构造方法,成员方法等)并且能操作对象的属性和方法。
2、加载完类之后,在堆中会生成一个class类型的对象(一个类只有一个class对象),这个对象包含了类的完整的结构信息。
三 Java程序在计算机的三个阶段
1 代码的编译阶段
在一个类创建之后,会通过javac编译生成类.class 字节码文件,这个字节码文件中包含了类的成员属性、构造器、成员方法等
2 class类加载阶段
当创建一个类的时候,这个class字节码文件,会被加载到堆内存中
3 运行阶段 runtime
Java反射机制可以完成
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时得到任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
生成动态代理
反射相关的类:
class class 表示在某个类加载之后,在堆中生成的class类对象
filed 类的成员变量 getfiled 不能得到私有的属性
method 类的方法
constructor 类的构造方法
四、反射的优点和缺点
优点:可以动态的创建和使用对象,使用灵活,没有反射机制框架技术就失去了底层支撑
缺点:使用反射基本是解释执行,对执行的速度有影响。
五、反射的调试
car类
public class car {
public String brand="wulinhongguang";
public int price=12;
public String color="red";
@Override
public String toString() {
return "car{" +
"brand='" + brand + '\'' +
", price=" + price +
", color='" + color + '\'' +
'}';
}
}
主函数
public class class01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
String classpath = "com.csc.reflection.car";
// ? 表示了不确定的类型
Class<?> aClass = Class.forName(classpath);
System.out.println(aClass); // 显示CLASS对象
System.out.println(aClass.getClass());//输出运行类型
//得到包名
System.out.println(aClass.getPackage().getName());
//得到全类名
System.out.println(aClass.getName());
//生成对象实例
car car = (car)aClass.newInstance();
System.out.println(car);
//通过反射获得属性值(用来获取共有属性)
Field brand = aClass.getField("brand");
System.out.println(brand.get(car));
//通过反射给字段赋值
brand.set(car,"benchi");
System.out.println(brand.get(car));
//遍历获得所有的属性
Field[] fields = aClass.getFields();
for (Field f:fields)
System.out.println(f.getName());
}
}
结果
class com.csc.reflection.car
class java.lang.Class
com.csc.reflection
com.csc.reflection.car
car{brand='wulinhongguang', price=12, color='red'}
wulinhongguang
benchi
brand
price
color
六、获取class对象
1 前提:已知一个类的全类名,且该类在类的路径下,可通过class类的静态方法forname()获取,可能会跑出 classnotfoundexception
多用于配置文件,读取类全路径,加载类
2 前提:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高
应用场景:多用于参数传递,比如通过反射得到对应构造器对象。
3 如果知道某个类的实例,那么可以通过调用实例的getclass()方法获取class对象。
应用场景:通过创建好的对象,获取classs对象
4 其他方式
通过类加载器,获取到类的class对象
四种类加载器
七、类加载
1 静态加载:编译时加载相关的类,如果没有则报错,依赖性强,但是对于程序来说,是一个安全性强的程序。 ( new 时候 是静态加载)
2 动态加载:运行时加载所需要的类,如果运行时不用改类,则不会报错,降低了依赖性,但程序存在一定的风险。(其中通过反射加载类对象是动态加载的过程)
类加载时机
1 当创建对象时
2 当子类被加载时
3 调用类中的静态成员时
4 通过反射
加载 (jvm 控制)
就是将类的class文件读入内存,并为之创建一个java.lang.class对象,此过程由类的加载器完成。
连接(jvm 控制)
1 验证
验证字节码文件的安全性
2 准备
对静态变量进行默认初始化,并且分配空间
3 解析
将符号引用转为直接引用
整个过程完成之后,就是类的二进制数据合并到jre当中。(可运行状态)
初始化(程序员控制)
jvm负责对类进行初始化,这里主要指静态成员