关于反射好处很多,为开发者提供了很多便利,但任何事情有好有坏,同样反射虽然有点很多,但同时也带来了性能的问题,反射会降低程序的性能。
在说反射的性能问题之前先简单了解下Java的安全性,Java语言是安全的,这是因为它在编译和加载时都会进行安全检查。每次都进行检查,就像我们每次做事前都要准备一下,这样势必会降低我们的执行效率,因此这也是Java程序运行起来相比较C和C++慢的原因。
在Java的反射当中,我们会调用某个方法,对于私有的方法如private修饰的方法,我们需要用到一个方法setAccessible(),将其安全检查关闭我们才能够进行方法的调用,而对于public修饰的方法,我们则不需要调用setAccessible()方法(但也要进行安全检查,能访问是因为权限时public)。那么setAccessible()方法的作用是什么呢?可以理解成Java中的一个安全检查的开关,因为Java是面向对象的语言,提供了属性和方法的封装,因此在程序执行时会进行大量的安全访问检查,判断是否有访问的权限。而setAccessible方法就是这样的一个开关,setAccessible(true)表示关闭安全检查,否则就要进行安全检查。显然,在每次进行安全检查时都会消耗时间,导致性能下降。
关于普通调用方法和反射进行安全检查调用方法以及反射不进行安全检查调用方法的性能比较
笔者写了一段测试代码进行了比较,发现反射的确会降低效率,而进行安全检查时也会降低效率
代码如下:
package com.tiantang.reflectionOfEfficiency;
public class Student {
//定义一个空方法,用于测试
public void show(){
}
}
package com.tiantang.reflectionOfEfficiency;
import java.lang.reflect.Method;
public class TestEfficiency {
public static void main(String[] args) throws Exception {
TestEfficiency t=new TestEfficiency();
t.testPlain(100000000L);
t.testReflect(100000000L);
t.testReflect2(100000000L);
}
/**
* 不通过反射调用方法(普通调用)
* @param times
*/
public void testPlain(long times){
Student student=new Student();
long start=System.currentTimeMillis();
for(int i=0;i<times;i++){
student.show();
}
long end=System.currentTimeMillis();
System.out.println("不通过反射调用方法耗时:"+(end-start)+"ms");
}
/**
* 通过反射调用方法,并进行安全检查
* @param times
* @throws Exception
*/
public void testReflect(long times) throws Exception{
Student s=new Student();
Class<?> clazz=Student.class;
Method m=clazz.getDeclaredMethod("show");
long start=System.currentTimeMillis();
for(int i=0;i<times;i++){
m.invoke(s);
}
long end=System.currentTimeMillis();
System.out.println("通过反射调用方法且进行安全检查耗时:"+(end-start)+"ms");
}
/**
* 通过反射调用方法,不进行安全检查
* @param times
* @throws Exception
*/
public void testReflect2(long times) throws Exception{
Student s=new Student();
Class<?> clazz=Student.class;
Method m=clazz.getDeclaredMethod("show");
m.setAccessible(true);
long start=System.currentTimeMillis();
for(int i=0;i<times;i++){
m.invoke(s);
}
long end=System.currentTimeMillis();
System.out.println("通过反射调用方法不进行安全检查耗时:"+(end-start)+"ms");
}
}
测试结果如下:
从结果中可以明显的发现反射降低了程序的运行效率。
总结:虽然反射会降低运行效率,但是不是意味着我们最好不要使用反射呢?NO!在真正的开发过程中,我们首先应该保证的是开发效率,然后才是运行效率,而用反射开发的框架大大提供了我们的开发效率,所以反射的对我们而言,依旧是一项十分好用的技术。