1.类的加载
java源码--编译-->java字节码--类的加载-->JVM
当字节码文件加载到内存之后,JVM会为它创建一个Class对象(字节码文件的对象)
2.类的加载时机
类的字节码文件什么时候会被加载???a.创建类的实例。
b.访问类的静态变量
c.调用类的静态方法
d.使用反射方式来强制加载某个类
e.使用到了该类的子类,也会导致该类被加载
f.直接使用java.exe命令运行某个测试类(含有main方法的类)
总而言之:
类的字节码文件什么时候会被加载,当我们用到该类或者该类的子类时!
3.类加载器的作用和分类
类加载器(ClassLoader),将字节码文件加载到JVM的内存中
类加载器的分类:
根类加载器(引导类加载器): 用于加载系统类库(比如:%JAVA_HOME%\bin下的这些类)
扩展类加载器: 用于加载扩展类库(比如:库\lib\ext目录下的类)
应用类加载器: 用于加载我们自定义类的加载器.
4.双亲委派机制
双亲委派机制的作用
1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
双亲委派模型工作工程:1.当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。2.当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成。3.如果Bootstrap ClassLoader加载失败(在\lib中未找到所需类),就会让Extension ClassLoader尝试加载。4.如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。5.如果Application ClassLoader也加载失败,就会使用CustomClassLoader(用户自定义类加载器)去尝试加载。 6.如果均加载失败,就会抛出ClassNotFoundException异常。
//1
Class clas = Dog.class;
System.out.println(clas);//2
Dog dog = newDog();
System.out.println(dog.getClass());//3
Class aClass = Class.forName("day26_classLoader.Dog");
System.out.println(aClass);
反射中万物皆对象:
一个成员方法-->Method类型对象
一个成员变量-->Field类型对象
一个构造方法-->Constructor类型对象
2个常见的单词:
newInstance: 创建对象
invoke: 执行方法/调用方法
反射的语法:
创建对象:
正常语法: 类名 对象名= new构造方法(参数);
反射语法: 类名 对象名=构造方法对象.newInstance();
调用方法:
正常语法: 对象名.方法(参数);
反射语法: 方法对象.invoke(对象名,参数);
setAccessible(true)想要调用私有构造或方法必须设置此参数
获取反射类的构造构造方法:public Constructor getConstructor(Class>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法public Constructor getDeclaredConstructor(Class>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)public Constructor>[] getConstructors() 获取所有的public 修饰的构造方法public Constructor>[] getDeclaredConstructors() 获取所有的构造方法(包含私有的)
根据构造不同的参数区分获取
Class dogClass = Dog.class;
Constructor constructor =dogClass.getConstructor();
Constructor constructorName = dogClass.getConstructor(String.class);
Constructor constructor1 = dogClass.getDeclaredConstructor(String.class,int.class);
//如果构造方法是非public,那么我们需要调用getDeclaredConstructor获取
Constructor con = cc.getDeclaredConstructor(String.class);
//如果是私有构造,那么必须先设置暴力访问权限
con.setAccessible(true);
Object con = con4.newInstance("旺财");
获取反射类的成员返回一个成员变量publicField getField(String name) 获取指定的 public修饰的变量publicField getDeclaredField(String name) 获取指定的任意变量返回多个成员变量publicField[] getFields() 获取所有public 修饰的变量
publicField[] getDeclaredFields() 获取所有的 变量 (包含私有)public voidset(Object obj, Object value)在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值publicObject get(Object obj)返回指定对象obj中,此 Field 对象表示的成员变量的值
//成员变量
Class dogClass = Dog.class;
Field field= dogClass.getField("towname");
System.out.println(field.get(dogClass.newInstance()));
Field name= dogClass.getDeclaredField("name");//必须暴力获取私有
name.setAccessible(true);
System.out.println(name.get(dogClass.newInstance()));
//获取所有成员变量
Field[] fields =dogClass.getFields();
System.out.println(Arrays.toString(fields));
获取成员方法:
返回获取一个方法:public Method getMethod(String name, Class>... parameterTypes)获取public 修饰的方法public Method getDeclaredMethod(String name, Class>... parameterTypes)获取任意的方法,包含私有的
参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型
返回获取多个方法:publicMethod[] getMethods() 获取本类与父类中所有public 修饰的方法public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)
Class dogClass = Dog.class;
Method method= dogClass.getMethod("drink");
Method eat= dogClass.getMethod("eat", String.class);
Method eat1= dogClass.getMethod("eat");
Dog dog=dogClass.newInstance();//调用invoke
method.invoke(dog);
eat.invoke(dog,"😀");
eat1.invoke(dog);//获取私有
Method declaredMethod = dogClass.getDeclaredMethod("testD", String.class);
declaredMethod.setAccessible(true);
declaredMethod.invoke(dog,"xiao");
成员变量:
返回一个成员变量publicField getField(String name) 获取指定的 public修饰的变量
Field ageField= c.getField("age");publicField getDeclaredField(String name) 获取指定的任意变量
Field addressField= c.getDeclaredField("address");
返回多个成员变量publicField[] getFields() 获取所有public 修饰的变量
Field[] fields=c.getFields();//遍历
publicField[] getDeclaredFields() 获取所有的 变量 (包含私有)
Field[] fields=c.getDeclaredFields();for(Field field : fields) {
System.out.println(field);
}public voidset(Object obj, Object value)
在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
nameField.set(obj,23)publicObject get(Object obj)
返回指定对象obj中,此 Field 对象表示的成员变量的值
nameField.get(obj)
nameField,nameField都是通过getField()获得的对象