转自: 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); } }