java-如何使用反射更新层次结构中的成员
我有一个名为沃尔沃的课程,它继承了汽车。java-如何使用反射更新层次结构中的成员,java,reflection,Java,Reflection,我有一个名为沃尔沃的课程,它继承了汽车。 它包含一个名为Engine的类,该类包含Valve public class Engine { public Engine(int e, int f) { this.e = e; valve = new Valve(f); } private int e; private Valve valve; } 阀门有一个单一的数据成员-int f public class Valve {
它包含一个名为Engine的类,该类包含Valve
public class Engine {
public Engine(int e, int f) {
this.e = e;
valve = new Valve(f);
}
private int e;
private Valve valve;
}
阀门有一个单一的数据成员-int f
public class Valve {
public Valve(int f) {
this.f = f;
}
public int f;
}
所有内容都是私有的,不包含setter
我想使用反射和以下字符串设置一个值
fillIn(volvo, "Engine.Valve.f", 10);
使用此代码:
String[] splits = path.split("\\.");
Class tmpClass = obj.getClass();
for (int i = 0; i < splits.length; i++) {
if (i + 1 != splits.length) {
Field field = tmpClass.getDeclaredField(splits[i]);
tmpClass = field.getClass();
} else {
System.out.println("**** - " + splits[i]);
}
}
String[]splits=path.split(“\\”);
类tmpClass=obj.getClass();
对于(int i=0;i
问题:1.我的目标是沃尔沃。发动机位于汽车的底部。我可以在迭代沃尔沃时获得字段吗
2.如何设置该值?类型每次都不一样
3.有没有更好的实践(FW?)可以做到这一点
谢谢。要访问私有字段,您可以在字段上设置访问权限为
true
,如下所示:
field.setAccessible(true);
看看这个例子:和javadoc
顺便说一句,使用setter肯定会更好
编辑:
您需要存储要设置的字段的对象:
由javadoc编写、未经测试的位编辑代码
String[] splits = path.split("\\.");
Class tmpClass = obj.getClass();
Object tmpObject = obj;
for (int i = 0; i < splits.length; i++) {
if (i + 1 != splits.length) {
Field field = tmpClass.getDeclaredField(splits[i]);
tmpClass = field.getClass();
if(tmpClass.equals(Integer.class)){
field.setInt(tmpObject,42); //where 42 is the number to set
return;
}
tmpObject = field.get(tmpObject); // tmpObject contais the object to set
}
}
String[]splits=path.split(“\\”);
类tmpClass=obj.getClass();
对象tmpObject=obj;
对于(int i=0;i
也许代码不起作用,但我希望它显示出您的想法您正朝着正确的方向前进,但是您的代码中有几个问题:
getDeclaredField
将为您获取一个字段,如果它是在您调用它的类中声明的,而不是在超类中声明的。但是,您可以使用NoSuchFieldException
,如果当前类中未声明字段,则会抛出该异常,以获取超类并重试getDeclaredField
方法的值区分大小写。这意味着您需要调用fillIn
方法作为fillIn(volvo,“engine.valve.f”,10)代码>因为沃尔沃类(通过继承汽车类)有一个名为引擎
的字段,而不是引擎
tmpClass=field.getClass()
将检索字段
对象的类,当然是字段
。您要做的是检索由field
表示的声明字段的类型,这可以通过field.getType()
完成private void fillIn(Object obj, String path, int number) throws Exception {
String[] splits = path.split("\\.");
Class tmpClass = obj.getClass();
for (int i = 0; i < splits.length; i++) {
if (i + 1 != splits.length) {
Field field = null;
while ((field == null) && (tmpClass != null)) {
try {
field = tmpClass.getDeclaredField(splits[i]);
} catch (NoSuchFieldException ex) {
tmpClass = tmpClass.getSuperclass();
}
}
tmpClass = field.getType();
} else {
System.out.println("**** - " + splits[i]);
}
}
}
private void fillIn(对象对象对象、字符串路径、整数)引发异常{
String[]splits=path.split(“\\”);
类tmpClass=obj.getClass();
对于(int i=0;i
我解决了这个问题,不需要访问级别或getter&setter,使用(这需要重新编写,用于生产+当前只解决int)
私有静态空白填充(对象对象对象、字符串路径、int值){
对象tempObj=obj;
反射数据反射数据;
if(路径包含(“.”){
String[]splits=path.split(“\\”);
对于(int i=0;i
在哪里
公共类ReflectionData{
public ReflectionData(Class<?> aClass, Field field, Object object) {
this.aClass = aClass;
this.field = field;
this.object = object;
}
public Class<?> aClass;
public Field field;
public Object object;
public Object getFieldObject() {
Object o = null;
try {
o = field.get(object);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return o;
}
public void setFieldObject(int value) {
try {
field.set(object, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public ReflectionData(类aClass、字段、对象){
this.aClass=aClass;
this.field=字段;
this.object=对象;
}
公共类aClass;
公共领域;
公共客体;
公共对象getFieldObject(){
对象o=null;
试一试{
o=field.get(对象);
}捕获(非法访问例外e){
e、 printStackTrace();
}
返回o;
}
公共无效setFieldObject(int值){
试一试{
设置字段(对象、值);
}捕获(非法访问例外e){
e、 printStackTrace();
}
}
}另一个答案表明,如果使用getter和setter,这将多么容易
// Assuming that the Volvo class builds it own engine,
// with the Engine class building its own value.
Car volvo = new Volvo();
int newF = 10;
volvo.getEngine().getValve().setF(newF); // Done
为什么要避免使用setter和getter?问题很简单,为什么更容易?请看我的答案。会更多吗
// Assuming that the Volvo class builds it own engine,
// with the Engine class building its own value.
Car volvo = new Volvo();
int newF = 10;
volvo.getEngine().getValve().setF(newF); // Done