提高Java反射速度的方法以及对setAccessable的误解

mercyblitz 写道
ouchxp 写道

再就是在执行反射之前执行field.setAccessible(true); 也可以提高JDK反射效率

这样可以提高效率?这个方法仅仅设置访问标识,让不能访问的成员可以访问。

keating 写道
ouchxp 写道
再就是在执行反射之前执行field.setAccessible(true); 也可以提高JDK反射效率

正如楼上mercyblitz所说,如private变量... 


在此澄清一下对于setAccessable的误解 
先看一个例子 
Java代码   收藏代码
  1. import java.lang.reflect.InvocationTargetException;  
  2. import java.lang.reflect.Method;  
  3.   
  4. public class Main {  
  5.     public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {  
  6.         Method m = A.class.getDeclaredMethod("getName"new Class[]{});  
  7.         System.out.println(m.isAccessible());  
  8.                 //getName是public的,猜猜输出是true还是false  
  9.           
  10.         A a = new A();  
  11.         a.setName("Mr Lee");  
  12.         long start = System.currentTimeMillis();  
  13.         for(int i=0;i<10000000;i++){  
  14.             m.invoke(a, new Object[]{});  
  15.         }  
  16.         System.out.println( "Simple              :" +(System.currentTimeMillis() - start));  
  17.           
  18.         m.setAccessible(true);//注意此处不同  
  19.         long start1 = System.currentTimeMillis();  
  20.         for(int i=0;i<10000000;i++){  
  21.             m.invoke(a, new Object[]{});  
  22.         }  
  23.         System.out.println("setAccessible(true) :"+( System.currentTimeMillis() - start1));  
  24.     }  
  25. }  
  26. class A{  
  27.     private String name;  
  28.     public String getName() {  
  29.         return name;  
  30.     }  
  31.     public void setName(String name) {  
  32.         this.name = name;  
  33.     }  
  34. }  


测试结果 
引用

false 
Simple              :4969 
setAccessible(true) :250 


明显 Accessible并不是标识方法能否访问的. public的方法 Accessible仍为false 
使用了method.setAccessible(true)后 性能有了20倍的提升  

Accessable属性是继承自AccessibleObject 类. 功能是启用或禁用安全检查 

JDK API中的解释 
引用

AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获得字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。 

在反射对象中设置 accessible 标志允许具有足够特权的复杂应用程序(比如 Java Object Serialization 或其他持久性机制)以某种通常禁止使用的方式来操作对象。 

setAccessible 
public void setAccessible(boolean flag) 
                   throws SecurityException 
将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。 


实际上 setAccessible是启用和禁用访问安全检查的开关 ,并不是为true就能访问为false就不能访问 

由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 

你可能感兴趣的:(java,java点滴)