反射

反射

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:代表类的构造器