Java反射-私有属性和方法

尽管广泛认知是,实际能够经过反射访问其余类的私有属性和方法。它甚至并不难。这个特性在单元测试中特别有用。本文将告诉你如何作。
注意:这只能在单体Java应用程序中运行,好比单元测试和常规程序。若是你尝试在Java Applet程序中使用,可能须要注意SecurityManager问题。可是,你并不常作这些操做,而且到目前为止已偏离了本文主题。
注意:已经有不少关于Java9禁用反射访问类私有属性的讨论。根据个人经历,在Java9依旧是能够的(访问类私有属性),但这可能会在Java将来版本中改变。java

访问私有属性

访问私有属性须要调用Class.getDeclaredField(String name)或者Class.getDeclaredFields()方法。方法Class.getField(String name) Class.getFields()只返回类的public方法,因此不能使用它们。下面的示例代码是一个有私有属性的类,再下一个是经过反射访问私有属性。单元测试

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }
}
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”,它是PrivateObject实例的privateString属性的值。
使用方法privateObject.class.getDeclaredField("privateString")时须要注意。这个方法返回私有属性。这个方法只返回特定类定义的属性,不包括任何超类的属性。
另外须要注意代码privateStringField.setAccessible(true);。调用这个方法将为特定的Field实例关闭访问权限检查,仅用于反射。如今你能够访问属性,无论它是private, protected 或者package scope,即便调用方不在访问scope内。你依旧不能使用普通代码访问私有属性,Java编译通不过。测试

访问私有方法

访问类私有方法须要调用Class.getDeclaredMethod(String name, Class[] parameterTypes)或者Class.getDeclaredMethods()。方法Class.getMethod(String name, Class[] parameterTypes)Class.getMethods() 只返回类的public方法,因此不能使用。下面是一个有私有方法的类和如何经过反射调用该类方法的私有代码:this

public class PrivateObject {

  private String privateString = null;

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

  private String getPrivateString(){
    return this.privateString;
  }
}
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")。这个方法调用将返回类的私有方法。这个方法只返回类直接定义的方法,而不返回任何超类的方法。
另外须要注意代码privateStringMethod.setAccessible(true);。调用Method.setAcessible(true)将关闭Method实例的访问权限检查,仅用于反射。如今你能够调用方法,不论它是private, protected 或 package scope,即便调用者不在这些scopes内。你依旧不能经过普通方法访问类的私有方法,这会编译不经过。code

相关文章
相关标签/搜索