java中用反射訪問私有方法和私有成員 – JAVA編程語言程序開發技術文章

 java的反射可以繞過訪問權限,訪問到類的私有方法和成員。可能這點會引起安全性的討論。反射的使用幫助解決很多復雜的問題,其運行時的類型檢查,動態調用,代理的實現等,反射為我們寫程序帶來瞭很大的靈活性,很多功能都是基於反射。
    利用反射還可以訪問內部類、匿名內部類的私有屬性。
    用java自帶的java -private 類名 反編譯命令可以查看類的完整定義。(參考think in java)
下面舉例子說明。首先定義一個接口
Java代碼 
public interface Ref {  
    public void f();  


public interface Ref {
 public void f();
}
接口的實現類
Java代碼 
public class RefImpl implements Ref {  
        //實現接口方法  
    public void f() {  
        System.out.println(“public method f()”);  
    }  
      
    void g(String args){  
        System.out.println(“package method g():” + args);  
    }  
      
    private void w(){  
        System.out.println(“private method w()”);  
    }  


public class RefImpl implements Ref {
        //實現接口方法
 public void f() {
  System.out.println(“public method f()”);
 }
 
 void g(String args){
  System.out.println(“package method g():” + args);
 }
 
 private void w(){
  System.out.println(“private method w()”);
 }
}


測試類
Java代碼 
public class TestRef {  
 
    public static void main(String[] args) {  
        Ref ref = new RefImpl();  
        System.out.println(ref.getClass().getSimpleName()); //RefImpl類型  
        ref.f(); //調用接口方法  
//      ref.g();  //向上轉型後實現類添加的方法不能調用  
        if(ref instanceof RefImpl){  
            RefImpl ref1 = (RefImpl)ref;  //類型識別後轉型  
            ref1.g(“zhouyang”);  
//          ref1.w(); //私有方法不能訪問  
        }  
          
        //通過反射調用方法  
        try {  
            Ref ref2 = new RefImpl();  
            Method m = ref2.getClass().getDeclaredMethod(“f”);  
            Method m1 = ref2.getClass().getDeclaredMethod(“g”, String.class);//有參的方法  
            Method m2 = ref2.getClass().getDeclaredMethod(“w”);  
            System.out.println(“==============”);  
            m.invoke(ref);  //調用方法f()  
            m1.invoke(ref, “yangzhou”);  
              
            m2.setAccessible(true);///調用private方法的關鍵一句話  
            m2.invoke(ref);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }   
          
        //java的javap反編譯能夠查看類的信息,-private 開關能夠打開所有信息  
        //javap -private 類名      類必須是編譯成.calss 文件  
          
        //利用反射訪問私有成員,改變私有成員值,但是final域可以訪問不可改變  
        PrivateField pf = new PrivateField();  
//      ps.ss; //私有成員不能訪問  
        //打印原來的成員值  
        pf.print();  
        try {  
            //反射訪問和改變原來值  
            Field[] f = pf.getClass().getDeclaredFields();  
            for(int   i=0;i<f.length;i++){  
                f[i].setAccessible(true);  
                System.out.println(f[i].getType());//打印字段類型     
                System.out.println(f[i].get(pf)); //打印值  
                if(“ss”.equals(f[i].getName())){  
                    f[i].set(pf, “hehe”); //修改成員值  
                }else{  
                    f[i].setInt(pf, 55);  
                }  
                  
            }  
            //重新打印修改後的成員值,final域值不變  
            pf.print();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }   
        /*打印輸出的結果 
         *  RefImpl 
            public method f() 
          &nb

發佈留言