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);  

    }  

}  

 

你可能感兴趣的:(java)