===========================================================================================
尽管普遍的观点是不能直接访问私有字段和私有方法的,实际上通过Java反射是可以访问其他类的私有字段和私有方法的。它甚至不是那么困难。在单元测试期间很容易使用。本文将介绍你怎么做。
注:这个只会作用在运行独立的Java应用程序时,如写单元测试和常规应用。如果你尝试在Java Applet内使用它,你需要处理好SecurityManager。但是,因为这不是你经常要做的事情,所以在本文中将不会涉及它。
下面是本文的主题列表:
Accessing Private Fields(访问私有字段)
Accessing Private Methods(访问私有方法)
===========================================================================================
Accessing Private Fields
为了访问私有字段,你需要调用Class.getDeclaredField(String name)方法或者Class.getDeclaredFields()方法。Class.getField(String name)和Class.getFields()方法只会返回public的字段,所有它们不会工作。下面是一个简单的例子,通过Java反射去访问一个类的私有字段:
public classPrivateObject {private String privateString = null;publicPrivateObject(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")。是这个方法调用返回了私有字段的值。这个方法只会返回在给定类里声明的字段的值,而不是其他任何在超类里声明的字段的值。
注意字体加粗的一行。仅仅针对反射,通过调用Field.setAccessible(true)方法,关闭了对特定的Field实例的访问检查。现在你可以访问它,尽管它是private,或者protected,或者是package scope,即使调用者不在这个范围内。你仍然不能通过一般的代码去访问这些字段。编译器不允许这样干。
===========================================================================================
Accessing Private Methods
为了访问私有方法,你需要调用Class.getDeclaredMethod(String name, Class[ ] parameterTypes)方法或者Class.getDeclaredMethods()方法。Class.getMethod(String name, Class[ ] parameterTypes)方法和Class.getMethods()只会返回共有的方法,所以它们不会工作。下面是一个简单的代码示例,通过Java反射访问一个类的私有方法:
public classPrivateObject {private String privateString = null;publicPrivateObject(String privateString) {this.privateString =privateString;
}privateString 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")。是这个方法调用返回的私有方法。这个方法只会返回在给定的类里面声明的方法,而不是在任何超类里声明的方法。
注意字体加粗的一行。仅仅针对反射,通过调用Method.setAccessible(true)方法,关闭了对特定的Method实例的访问检查。现在你可以访问它了,尽管它是private,或者protected,或者package scope,即使调用者不在这个范围内。你仍然不能通过一般的代码访问这些方法。编译器不允许这样干。
========================================================================================
目录
这是一个本教程到目前为止涵盖的主题列表:
(敬请期待下一篇翻译)