反射
反射是什么?
反射是动态语言的关键,反射机制的存在允许程序在执行期间通过API获取任何类的内部信息,并能够直接操作任意对象的内部属性和方法。
反射提供的功能
- 在运行时判断任意一个对象是哪个类的
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类的属性和方法
- 运行时获得泛型信息
- 运行时调用任意一个对象的属性和方法
- 运行时处理注解
- 生成动态代理
有了一个Person类之后,通过反射实现创建类对象、调用指定对象的属性和方法
public void test(){
// 正常的创建对象
Person person = new Person();
//通过反射创建对象
Class clazz = Person.class;
Constructor cons = clazz.getCostructor(String.class,int.class);// 拿到带参构造器
Object obj = cons.newInstance("lzc",12); // 通过构造器实例化类对象
Person p = (Person)obj;
sout(p.toString());
//正常的调用属性和方法
int age = person.age;
person.setAge(10);
//通过反射调用属性和方法
Field age = clazz.getDeclaredField("age");
age.set(p,10);
Method show = clazz.getDeclaredMethod("show");
show.invoke(p);
//一般来说私有方法和属性、构造器是不允许外部访问的,通过反射可以访问
Constructor cons1 = clazz.getDeclaredConstructor(String.class);
cons1.setAccessible(true);
Person p1 = (Person)cons1.newInstance("Jerry");
//私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1,"lzc");
sout(p1); //正常是通过对象的set方法来设置,此处直接操作属性
//私有方法
Method showNation = clazz.getDeclaredMethod("showNation",String.class);
showNation.setAccessible(true);
showNation.invoke(p1,"中国");
}
答:一般是直接用new的方式创建对象,不排除有些时候不确定所需要的对象是什么就可以用到反射。
比如后台服务器跑起来了,前端发来请求,可能是登录也可能是注册,此时就需要根据请求在服务器已经运行的情况下创建对应的对象,此时就需要用到反射。
答:不矛盾,封装性主要是建议你去使用哪些方法,不建议去使用哪些方法或属性。反射解决的其实就是你一定要使用这些封装不建议使用的方法或属性的时候,能不能实现的问题。总有些情境会必须用到这些封装不建议的东西,这时候就需要反射了。两者的初衷就是不一样的。
关于java.lang.Class的理解
- 类的加载过程
-
javac 命令以后,会生成字节码文件(.class文件),此过程为编译过程。
-
接着通过java命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中,此过程就叫做类的加载。加载到内存中的类就是运行时类。运行时类就是Class的一个实例。(万事万物皆对象,这也就解释了Class clazz = Person.class这行代码)
换句话说,Class的实例就对应着一个运行时类,下篇文章将详细展开来讲。
-