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

相關文章
相關標籤/搜索