java中用反射访问私有方法和私有成员[转]

转自: http://zhouyangchenrui.iteye.com/blog/470521

    java的反射可以绕过访问权限,访问到类的私有方法和成员。可能这点会引起安全性的讨论。反射的使用帮助解决很多复杂的问题,其运行时的类型检查,动态调用,代理的实现等,反射为我们写程序带来了很大的灵活性,很多功能都是基于反射。 
    利用反射还可以访问内部类、匿名内部类的私有属性。 
    用java自带的java -private 类名 反编译命令可以查看类的完整定义。(参考think in java) 
下面举例子说明。首先定义一个接口 

public interface Ref {  
    public void f();  
}  

接口的实现类

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()");  
    }  
}  

测试类:

import java.lang.reflect.Field;
import java.lang.reflect.Method;

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() 
            package method g():zhouyang 
            ============== 
            public method f() 
            package method g():yangzhou 
            private method w() 
            ss:nihao 
            count:1 
            num:47 
            class java.lang.String 
            nihao 
            int 
            1 
            int 
            47 
            ss:hehe 
            count:55 
            num:47 
         */  
      
    }  
}  
  
class PrivateField {  
    private String ss = "nihao";  
    private int count = 1;  
    private final int num = 47;  
      
    void print(){  
        System.out.println("ss:" + ss);  
        System.out.println("count:" + count);  
        System.out.println("num:" + num);  
    }  
}  

 

posted on 2013-07-25 21:38  在旅途  阅读(735)  评论(0编辑  收藏  举报

导航