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 方法。

如果 flagtrue,但是不能更改輸入 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 方法。

如果 flagtrue,並且不能更改此對象的可訪問性(例如,如果此元素對象是 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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM