2

我想通过以下方式迭代类字段

我有课

public class Parent{

String name;
String lastName;

}

public class Child extends Parent{

int childNumber;
}

在父类中我想要一个“get”方法

孩子将继承

此方法将按名称返回字段的值

我如何检索该字段的值?

我希望方法是这样的:

public Object get(String key){
            Field field;
        Object result = null;
        try {
            field = this.getClass().getDeclaredField(key);
            if(field!=null) {
                field.setAccessible(true);
            }
            result = field.get(this); // this is where my problem, i don't know how to retrieve the field's value
        } catch (NoSuchFieldException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

堆栈跟踪

java.lang.IllegalArgumentException: Can not set int field com.database.User.userID to java.lang.String
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(Unknown Source)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(Unknown Source)
    at java.lang.reflect.Field.get(Unknown Source)
    at com.database.DatabaseObject.get(DatabaseObject.java:106)
    at com.database.DatabaseObject.set(DatabaseObject.java:128)
    at com.database.DatabaseObject.getInsertPreparedStatement(DatabaseObject.java:64)
    at com.database.Database.insert(Database.java:95)
    at com.lenabru.webservice.ElectronicArenaWebService.register(ElectronicArenaWebService.java:21)
    at com.database.Main.main(Main.java:29)
4

3 回答 3

1

要获得此堆栈跟踪,您必须将字符串值传递给field.get,而不是this。进行完全重建并再次测试。

以下是UnsafeFieldAccessorImpl该类中的相关方法,如您所见,如果您尝试传入 String 而不是可从声明该字段的类中分配的对象,则只能得到给定的、令人困惑的错误消息:

protected void ensureObj(Object o) {
    // NOTE: will throw NullPointerException, as specified, if o is null
    if (!field.getDeclaringClass().isAssignableFrom(o.getClass())) {
        throwSetIllegalArgumentException(o);
    }
}

protected void throwSetIllegalArgumentException(Object o) {
    throwSetIllegalArgumentException(o != null ? o.getClass().getName() : "", "");
}

protected void throwSetIllegalArgumentException(String attemptedType,
                                                String attemptedValue) {
    throw new IllegalArgumentException(getSetMessage(attemptedType,attemptedValue));
}

protected String getSetMessage(String attemptedType, String attemptedValue) {
    String err = "Can not set";
    if (Modifier.isStatic(field.getModifiers()))
        err += " static";
    if (isFinal)
        err += " final";
    err += " " + field.getType().getName() + " field " + getQualifiedFieldName() + " to ";
    if (attemptedValue.length() > 0) {
        err += "(" + attemptedType + ")" + attemptedValue;
    } else {
        if (attemptedType.length() > 0)
            err += attemptedType;
        else
            err += "null value";
    }
    return err;
}
于 2013-08-17T19:18:38.020 回答
1

我建议你做以下两件事之一:

  1. 如果您的真实代码的字段与您在此处显示的示例一样少,请getXxx()为每个字段添加一个方法。例如,Parent应该有getName()(应该是getFirstName()?)和getLastName()方法和Child应该有getChildNumber()

  2. 如果您的代码比这更复杂,请使用 a并Map通过委托给.get()set()Map

反射适用于构建需要在非常低级别操作对象的复杂工具的程序员。对于我们其他人来说,通常有更好的解决方案。

于 2013-08-17T19:57:42.223 回答
0

如果您想访问 bean 字段BeanUtils,可能是最简单的使用方法:commons-beanutils

System.out.println(BeanUtils.getProperty(child, "name")); // get value from property

BeanUtils.setProperty(c, "lastName", "Ivan Ivanov"); // set value to property
于 2013-08-17T19:27:34.617 回答