一.类加载器 当程序要使用某个类时,如果类还没有被加载到内存中,JVM则会通过类的加载器,类的连接,类初始化这三个步骤来完成类的加载,熟称:类加载或类初始化 类的加载:将.class文件读入内存,并为该文件创建一个java.lang.Class对象,任何类被加载时,系统都会为之建立一个这样的对象 类的连接:1.验证阶段->验证加载类内部结构是否正确,并协调与其它类的关联。 2.准备阶段->分配内存空间,并设置默认值 3.解析阶段->将类的二进制的符号引用替换成为直接引用 类的初始化:主要是对变量进行初始化 步骤:若没加载类和连接,则加载连接,若父类没有加载,则加载连接,若类中有初始化语句,则执行这些语句 初始化类的时机:创建类,调用类的方法,访问类的成员,用反射来强制创建某个类或接口对应的java.lang.Class对象,使用某个类的子类,java.exe运行某个类 类加载器的机制:全盘负责->加载一个Class时,该Class所依赖和引用的其它Class也由该加载器载入,除非显示的说明用另一个加载器来完成 父类委托->加载一个Class时,先让父类试图加载该Class,父类无法完成时,才试图从自己的路径中加载 缓存机制->所有加载过的Class都会放在缓存区中,程序使用某一个Class对象时,先从缓存区中找Class,只有缓存中不存在Class 时,系统才会调用该类的二进制数据,生成Class对象,存到缓存区中 二.反射 Java反射机制:在运行时去获取一个类的变量和方法信息,用得到的这些信息去创建该对象,调用方法的机制。 1.获取Class类的对象:通过反射去使用一个类,首先要获取该类的字节码文件(xxx.class 由xxx.java编译出来的)去获得该类的Class对象 使用类的class属性来获取该类对应的Class对象, 调用对象的getClass()方法来获取所属类的Class对象 使用Class类的静态方法:forName(String className),完整包名路径名
package twelve;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author KuKaFei.Hai
* @date 2020/4/24 : 16:10
* 反射得到类的对象,要使用类的相关成员变量,成员方法等,必须要分别对成员变量和成员方法进行获取,并不能像对象去调用
* Class ->构造方法-->newInstance-->对象->getConstructor->使用构造方法,调用构造函数,创建对象
* Class ->构造方法-->newInstance-->对象->getDeclaredField->使用获取成员变量的方法,调用成员变量
* Class ->构造方法-->newInstance-->对象->getDeclaredMethods->使用获取成员方法,调用成员方法
* <p>
* 暴力反射
* nullConst.setAccessible(true);
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//类的.class属性来获得该类的Class对象
Class<Student> stuClassA = Student.class;
//调用对象的getClass()方法来获取所属类的Class对象
Student stup = new Student();
Class<? extends Student> stuClassB = stup.getClass();
//使用Class类的静态方法:forName(String className),完整包名路径名
Class<?> stuClassC = Class.forName("twelve.Student");
//判断三种不通的方式所指向的是否是同一个Class文件
boolean flag1 = stuClassA == stuClassB;
boolean flag2 = stuClassA == stuClassC;
boolean flag3 = stuClassB == stuClassC;
System.out.println(flag1 && flag2 && flag3);
System.out.println("-----------------------");
//getConstructors() 只能获取公有的
Constructor<?>[] constructors = stuClassC.getConstructors();
for (Constructor<?> con : constructors) {
System.out.println(con);
}
System.out.println("------------------------");
// getDeclaredConstructors() 私有,公共的,全获取
Constructor<?>[] declaredConstructors = stuClassC.getDeclaredConstructors();
for (Constructor<?> con : declaredConstructors) {
System.out.println(con);
}
//获取某个特定的构造函数
Constructor<?> nullCon = stuClassC.getConstructor();
//利用构造方法创建一个实例
Object refStuA = nullCon.newInstance();
System.out.println(refStuA);
System.out.println("------------");
Constructor<?> con3 = stuClassC.getConstructor(String.class, int.class, String.class);
Object stuc = con3.newInstance("李某", 28, "江西九江");
System.out.println(stuc);
System.out.println("-------------");
/**
* 暴力反射 获得的私有方法等,不能直接调用,需要使用
* setAccessible(true) 打开访问权限,才可以调用生成对象
*/
//获得私有构造器
Constructor<?> priveteCont = stuClassC.getDeclaredConstructor(String.class);
//打开访问权限
priveteCont.setAccessible(true);
//私有构造器,获得对象
Object priStu = priveteCont.newInstance("王某");
System.out.println(priStu);
System.out.println("-----------");
/**
* 反射获取成员变量
*
*/
//获取所有的成员变量
Field[] decFiles = stuClassC.getDeclaredFields();
for (Field f : decFiles) {
System.out.println(f);
}
//获取单个成员变量
Field name = stuClassC.getDeclaredField("name");
Field age = stuClassC.getDeclaredField("age");
Field addrss = stuClassC.getField("addrss");
//获取构造器,生成对象,才对能获取的成员变量,赋值
Constructor<?> nullConst = stuClassC.getConstructor();
//生成实例
Object nullObj = nullConst.newInstance();
//暴力破解,访问私有属性
//nullConst.setAccessible(true);
// 获取到的成员对象,调用set()方法,给实例nullObj,赋值"xxxx"
name.setAccessible(true);
name.set(nullObj, "周某");
age.set(nullObj, 48);
addrss.set(nullObj, "江西九江");
System.out.println(nullObj);
System.out.println("------------------------");
/**
* 反射获取成员方法
* Class ->构造方法-->newInstance-->对象->getDeclaredMethods->使用获取成员方法,调用成员方法
*/
Method[] decMethods = stuClassC.getDeclaredMethods();
//包括类中的所有成员方法和接口,继承来的所有的方法
for(Method me :decMethods){
System.out.println(me);
}
System.out.println("==========================================");
//获取私有的成员方法
Method studyPri = stuClassC.getDeclaredMethod("studyPri");
//暴力破解访问权限
studyPri.setAccessible(true);
studyPri.invoke(nullObj);
//获取公有无参方法
Method studyA = stuClassC.getDeclaredMethod("studyA");
Method studyB = stuClassC.getDeclaredMethod("studyB", String.class);
studyA.invoke(nullObj);
studyB.invoke(nullObj,"周某某");
}
}