什么是反射?
讲什么是反射前,先看下Java创建对象的过程
以A类为例,当JVM加载A类时,它首先读取A.class文件到内存,然后,为String类创建一个Class实例并关联起来:Class cls = new Class(A),这个Class实例是JVM内部创建的,如果我们查看JDK源码,可以发现Class类的构造方法是private,只有JVM能创建Class实例,我们自己的Java程序是无法创建Class实例的。所以,JVM持有的每个Class实例都指向一个数据类型。可以看出,要创建一个实例,最关键的就是得到对应的Class对象。只不过对于初学者来说,new这个关键字配合构造方法,实在太好用了,底层隐藏了太多细节,一句 A a = new A();直接把对象返回给你了。
JVM为每个加载的class
及interface
创建了对应的Class
实例来保存class
及interface
的所有信息,获取一个class
对应的Class
实例后,就可以获取该class
的所有信息,通过Class实例获取class
信息的方法称为反射(Reflection)。
反射什么用处?
反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。但通过反射读写字段是一种非常规方法,它会破坏对象的封装。通过反射能过访问和修改类及对象中的所有属性,包括private、final修饰的。
举例:对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。但是有一点仍然很麻烦,就是需要知道完整的包名和类名。
interface Subject {
public abstract void do();
}
class Coding implements Subject {
public void do() {
System.out.println("I am coding!");
}
}
class Banzhuan implements Subject {
public void do() {
System.out.println("I am banzhuaning!");
}
}
class Factory {
public static Subject getInstance(String ClassName) {
Subject s = null;
try {
s = (Subject) Class.forName(ClassName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return s;
}
}
public class TestReflect {
public static void main(String[] args) throws Exception {
Subject s = Factory.getInstance("com.sjj.Coding");
if (s != null) {
s.do();
}
}
}
JDK动态代理使用了反射。
反射的优缺点
优点:
(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
(2)与Java动态编译相结合,可以实现无比强大的功能。
缺点:
(1)使用反射的性能较低 。
(2)使用反射相对来说不安全 。
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性 。