JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。“反”,就要先了解“正”。一般先知道类,然后通过类产生实例化对象,而反射是通过对象找类。
反射机制一般用在框架类代码编写,所以平时在框架基础上开发特性时一般用的比较少。
Class类是反射机制的基础。反射机制是跟spring 和bean的基础。
优点:
使得系统框架具有高度的灵活性和扩展性。(反射是框架设计的灵魂)
缺点:
1)可能引入性能问题
2)使得程序的逻辑不再直观
3)可移植性,因为反射依赖于java本身框架支持,如果移植到类似andriod平台可能就支持的不好。
4)多线程高并发环境下可能引入问题。
所以,任何语言特性都不能滥用,要考虑是否需要另一种更合适的语言。
很多设计模式使用java的反射机制实现非常方便,甚至连客户端的代码都不需要修改。例如下面的简单工厂的实现,不需要停运行环境,只需要改配置文件即可实现不同类的生产。
import java.io.*;
import java.lang.reflect.InvocationTargetException;
class Animal {
void MyPrint(String str) {
System.out.println(str);
}
void Show() {
MyPrint("I'm Animal");
}
}
class Dog extends Animal {
@Override
void Show() {
MyPrint("I'm Dog");
}
}
class Cat extends Animal {
@Override
void Show() {
MyPrint("I'm Cat");
}
}
class AnimalFactory {
private static AnimalFactory factory = new AnimalFactory();
private AnimalFactory() {}
static AnimalFactory GetInst() {
return factory;
}
Animal Create() {
try {
// 替换成你自己的文件路径
File file = new File("C:\\Users\\Administrator\\IdeaProjects\\demo2\\src\\test.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String animalName = reader.readLine();
Class<?> clazz = Class.forName(animalName);
Object obj = clazz.getDeclaredConstructors()[0].newInstance();
reader.close();
return (Animal) obj;
// 忽略异常处理
} catch (IOException e) {
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
} catch (ClassNotFoundException e) {
}
return null;
}
}
你可以在执行过程中修改test.txt文件,可以看到工厂创建的类在及时地变化,而不需要重新编译代码,甚至不需要重新启动程序。
I'm Cat
I'm Cat
I'm Cat
I'm Dog
重要的是要意识到反射没有什么魔力。当你使用反射与未知类型的对象交互时,JVM 将查看该对象,并看到它属于特定的类(就像普通的 RTTI)。在对其执行任何操作之前,必须加载 Class 对象。因此,该特定类型的 .class 文件必须在本地计算机上或通过网络对 JVM 仍然可用。因此,RTTI 和反射的真正区别在于,使用 RTTI 时,编译器在编译时会打开并检查 .class 文件。换句话说,你可以用“正常”的方式调用一个对象的所有方法。通过反射,.class 文件在编译时不可用;它由运行时环境打开并检查。
反射机制的应用场景:序列化,文档提取(见类方法提取器)。
示例代码仓库:
网友评论