反射
-
reflect 高级特性
-
反射 是框架的灵魂;
-
反射:运行过程中 动态获取类的信息(获取类对象) 和对类进行操作的机制;
-
Java的程序的执行:
-
1 编译 .java .class字节码文件 Student.java->Student.class
-
2 运行 .class文件由类加载器 加载进JVM内存 形式 Class类型 类对象;
-
类对象{成员变量,构造器,方法},每一个成分放大来看,他们都是对象;
-
反射的使用
1,获取类对象
/**
* 1,获取类对象的 三种方式
*
* @throws ClassNotFoundException
*/
private static void method1() throws ClassNotFoundException {
//1, 类名.class
Class<Monkey> monkeyClass = Monkey.class;
//2,对象名.getClass();
Monkey monkey = null;
Class<? extends Monkey> aClass = monkey.getClass();
//3,类的全路径 包名+类名 (常用)
Class<?> aClass1 = Class.forName("com.edu.www.day0509.Monkey");
Class<?> aClass2 = Class.forName("com.edu.www.day0509.Monkey");
//一个类的类对象只有一个
System.out.println(monkeyClass == aClass);
System.out.println(aClass1 == aClass);
System.out.println(aClass1 == aClass2);
}
2,构造器的操作
/**
* 对构造器的操作
*
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private static void method3() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> aClass = Class.forName("com.edu.www.day0509.Monkey");
//Constructor构造器类型
// getConstructors只获取public修饰的构造器对象
Constructor<?>[] constructors = aClass.getConstructors();
System.out.println(constructors.length);
// getDeclaredConstructors 获取本类声明的所有构造器对象
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
System.out.println(declaredConstructors.length);
//getConstructor 只获取public修饰的某个构造器对象
Constructor<?> constructor1 = aClass.getConstructor(String.class);
// Constructor<?> constructor2 = aClass.getConstructor(int.class);
Constructor<?> constructor3 = aClass.getConstructor(int.class, String.class);
Object instance = constructor3.newInstance(11, "猴子3");
System.out.println(instance);
Constructor<?> constructor4 = aClass.getConstructor();
//getDeclaredConstructor 所有修饰符的某个构造器对象
Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class);
//使用构造器创建对象 实例(对象 instance)
Object o = declaredConstructor1.newInstance("猴子1");
System.out.println(o);
Constructor<?> declaredConstructor2 = aClass.getDeclaredConstructor(int.class);
declaredConstructor2.setAccessible(true);
Object o2 = declaredConstructor2.newInstance(12);
System.out.println(o2);
}
创建对象的简易方式
/**
* 创建对象简易方式
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
private static void method4() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class<?> aClass = Class.forName("com.edu.www.day0509.Monkey");
//newInstance直接创建对象 其实是调用无参构造器对象去创建对象
Object o = aClass.newInstance();
System.out.println(o);
}
3,对成员变量的操作
/**
* 对成员变量的操作
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws NoSuchFieldException
*/
private static void method5() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> aClass = Class.forName("com.edu.www.day0509.Student");
Object o = aClass.newInstance();
System.out.println(o);
//Field 成员变量类型
//getFields只获取public修饰成员变量 也包含继承的
Field[] fields = aClass.getFields();
System.out.println(fields.length);
// getDeclaredFields只获取本类声明的成员变量对象
Field[] declaredFields = aClass.getDeclaredFields();
System.out.println(declaredFields.length);
// getField 只获取public修饰成员变量 也包含继承的
// Field id = aClass.getField("id");
// getDeclaredField 根据成员变量的名称 获取本类声明的某个成员变量对象
Field declaredField1 = aClass.getDeclaredField("id");
Field declaredField2 = aClass.getDeclaredField("name");
declaredField1.setAccessible(true);
declaredField2.setAccessible(true);
//赋值的
declaredField1.set(o, 1001);
declaredField2.set(o, "张三");
System.out.println(o);
}
类的加载时机
-
类是按需加载的,用到的时候才加载
-
某个类只会被加载一次的
类加载器
-
核心类加载器(启动类加载器) bootstrapClassLoader
-
本地语言实现的
-
核心包中核心类型
-
-
扩展类加载器 platformClassLoder 平台类加载器
-
扩展类
-
-
应用类加载器 ApplicationClassLoader
-
自定义的类型都是ACL加载
-
-
其他类加载器
双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。
使用双亲委派模型的好处在于Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类,可以正常编译,但是永远无法被加载运行。
2036

被折叠的 条评论
为什么被折叠?



