类加载器
?作用: 负责将.class文件加载到内存中,并为之生成对应的 java.lang.Class 对象。 ???
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或者类初始化??
??? JVM的类加载机制:
?? ???? 全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入 ?? ??? ?父类委托:当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类 ?? ??? ?缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器先从缓存区中搜索该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存储到缓存区
?? ?内置类加载器:
?? ???? Bootstrap class loader:它是虚拟机的内置类加载器,通常表示为null ,并且没有父null ?? ??? ?Platform class loader:平台类加载器可以看到所有平台类 ,平台类包括由平台类加载器或其祖先定义的Java SE平台API,其实现类和JDK特定的运行时类。
?? Classloader中的两个方法:
?? ??? ??? ???? 返回用于委派的系统类加载器:static ClassLoader getSystemClassLoader() ?? ??? ??? ??? ?返回父类加载器进行委派:ClassLoader getParent() ?? ??? ??? ??? ?代码示例: ?? ??? ??? ??? ??
public class ClassLoaderDemo {
public static void main(String[] args) {
//static ClassLoader getSystemClassLoader():返回用于委派的系统类加载器
ClassLoader c = ClassLoader.getSystemClassLoader();
System.out.println(c); //AppClassLoader
//ClassLoader getParent():返回父类加载器进行委派
ClassLoader c2 = c.getParent();
System.out.println(c2); //PlatformClassLoader
ClassLoader c3 = c2.getParent();
System.out.println(c3); //null
}
}
??? System class loader:它也被称为应用程序类加载器 ,与平台类加载器不同。 系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类。 ?? ?类加载器的继承关系: System的父加载器为Platform,而Platform的父加载器为Bootstrap。
反射:
??? 定义:反射是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。
?? ?实例化class类对象的三种方式:
?? ??? ① 类名.class属性(若已知具体的类,通过类的class属性获取,该方法最为可靠安全,程序性能最高)——格式: Class<Student> c1 = Student.class; ?? ?? ? ②对象名.getClass()方法,调用对象的getClass()方法,返回该对象所属类对应的Class对象 ?? ??? ??? ?格式: Student s = new Student(); ??????? Class<? extends Student> c3 = s.getClass();
?? ??? ③ Class.forName(全类名)方法:但该方式可能抛出ClassNotFoundException 使用Class类中的静态方法forName(String className) ?? ??? ??? ?格式:Class<?> c4 = Class.forName("包.类名");
?? ?反射获取构造方法并调用:
?? ??? ?步骤如下:①获取class对象②获取构造函数③根据指定的构造方法创建对象 ?? ??? ??? ?例如:
import java.lang.reflect.Field;
public class ReflectTest {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
PrivateTest pt = new PrivateTest();
Class<PrivateTest>re= PrivateTest.class;
Field field=re.getDeclaredField("name");
field.setAccessible(true);
System.out.println("修改前"+pt.getName());
field.set(pt,"魈");
System.out.println("修改后"+pt.getName());
}
}
?Constructor<T> getConstructor(Class<?>... parameterTypes) ?Constructor<?> con = c.getConstructor(String.class, int.class, String.class);//获取构造函数 ?Object obj = con.newInstance("xxxx", yy, "xx");//根据指定的结构创建对象
?? ?反射获取成员变量并使用:
?? ??? ?方法: ?? ??? ??? ?返回所有公共成员变量对象的数组: Field[] getFields() ?? ??? ??? ?返回所有成员变量对象的数组:Field[] getDeclaredFields() ?? ??? ??? ?返回单个公共成员变量对象: Field getField(String name) ?? ??? ??? ?返回单个成员变量对象:Field getDeclaredField(String name)
??? 步骤:
①获取class对象
②使用对应的方法获取包含field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段
③ 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段
④根据需要修改相应字段
案例:
①利用Class类的forName方法得到File类
②在控制台打印File类的所有构造器
③通过newInstance的方法创建File对象,并创建D:\mynew.txt文件?
????????????????????????????????
Class cl=Class.forName("java.io.File");
//获取File的所有构造器并输出
Constructor[] con = cl.getDeclaredConstructors();
for (Constructor c : con){
System.out.println(c);
}
//获取File的一个构造器
Constructor constructor = cl.getConstructor(String.class);
//用上面得到构造器创建File对象
File file = (File) constructor.newInstance("D:\\mynew.txt");
//获取File的createNewFile方法
Method method = cl.getMethod("createNewFile");
//通过createNewFile方法,File对象,完成文件的创建
method.invoke(file);
对class类的理解
?? ?它是一个java系统运行时的类型标识,保存着运行时类的信息,这些信息跟踪者每个对象所属的类,class本质上可以帮我们获取类中的值,通常和反射配套使用,class可以为我们提供属性、方法、构造器、类名、修饰符等等信息。
|