1.类加载器
A.类加载器
负责将.class文件加载到内在中,并为之生成对应的Class对象。
虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
B.类加载器的组成
Bootstrap ClassLoader 根类加载器
Extension ClassLoader 扩展类加载器
Sysetm ClassLoader 系统类加载器
2.反射
A .JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
B .要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
Class类:
成员变量: Field
构造方法: Constructor
成员方法: Method
C .获取Class文件对象的方式:
a.Object类的getClass()方法 p.getClass()
b.数据类型的静态属性 Person.class
c.Class类中的静态方法
public static Class forName(String className) ;//className是包名.类名
注:一般使用第三种方式,因为第三种返回的是一个字符串,而不是一个具体的类名,这样可以把字符串配置到配置文件中去。
3.通过反射获取构造方法并创建对象过程
A.获取字节码文件:使用Class.forName()方法
static Class< ?> forName(String className) :返回与带有给定字符串名的类或接口相关联的 Class 对象。
B.获取构造方法对象
Constructor< T> getConstructor(Class< ?>… parameterTypes) :返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor< ?>[] getConstructors() :返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Constructor< T> getDeclaredConstructor(Class< ?>… parameterTypes) :返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Constructor< ?>[] getDeclaredConstructors() :返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
C.使用Constructor的newInstance()方法创建对象
T newInstance(Object… initargs) :使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
如果想要获取private构造方法对象,可以对Constructor对象先设置暴力访问
public void setAccessible(boolean flag) throws SecurityException :将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
//获取字节码对象
Class c = Class.forName("cn.zsl.Person") ;
//获取带参构造方法
Constructor con = c.getDeclaredConstructor(String.class,int.class) ;
//创建对象
Object obj = con.newInstance("张三" , 25) ;
System.out.println(obj); //Person [name="张三" , age=25]
4.通过反射获取成员变量过程
A.获取构造方法并创建对象
B.通过字节码Class对象的方法获取成员变量
Field getField(String name) :返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields() :返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Field getDeclaredField(String name) :返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields() :返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
C.通过Filed对象方法将指定对象变量上此Field对象表示的字段值设置为指定的新值
void set(Object obj, Object value) :将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
如果要访问对象的私有变量,也可以使用Field的暴力访问
public void setAccessible(boolean flag) throws SecurityException :将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
//获取字节码对象
Class c = Class.forName("cn.zsl.Person") ;
//获取带参构造方法
Constructor con = c.getDeclaredConstructor() ;
//创建对象
Object obj = con.newInstance() ;
//获取单个成员变量
Field nameField = c.getField("name") ;
Field ageField = c.getField("age") ;
//将指定对象变量上此Field对象表示的字段值设置为指定的新值
nameField.set(obj, "张三");
Integer i= new Integer(25);
ageField.set(obj, i);
System.out.println(obj); //Person [name="张三" , age=25]
5.通过反射获取成员方法
A.获取构造方法并创建对象
B.通过字节码对象获取方法对象
Method getMethod(String name, Class< ?>… parameterTypes) :返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method[] getMethods() :返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method getDeclaredMethod(String name, Class< ?>… parameterTypes) :返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 第一个参数表示方法名,第二个参数表示该方法的参数的class类型,无参方法则不需要第二个参数
Method[] getDeclaredMethods() : 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
C.通过方法对象调用对象的该方法
Object invoke(Object obj, Object… args) :对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。 第一个参数表示要调用的对象,第二个参数表示调用该方法的实际参数。无参方法则不需要第二个参数
// 获取字节码对象
Class c = Class.forName("cn.zsl.Person");
// 获取带参构造方法
Constructor con = c.getDeclaredConstructor();
// 创建对象
Object obj = con.newInstance(null);
// 获取单个成员方法
Method m = c.getMethod("show", String.class);
// 调用对象的该方法,因为不确定会返回什么值,所以返回值用Object接收
Object objString = (String)m.invoke(obj, "张三"); // =obj.show("张三")