介绍

在通常的观点中从对象的外部访问私有变量以及方法是不允许的,但是 Java 反射机制可以做到这一点。

访问私有变量

要想获取私有变量你可以调用 Class.getDeclaredField(String name) 方法或者 Class.getDeclaredFields() 方法。Class.getField(String name) 和 Class.getFields() 只会返回公有的变量,无法获取私有变量。
下面例子定义了一个包含私有变量的类,在它下面是如何通过反射获取私有变量的例子:

  1. public class PrivateObject {
  2. private String privateString = null;
  3. public PrivateObject(String privateString) {
  4. this.privateString = privateString;
  5. }
  6. }
  1. PrivateObject privateObject = new PrivateObject("The Private Value");
  2. Field privateStringField = PrivateObject.class.
  3. getDeclaredField("privateString");
  4. privateStringField.setAccessible(true);
  5. String fieldValue = (String) privateStringField.get(privateObject);
  6. System.out.println("fieldValue = " + fieldValue);

这个例子会输出”fieldValue = The Private Value”。
privateStringField.setAccessible(true) 这行代码,通过调用 setAccessible() 方法会关闭指定类 Field 实例的反射访问检查,这行代码执行之后不论是私有的、受保护的以及包访问的作用域,你都可以在任何地方访问,即使你不在他的访问权限作用域之内。但是你如果你用一般代码来访问这些不在你权限作用域之内的代码依然是不可以的,在编译的时候就会报错。

访问私有方法

访问一个私有方法你需要调用 Class.getDeclaredMethod(String name, Class[] parameterTypes) 或者 Class.getDeclaredMethods() 方法。 Class.getMethod(String name, Class[] parameterTypes) 和 Class.getMethods() 方法,只会返回公有的方法,无法获取私有方法。下面例子定义了一个包含私有方法的类,在它下面是如何通过反射获取私有方法的例子:

  1. public class PrivateObject {
  2. private String privateString = null;
  3. public PrivateObject(String privateString) {
  4. this.privateString = privateString;
  5. }
  6. private String getPrivateString(){
  7. return this.privateString;
  8. }
  9. }
  1. PrivateObject privateObject = new PrivateObject("The Private Value");
  2. Method privateStringMethod = PrivateObject.class.
  3. getDeclaredMethod("getPrivateString", null);
  4. privateStringMethod.setAccessible(true);
  5. String returnValue = (String)
  6. privateStringMethod.invoke(privateObject, null);
  7. System.out.println("returnValue = " + returnValue);

这个例子会输出”returnValue = The Private Value”。
Method.setAcessible(true) 这行代码,通过调用 setAccessible() 方法会关闭指定类的 Method 实例的反射访问检查,这行代码执行之后不论是私有的、受保护的以及包访问的作用域,你都可以在任何地方访问,即使你不在他的访问权限作用域之内。但是你如果你用一般代码来访问这些不在你权限作用域之内的代码依然是不可以的,在编译的时候就会报错。