由于工作需要,需要拿到一个对象的属性的属性的属性。没骗你,这是真的。当然,这真的不算什么,不就才3级的属性调用嘛,天天写的。我要说的是,这3个属性中,前2个是在其父类中声名的,第一个是protected,后两个都是private的。这3级,没有一级提供Getter和Setter。同时,这3级的代码,都是jar包中的,我反编译加Debug,才知道有这个东西的。正常的调用,第一个属性都拿不到的。
这种情况下,不用反射,是走投无路了。当然,反射用在这样的地方,不是一个好的选择。但没办法,项目赶,jar包的代码我又动不了,这个东西,我又一定要,没它不行。所以,只能用反射出个临时的解决方案。
废话少说,自己尝试的过程,也不叙述了,只把最后能跑的例子贴出来。
1、先写个父类,叫Person
package com.lippeng.helloworld;
public class Person {
private String name = "xiaoming";// 例子嘛,追求简单 和 有代表性,只保留这一个属性
}
2、写个子类,叫XiaoMing
package com.lippeng.helloworld;
public class XiaoMing extends Person {
// 遗憾的事,这里面什么都没有,哈哈。。。
}
3、准备工作做完了,看看我的HelloWorld吧!
package com.lippeng.helloworld;
import java.lang.reflect.Field;
public class HelloWorld {
public static void main(String[] args) {
Object object = new XiaoMing();
String fieldName = "name";
Object value = getFieldValue(object, fieldName);
if (value != null) {
System.out.println(value);// 不好意思,忘记了,这里输出的不是"Hello World!",而是"xiaoming"。哈哈。。。
} else {
System.out.println("什么都没拿到。。。");
}
}
/**
* get the field value in aObject by aFieldName
*
* @param aObject
* @param aFieldName
* @return
*/
private static Object getFieldValue(Object aObject, String aFieldName) {
Field field = getClassField(aObject.getClass(), aFieldName);// get the field in this object
if (field != null) {
field.setAccessible(true);
try {
return field.get(aObject);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return null;
}
/**
* 这个方法,是最重要的,关键的实现在这里面
*
* @param aClazz
* @param aFieldName
* @return
*/
private static Field getClassField(Class aClazz, String aFieldName) {
Field[] declaredFields = aClazz.getDeclaredFields();
for (Field field : declaredFields) {
// 注意:这里判断的方式,是用字符串的比较。很傻瓜,但能跑。要直接返回Field。我试验中,尝试返回Class,然后用getDeclaredField(String fieldName),但是,失败了
if (field.getName().equals(aFieldName)) {
return field;// define in this class
}
}
Class superclass = aClazz.getSuperclass();
if (superclass != null) {// 简单的递归一下
return getClassField(superclass, aFieldName);
}
return null;
}
}
这样就完了?是的,这样就完了。有了这些,上面的3级属性调用,如同儿戏。