如何访问一个类的私有属性
这个类是在库函数中所写的,我们不能修改库函数的代码(即代码中添加getter() 方法,修改私有属性的方式是不可用的)。
使用反射的方法
首先,创建一个Exam 实体类。
public class Exam {
// private 成员变量
private String str1 = "private Attribute";
// public 成员变量
public String str2 = "public Attribute";
// private Method
private void fun1(){
System.out.println("the private Method");
}
//public Method
public void fun2(){
System.out.println("the public Method");
}
//private Method With Argument
private void fun3(String arg){
System.out.println("the private Method With Argument");
}
}
来看第一种测试方式
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test01 {
public static void main(String[] args) {
Exam e = new Exam();
System.out.println("获取类中所有属性");
// 通过反射来获取其所有fileds
Field[] fields = e.getClass().getFields();
for (Field field: fields){
System.out.println(field);
}
// 通过反射来获取其所有 methods
System.out.println("获取类中所有方法");
Method[] methods = e.getClass().getMethods();
for (Method method: methods){
System.out.println(method);
}
}
}
--- 这里只获取到了 public 成员变量 str2
//获取类中所有属性
//public java.lang.String Exam.str2
--- 这里只获取到了 public 成员方法 fun2()
//获取类中所有方法
//public void Exam.fun2()
//public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
//public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
//public final void java.lang.Object.wait() throws java.lang.InterruptedException
//public boolean java.lang.Object.equals(java.lang.Object)
//public java.lang.String java.lang.Object.toString()
//public native int java.lang.Object.hashCode()
//public final native java.lang.Class java.lang.Object.getClass()
//public final native void java.lang.Object.notify()
//public final native void java.lang.Object.notifyAll()
//
//Process finished with exit code 0
再来看后面一种测试的方式
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test02 {
public static void main(String[] args) {
Exam e = new Exam();
try {
// 通过属性名来获取对应的
Field field1 = e.getClass().getDeclaredField("str1");
Field field2 = e.getClass().getDeclaredField("str2");
// 将其可见性 设定为true
field1.setAccessible(true);
// filed1 : private Attribute
System.out.println(" filed1 : " +field1.get(e) );
field1.set(e, "重新设定filed1 的值");
// filed1 : 重新设定filed1 的值
System.out.println(" filed1 : " +field1.get(e) );
// filed2 : public Attribute
System.out.println(" filed2 : " +field2.get(e) );
field2.set(e, "重新设定filed2的值");
// filed1 : 重新设定filed1 的值
System.out.println(" filed1 : " +field1.get(e) );
// filed2 : 重新设定filed2的值
System.out.println(" filed2 : " +field2.get(e) );
} catch (NoSuchFieldException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
try {
Method method1 = e.getClass().getDeclaredMethod("fun1");
method1.setAccessible(true);
// the private Method
method1.invoke(e);
Method method2 = e.getClass().getDeclaredMethod("fun2");
method2.setAccessible(true);
//the public Method
method2.invoke(e);
Method method3 = e.getClass().getDeclaredMethod("fun3", String.class);
method3.setAccessible(true);
//the private Method With Argument
method3.invoke(e, "method3的参数");
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InvocationTargetException ex) {
ex.printStackTrace();
}
}
}
//可以看到。这样获访问到了一个类中的私有成员变量,并且也没有对该类进行改变。
同样,你也可以把这些方法封装成一个Util 工具类,通过static (设定为类方法)的方式来通过工具类访问其内部的属性与方法,当然,我要我们调用方法的时候传入属性名(参数名)。