反射概念
在程序的运行过程中,动态地创建对象。
类的全路径:com.zhangsc.reflect.Person
servlet类由我们自己实现,其对象是Tomcat(容器)创建的,创建原理即为反射。
只要知道该类的类名称,就可以使用它的字节码对象创建类的一个对象。对于这个类中的任何一个对象或者属性(包括私有的),我们都可以访问或者使用它。
知道了类的全路径以后,就根据类的全路径获得这个类的字节码文件。
反射打破封装性。
框架的底层支撑。
IDE框架的底层支撑。
servlet创建类的实例。
通常结合注解使用。
字节码文件(*.class)
字节码:.class里的内容
Hello.java--->>Hello.class--->>javaHello
JVM如何执行字节码文件?
1. 把字节码文件加载到内存中去变成Class对象;
2. 通过这个Class对象来创建我们的类的实例。
字节码文件的加载时机?
1. 调用Java命令执行字节码文件的时候;
2. new一个类的对象的时候,Person p = new Person(); ;
3. 调用一个类的静态成员和方法的时候,Math.max(); ;
4. 创建一个子类对象的时候;
5. 通过反射创建一个类的字节码文件对象的时候。
反射是基于什么实现的?
建立在字节码文件上,Class对象。
获取字节码对象:
1. 对象.getClass(); Ep: Class c1 =s.getClass();
2. 类型.class; Ep: Class c2 =Student.class;//int.class也对
3. Class.forName(“”); Ep: Class c3 = Class.forName(“类的全路径名称”);
c1和c2、c3是同一个字节码对象。一个类的字节码对象在程序的一次运行过程中只会有一个。
Hello.java 字节码对象
成员变量/属性 field对象
成员方法 Method对象
构造方法 Constructor对象
对象创建(Constructor)
通过反射创建类的对象的快捷方式:
1.1 获得字节码对象;
Ep: Class clazz1= Class.forName(“com.*.Student”);
1.2 直接用字节码对象创建该类的实例;
Ep: Student obj = (Student) clazz1.newInstance();//无参构造器存在时成功(依赖无参构造器),如果只存在有参的构造器则报错。
通过Constructor来创建类的对象
2.1 获得Constructor对象
Ep: Constructor c = clazz1.getConstructor();//getConstructors();
***快捷键:alt+shift+L
getConstructors();方法只能获得公共的构造方法;
getdeclareConstructors();//获得所有的构造法
获得单个构造方法:
clazz1.getConstuctor(“匹配方法名”);
Ep: Constructors c2 =clazz1.getConstructor(int.class);
2.2 用构造器对象创建该类的对象
Student obj1= (Student) c.newInstance();//带参或无参,强制转换类型
Student obj2 = (Student) c2.newInstance(2);
2.3 私有构造器
private Student(int i, String n){};
Student s = new Student(20, “Jack”);//报错
用构造器对象来创建:
获得单个私有修饰符的构造器对象
Constructor c3 = clazz1.getDeclareConstructor(int.class,String.class);
根据该私有的构造器对象创建这个类的实例
c3.newInstance(20, “James”);//报错
暴力访问
c3.setAccessible(true);
c3.newInstance(20, “James”);
Method对象
Class clazz =Student.class;
Student{privatevoid method2(String){}}
通过字节码对象获得method对象
clazz.getMethod();//getMethods(); 能获得继承过来的方法
clazz.getDeclareMethod();//getDeclareMethods(); 不能获得继承过来的方法
Method m =clazz.getDeclareMethod(“method2”, String.class);
执行方法对象名
m.setAccessible(true);
m.invoke(clazz.newInstance(),“Jack”);
Field对象
同理。
以上是我经验总结,想一起交流和学习Java知识可以加我个人建了个Java架构师学习交流群(788692365
),欢迎更多志同道合的一起交流探讨,也可以加我个人QQ号交流讨论:3164242775