Java 反射 调用私有域和方法(setAccessible)

Java 反射 调用私有域和方法(setAccessible)

@author ixenos

 

 

 

AccessibleObject类


Method、Field和Constructor类共同继承了AccessibleObject类,该基类有两个setAccessible方法能在运行时压制Java语言访问控制检查(Java language access control checks),从而能任意调用被私有化保护的方法、域和构造方法

public class AccessibleObjectextends Objectimplements AnnotatedElement

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

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

 

 

两个setAccessible方法设置访问权限


 

static void setAccessible(AccessibleObject[] array, boolean flag)
          使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志的便捷方法。
 void setAccessible(boolean flag)
          将此对象的 accessible 标志设置为指示的布尔值。

 

setAccessible

public static void setAccessible(AccessibleObject[] array,
                                 boolean flag)
                          throws SecurityException
使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志的便捷方法。

首先,如果存在安全管理器,则在 ReflectPermission("suppressAccessChecks") 权限下调用 checkPermission 方法。

如果 flag 为 true,但是不能更改输入 array 的任何元素的可访问性(例如,如果元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。如果发生 SecurityException,对于少于(不包括)发生异常的元素的数组元素,可以将对象的可访问性设置为 flag;对于超出(包括)引发异常的元素的那些元素,则不更改其可访问性。

参数:
array - AccessibleObjects 的数组
flag - 每个对象中的 accessible 标志的新值
抛出:
SecurityException - 如果请求被拒绝。
另请参见:
SecurityManager.checkPermission(java.security.Permission), RuntimePermission

setAccessible

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

首先,如果存在安全管理器,则在 ReflectPermission("suppressAccessChecks") 权限下调用 checkPermission 方法。

如果 flag 为 true,并且不能更改此对象的可访问性(例如,如果此元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。

如果此对象是 java.lang.Class 类的 Constructor 对象,并且 flag 为 true,则会引发 SecurityException。

参数:
flag - accessible 标志的新值
抛出:
SecurityException - 如果请求被拒绝。
另请参见:
SecurityManager.checkPermission(java.security.Permission), RuntimePermission

 

 

示例


 被测类:

 1 class Employee{
 2     private int id;
 3     private String name;
 4     private int age;
 5     
 6     public Employee(){
 7     
 8     }
 9     public Employee(int id, String name, int age){
10         this.id = id;
11         this.name = name;
12         this.age = age;
13     }
14 
15     private void setId(int id){
16        this.id = id;
17     }
18     private int judge(int id){
19         return this.id - id;
20     }
21     private String sayHalo(String name){
22         return "Halo" + name;
23     }
24 }
Employee

 

 测试类:

 1 public class PrivateTest{
 2      public static void main(String[] args){
 3          Employee em = new Employee(1, "Alex", 22);
 4         //获取Class对象
 5          Class<?> emClass =  em.getClass();
 6  
 7          //获取特定的声明了的方法
 8          Method judgeMethod = emClass.getDeclaredMethod("judge", new Class[]{Integer.TYPE});
 9          //setAccessible(boolean flag)使所有成员可以访问,访问之前设置
10          judgeMethod.setAccessible(true);
11  
12          //获取所有声明的方法
13          Method[] allMethods = emClass.getDeclaredMethods();
14          //AccessibleObject.setAccessible(AccessibleObject[] array,
15                                   boolean flag)批量给访问权限
16          AccessibleObject.setAccessible(allMethods, true);
17  
18          //下面就可以通过反射访问了
19          judgeMethod.invoke(em, new Object[]{3});
20  
21          //or...
22          for(Method method : allMethods){
23           ...
24          }
25      }
26 }

 

posted @ 2016-07-24 11:36  ixenos  阅读(7183)  评论(0)    收藏  举报