这个反射代码中的错误是什么?

时间:2011-07-26 19:25:09

标签: java reflection

我缺乏Java让我再次陷入困境。我有以下成员函数:

protected void setData(Map<String, String[]> data) {
    Class thisClass = this.getClass();
    for(Map.Entry<String, String[]> item : data.entrySet()) {
        try {
            Field field = thisClass.getDeclaredField(item.getKey());
            try {
                if(field.getType().getName().equals("java.lang.Long")) {
                    // EXCEPTION HERE!!!
                    field.setLong(this, Long.valueOf(item.getValue()[0]) );
                }...
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } catch (NoSuchFieldException e) {
            // Skip this field...
            continue;
        }
    }
}

我继续收到IllegalArgumentException,我不完全理解为什么。任何人都可以提供一些见解吗?

该函数采用迭代的地图,并通过检查“this”上是否存在该字段将值分配给“this”,如果是,则尝试调用field.set()

5 个答案:

答案 0 :(得分:3)

setLong(..)尝试设置原始值,您的字段为java.lang.Long。始终对非基元使用set(..)方法。对于原语getType().getName(),将返回intlong

初步答案:您需要访问该字段:field.setAccessible(true)

答案 1 :(得分:0)

根据Field.set() docs,如果您尝试将值()设置为字段值不是assignable的字段,则会得到IllegalArgumentException。

答案 2 :(得分:0)

使用以下代码,我只会获得非法的ARGUMENT异常 - 没有非法访问异常:

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;


public class Asdf2 {

    private Long long1;
    Long long2;
    protected Long long3;
    private long long4;
    Long long5;
    protected long long6;

    protected void setData(Map<String, String[]> data) {
        Class thisClass = this.getClass();

        for (Map.Entry<String, String[]> item : data.entrySet()) {

            try {
                Field field = thisClass.getDeclaredField(item.getKey());

                try {

                    field.setAccessible(true);

                    if (field.getType().getName().equals("java.lang.Long")) {
                        field.setLong(this, Long.valueOf(item.getValue()[0]));
                    } else {
                        field.set(this, item.getValue()); // EXCEPTION HERE!!!
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
            } catch (NoSuchFieldException e) {

                // Skip this field...
                continue;
            }
        }
    }

    @Override
    public String toString() {
        return "Asdf2["
            + "long1=" + long1
            + ",long2=" + long2
            + ",long3=" + long3
            + ",long4=" + long4
            + ",long5=" + long5
            + ",long6=" + long6
            + "]";
    }

    public static void main(String[] args) {
        Map<String, String[]> data = new HashMap<String, String[]>();
        data.put("long1", new String[] { "1" });
        data.put("long2", new String[] { "2" });
        data.put("long3", new String[] { "3" });
        data.put("long4", new String[] { "4" });
        data.put("long5", new String[] { "5" });
        data.put("long6", new String[] { "6" });

        Asdf2 test = new Asdf2();
        test.setData(data);
        System.out.println(test);

        System.out.println("Done!");
    }
}

我的评论是:

1)如果它是一个Long,你将值的第一个元素(这是一个数组)放入该字段中,否则你将整个数组放入 - 只有当字段也是字符串数组时才会起作用

2)您尚未发布您获得的实际例外情况。它可能会提供更多细节吗?

3)你需要给我们“这个”类 - 不仅仅是set方法 - 我们至少需要看到字段定义。

答案 3 :(得分:0)

您使用的是哪个java版本。请记住,autoboxing工作超过5.0版本。根据异常细节,您似乎尝试将Long对象值分配给long(本机)值。你可以试试这个:

field.setLong(this, Long.valueOf(item.getValue()[0]).longValue());

希望这会有所帮助。

答案 4 :(得分:0)

使用field.set(this,Long.valueOf(item.getValue()[0])); item.getValue()[0]为长值。