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()
相關文章
相關標籤/搜索