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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值