java利⽤反射访问类的私有(private)属性及⽅法
三方协议范本java语⾔中,在⼀个类中,为了不让外界访问到有的属性和⽅法,通常将其设置为private,⽤正常的⽅式(对象名.属性名,对象名.⽅法名)将⽆法访问此属性与⽅法,但有没有其他⽅法可以访问呢?答案是有的,这就是java反射带来的便利。利⽤反射访问类的私有属性及⽅法如下:
1.准备⼀个java类,包含私有属性及⽅法:
公众号注销//Exam.java
public class Exam{
private String field1="私有属性";
public String field2="公有属性";
public void fun1(){
System.out.println("fun1:这是⼀个public访问权限⽅法");
终生难忘
}
private void fun2(){
System.out.println("fun2:这是⼀个private访问权限⽅法");
}
private void fun3(String arg){
System.out.println("fun3:这是⼀个private访问权限且带参数的⽅法,参数为:"+arg);
}
}
将其编译成class,然后删除java源⽂件。注意:删除java源⽂件并⾮必须,但是在实际情况中,我会使⽤的往往不是java源⽂件,⽽是jar 包,⽽jar包中的⽂件都是class,所以为了贴近实际的情况,将Exam.java编译成Exam.class⽂件后,删除Exam.java⽂件,只保留Exam.class⽂件。
2.获取类中属性及⽅法的信息
第⼀步做好后,接下来进⾏第⼆步:获取类中属性及⽅法的信息。对于⼀个class⽂件,⽆法查看源码,
如何获取类中属性及⽅法的信息呢?很⾃然地,我们会想到利⽤java反射功能,得到类的属性、⽅法:
//Test01.java
import flect.Field;
import flect.InvocationTargetException;
import flect.Method;
public class Test01 {
public static void main(String args[]){
Exam e=new Exam(); //初始化Exam实例
System.out.println("获取类中所有的属性:");
Field field[] = e.getClass().getFields();
for(Field f : field){
System.out.println(f);
}
System.out.println("获取类中所有的⽅法:");
Method[] method = e.getClass().getMethods();
阴道炎是什么引起的
for(Method m : method){
System.out.println(m);
}
}
}
运⾏结果如下:
从运⾏结果可以看到,获取的属性中只有field2,⽽获取的⽅法中似乎多了好多类中没有的,但最主要的是,⽆论是属性还是⽅法,都是public声明的,没有得到private声明的属性或⽅法。由此可以推断:
老爸1.声明为private的属性或⽅法⽆法通过这种途径来获取。
2.结果中多出来的⽅法为从Object类中继承来的⽅法。
那么,是不是就没有办法了呢?不是的!我们可以使⽤jdk中的javap命令来突破这个问题:
小品剧本搞笑幽默java -private Exam ; -private 标志表⽰所有的成员都应该显⽰,甚⾄包括私有成员
运⾏结果如下:
炒白芍
此时,可以看到类中所有的属性、⽅法都有了。
3.调⽤Method及Field类中的相关⽅法获取private声明的属性及⽅法
也许你还在为第⼆步中如此⾟苦地得到类中的信息相当不解,其实这是在为这⼀步作铺垫。请看以下代码:Testo2.java
import flect.Field;
import flect.InvocationTargetException;
import flect.Method;
public class Test02 {
public static void main(String args[]){
Exam e=new Exam();
try {
field1 = e.getClass().getDeclaredField("field1");
field2 = e.getClass().getDeclaredField("field2");
field1.tAccessible(true);
System.out.println("field1: "+(e));
汽车安全气囊field1.t(e,"重新设置⼀个field1值");
System.out.println("field1: "+(e));
System.out.println("field2: "+(e));
field2.t(e,"重新设置⼀个field2值");
System.out.println("field2: "+(e));
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
}catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
try {
Method method1 = e.getClass().getDeclaredMethod("fun1");
method1.invoke(e);
Method method2 = e.getClass().getDeclaredMethod("fun2");
method2.tAccessible(true);
method2.invoke(e);
Method method3 = e.getClass().getDeclaredMethod("fun3",String.class); method3.tAccessible(true);
method3.invoke(e,"fun3的参数");
} catch (NoSuchMethodException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
注意以下语句:
field1 = e.getClass().getDeclaredField("field1");
getDeclaredField(String fieldName)中,参数fieldName为属性名,
Method method3 = e.getClass().getDeclaredMethod("fun3",String.class);
getDeclaredMethod(String methodName,Class parameterType)中,第⼀个参数为⽅法名,第⼆个参数为⽅法参数类型,当然在此⽅法中第⼆个参数为可娈参数。
Test02.java运⾏结果如下:
由运⾏结果可知,利⽤反射不但可以访问类的私有属性、⽅法,还可以重新设置私有属性的值,调⽤私有⽅法。