在现在很多比较流行的框架中都用到了反射,反射这个概念,可能会让我们联系到光学里的反射,不过Java中的,确切地说是计算机科学中的反射和光学中的反射有点区别,它指一类应用能够通过采用某种机制实现对自身的描述和检测,并能根据自身行为的状态和结果,调整和修改应用所描述的状态和相关语义。这么讲可能有点抽象,来点代码吧。
public static void main(String[] args) {
String test = "test";
System.out.println(test.getClass());
}
这是我们写代码过程中经常遇到的,获取某个对象的所属类,其实这是最基本的反射。这也和定义中的叙述相吻合,test字符串通过getClass()这个方法得知自身所属类,这属于对自身一种描述和检测。
下面来点稍微高级点的。先讲讲我们编码过程一个常见的知识,如果一个类中的方法定义成private,通常在我们在这个类之外就不能调用它了。但是反射可以!同样先来代码吧。
public class ReflectTest {
private String attribute1;
private String attribute2;
public String getAttribute1() {
return attribute1;
}
public void setAttribute1(String attribute1) {
this.attribute1 = attribute1;
}
public String getAttribute2() {
return attribute2;
}
public void setAttribute2(String attribute2) {
this.attribute2 = attribute2;
}
private void testString(String s) {
System.out.println(s);
}
}
先定义一个类ReflectTest,里面有个两个私有属性和一个私有方法。通常情况下,testString方法只能在RelectTest这个类中使用,下面将示范如
何在其他类中调用testString方法,代码如下:
public static void main(String[] args) {
Class<?> c = null;
try {
//获取ReflectTest类
c = Class.forName("ReflectTest");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class[] p = {String.class};
try {
Object object = c.getConstructor().newInstance();
//获取相应方法
Method method = c.getDeclaredMethod("testString",p);
//设置testString方法权限
method.setAccessible(true);
//调用方法
method.invoke(object,"test reflect ok!");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
代码中先通过类名获取到这个类,然后通过这个类生成实例并获取到testString这个方法, 设置这个方法的权限,最后调用这个方法,运行结果如下:
test reflect ok!
Process finished with exit code 0
以上讲的都是反射比较基本的用法,算是对反射有个最基本的认识,反射的深入理解应该结合源码来说明,这里不加说明。下面是反射和new关键字的一些总结
1.使用反射必须保证这个类已经被加载并且连接了。使用new关键字,这个类可以被加载了也可以没有被加载。
2.new 关键字是强类型的,效率较高;反射是弱类型的,效率比较低
3.反射提供了一种比较灵活的方式创建对象、获取对象信息,spring的AOP、动态代理都是基于反射的。
以上,不足之处还望指出。