Java如何訪問private變量


大家都知道private變量是無法訪問的,一編譯就報錯根本無法訪問啊。本文教你如何破解這種限制。


實現的原理是利用了Java的反射機制。


首先定義一個最簡單的類,只有一個私有變量和一個公開的方法。代碼如下:

     class Foo { 
    private String message = "This is a Foo."; 
  
    public void show() { 
        System.out.println(message); 
    } 
} 

正常情況下調用show函數會輸出“This is a Foo.”。下面這段代碼通過setAccessible方法繞過了Java的權限檢測。

Class<foo> fooClass = (Class<foo>) foo.getClass(); 
Field messageField = fooClass.getDeclaredField("message"); 
messageField.setAccessible(true); // 繞過權限檢測!

setAccessble接受一個布爾類型的參數,true表示繞過Java的權限檢測機制,false表示啟用權限檢測。上面調用了setAccessible(true)因此Java在訪問的時候不會檢測權限。這個方法在調用時需要虛擬機的ReflectPermission("suppressAccessChecks")權限。

為什么要訪問private變量呢?因為有時候在串行化的時候必須要訪問私有變量。

訪問私有的方法也是類似。但是這種代碼不宜使用太多,否則會造成程序混亂,無法維護。

下面是完整的代碼:

import java.lang.reflect.*; 
  
  
public class AccessPrivate { 
  
  
    public static void main(String[] argv) throws Exception { 
        // 定義一個測試對象 
        Foo foo = new Foo(); 
  
  
        // 正常情況,測試函數 
        foo.show(); 
  
  
        // 繞過Java權限檢測 
        Class<foo> fooClass = (Class<foo>) foo.getClass(); 
        Field messageField = fooClass.getDeclaredField("message"); 
        messageField.setAccessible(true); // 繞過權限檢測! 
        System.out.println("Foo is hacked!"); 
  
  
        // 修改message變量 
        messageField.set(foo, "This is a Bar."); 
  
  
        // 再次調用測試函數 
        foo.show(); 
    } 
} 
  
  
class Foo { 
    private String message = "This is a Foo."; 
  
  
    public void show() { 
        System.out.println(message); 
    } 
}

另外,還有一種方法,就是通過編寫native庫進行訪問,因為native中所有的訪問都不需要權限檢測。

 


免責聲明!

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



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