如何获取此类中字段的字段值

时间:2013-08-17 18:18:29

标签: java reflection field

我想以下列方式迭代类字段

我有课

public class Parent{

String name;
String lastName;

}

public class Child extends Parent{

int childNumber;
}
父类中的

我想要一个“获取”方法

孩子将继承

此方法将按名称

返回字段的值

我如何检索该字段的值?

我希望方法是这样的:

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)

3 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:1)

我建议你做两件事之一:

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

  2. 如果您的代码比此更复杂,请使用Map并通过委派给get()来实施set()Map方法。

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

答案 2 :(得分: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