Better

业精于勤荒于嬉

Java反射7-私有成员变量域和方法

Better's Avatar 2017-02-26 Java译文

  1. 1. 获取私有成员变量域
  2. 2. 获取私有的方法
  • Accessing Private Fields
  • Accessing Private Methods

获取私有的成员变量域和方法也是可能的。这甚至不是那么的困难。在单元测试的时候是非常便利的。本文将讲述怎么去获取。
注意:只有当你运行程序作为独立的Java应用的时候比如单元测试才能去获取私有的变量域和方法。如果你在程序运行的时候来做这件事,就需要SecurityManager来处理。

获取私有成员变量域

为了去获取私有的成员变量域你需要使用Class.getDeclaredField(String name),和Class.getDeclaredFields()方法。记得前文说过的Class.getField(String name)Class.getFields()这两个方法只会返回类中定义为public的成员变量域的对象。例子如下:

1
2
3
4
5
6
7
8
public class PrivateObject {

private String privateString = null;

public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
1
2
3
4
5
6
7
8
9
PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);

上述代码将会输出fieldValue = The Private Value,其值是orivateObject对象在创建的时候指定的私有值。
注意到PrivateObject.class.getDeclaredField("privateString")方法,返回的值是当前类私有的成员变量域的对象,而不是是父类的值。
注意到Field.setAcessible(true)这句代码,你设置了它可以通过反射来访问。所以你能访问到私有的(private),受保护的(protected)属性,甚至是包范围类的即使它不是这个类的。当你使用常规的方法去访问它,编译器是不接受的。

获取私有的方法

获取的方法你需要使用Class.getDeclaredMethod(String name, Class[] parameterTypes)Class.getDeclaredMethods()方法。 Class.getMethod(String name, Class[] parameterTypes)Class.getMethods()方法只会返回public的方法。例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class PrivateObject {

private String privateString = null;

public PrivateObject(String privateString) {
this.privateString = privateString;
}

private String getPrivateString(){
return this.privateString;
}
}
1
2
3
4
5
6
7
8
9
10
11
PrivateObject privateObject = new PrivateObject("The Private Value");

Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);

privateStringMethod.setAccessible(true);

String returnValue = (String)
privateStringMethod.invoke(privateObject, null);

System.out.println("returnValue = " + returnValue);

上述代码将打印returnValue = The Private Value,其值是PrivateObject在创建的时候指定的值通过getPrivateString()获取到的。
注意到PrivateObject.class.getDeclaredMethod("privateString"),将返回当前类定义的私的方法而不是父类的私有方法。
注意到Method.setAcessible(true)你是在了直达Method对象的访问属性。所以捏那个访问私有的,受保护的甚至是相同包的方法。常规的方法编译器是不接受的。
原文

This article was last updated on days ago, and the information described in the article may have changed.