如何从Java中的不同类读取私有字段的值?
我在第三方JAR
设计得很差,我需要访问其中一个专用字段。 例如,为什么我需要选择私人领域是否有必要?
class IWasDesignedPoorly {
private Hashtable stuffIWant;
}
IWasDesignedPoorly obj = ...;
我如何使用反射来获得stuffIWant
的价值?
为了访问私有字段,您需要从类的声明字段中获取它们,然后使其可访问:
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
编辑 :由aperkins评论,既访问该字段,将其设置为可访问和检索值将全部抛出Exception
s,虽然只需检查您需要注意的异常上面评论。
如果您通过与声明字段不对应的名称询问字段,则会引发NoSuchFieldException
。
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
如果该字段不可访问,则会抛出IllegalAccessException
异常(例如,如果该字段是私有的,并且由于缺少f.setAccessible(true)
行而无法访问f.setAccessible(true)
。
如果您尝试访问非字段类类型的对象的字段,则可能抛出的RuntimeException
为SecurityException
(如果JVM的SecurityManager
不允许您更改字段的辅助功能)或IllegalArgumentException
。
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
尝试FieldUtils
Apache的公地lang3:
FieldUtils.readField(object, fieldName, true);
反射并不是解决问题的唯一方法(即访问类/组件的私有功能/行为)
另一种解决方案是从.jar中提取类,使用(例如)Jode或Jad对其进行反编译,更改字段(或添加访问器),然后将其重新编译为原始.jar。 然后将新的.class放在类路径中的.jar
之前,或者将它重新插入到.jar
。 (jar实用程序允许您提取并重新插入现有的.jar)
如下所述,这解决了访问/更改私人状态这一更广泛的问题,而不是简单地访问/更改字段。
这需要.jar
当然不能被签名。
上一篇: How to read the value of a private field from a different class in Java?