反射
反射
Java程序中,所有的对象都有两种类型:编译时类型和运行时类型,很多对象的编译时类型和运行时类型不一致。
多态: Object obj = new String("hello");
当程序完全知道编译时和运行时的完成信息,这种情况下不需要使用反射
当程序需要靠运行时信息来调用对象和类的真实信息时,必须要用到反射
反射的定义
Reflection 是被视为动态语言的关键,反射机制允许程序在运行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象内部的属性和方法。
利用反射,我们可以直接对运行时类中私有的方法和属性进行操作(暴力反射)
从我们作为开发者角度来讲,我们开发中主要是完成业务代码,对于相关对象和方法的调用都是确定的,所以我们基本不会用到反射
因为反射的特性是动态性(可以在运行时动态获取对象所属的类,动态的调用相关的方法),所以在设计框架时会使用大量的反射
框架 = 注解 + 反射 + 设计模式
反射的问题
通过反射,可以调用类中私有的结构,这与对象的封装性有冲突
封装性体现的是是否建议我们调用内部api的问题
而类被加载到内存中,我们当然是有能力去调用
Class类
Class类的本质其实是.java文件经过编译后的.class文件加载(类的加载器)到内存中(存放在方法区),对应的结构即为Class的一个实例
Class clazz = Person.class;//运行时类
注:此时不使用class作为对象名,是因为class为关键字不能作为对象名
Class是反射的源头
获取Class的三种方法
//通过Person类获取Class
Class clazz1 = Person.class;
//通过对象.getClass()返回其类的Class
User user = new User();
Class class2 = user.getClass();
//通过Class的静态方法forName(String className)返回一个Class
String className = "com.xiaobai.test.User"; //这里的参数应为全类名
Class class3 = Class.forName(className);
注:同一个类只有一个Class类的对象,也就是说,运行时类在内存中缓存起来,在整个执行期间,只会加载一次
反射相关的API
java.lang.Class :代表一个类
java.lang.reflectMethod:代表类的方法
java.lang.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器