【问题标题】:Setting value of array using java reflection使用java反射设置数组的值
【发布时间】:2013-12-03 17:40:25
【问题描述】:

我已经使用 java 反射创建了通用 json 解析器,但是有一个我无法解决的错误。

方法(在这个问题的底部),接收我的自定义模型类的子类。我遍历字段并从 json 设置值。如果子类包含其他类的数组属性(同样是模型的子类),我创建了小递归来填充这些对象。

例如。

class UserModel extends Model
{
    @JsonResponseParam(Name="userName")
    public String Name;

    @JsonResponseParam(Name="friends")
    public FriendModel[] Friends;
}

最后 UserModel 应该用 Friends 填充。 (JsonResponseParam 为自定义注解,Name 值作为属性用于从 json 中取值)

这个方法的结果是IllegalArgumentException,并且被抛出

field.set(t, values.toArray());

方法如下:

protected <T extends Model> T getModel(T t)
{
    Field[] fields = t.getClass().getFields();

    for (Field field : fields) {
        Annotation an = field.getAnnotation(JsonResponseParam.class);

        if(an != null){
            try 
            {               
                if(field.getType() == boolean.class)                
                    field.setBoolean(t, t.getBool(((JsonResponseParam)an).Name()));

                if(field.getType() == String.class)
                    field.set(t,  t.getString(((JsonResponseParam)an).Name()));

                if(field.getType() == int.class)
                    field.setInt(t,  t.getInt(((JsonResponseParam)an).Name()));

                if(field.getType() == Date.class)
                    field.set(t,  t.getDate(((JsonResponseParam)an).Name()));

                if(field.getType().isArray()){

                    ArrayList<Model> modelArray = t.getModelArray(((JsonResponseParam)an).Name());
                    ArrayList<Model> values = new ArrayList<Model>();

                    for (Model model : modelArray) {

                        Class<? extends Model> arrayType = field.getType().getComponentType().asSubclass(Model.class);
                        Model m = arrayType.newInstance();
                        m.jsonObject = model.jsonObject;
                        model.getModel(m);
                        values.add(m);                      
                    }

                    field.set(t, values.toArray());
                }

            } catch (IllegalArgumentException e) { 
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }

    return t;
}

我怀疑字段和值之间的类类型不一致..

感谢您的宝贵时间。

【问题讨论】:

    标签: java arrays reflection illegalargumentexception setvalue


    【解决方案1】:

    toArray() 只返回一个Object[],因此它不能分配给任何其他数组类型。

    你想要的是

    field.set(t, values.toArray(Array.newInstance(field.getType().getComponentType(), values.size()));
    

    这将创建一个类型与字段匹配的数组。

    Array.newInstance

    【讨论】:

    • 我还必须将实例化的数组转换为它自己的类型。 field.set(t, values.toArray((String[]) Array.newInstance(field.getType().getComponentType(), values.size())));
    • @starkm 这假设您知道类型是`String[]`,如果是这种情况,您真的应该使用new String[values.size()]
    【解决方案2】:

    基本上,模式如下:

    // First, create the array
    Object myArray = Array.newInstance(field.getType().getComponentType(), arraySize);
    
    // Then, adding value to that array
    for (int i = 0; i < arraySize; i++) {
        // value = ....
        Array.set(myArray, i, value);
    }
    
    // Finally, set value for that array field
    set(data, fieldName, myArray);
    

    set函数取自this stackoverflow question:

    public static boolean set(Object object, String fieldName, Object fieldValue) {
        Class<?> clazz = object.getClass();
        while (clazz != null) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(object, fieldValue);
                return true;
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            } catch (Exception e) {
                throw new IllegalStateException(e);
            }
        }
        return false;
    }
    

    应用上面的代码,我们有:

    if(field.getType().isArray()){
        // ....
        int arraySize = modelArray.size();
        Object values = Array.newInstance(field.getType().getComponentType(), modelArray.size());
        for (int i = 0; i < arraySize; i++) {
            // ......
            Array.set(values, i, m);                     
        }
    
        field.set(t, values);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-23
      • 2012-04-04
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      相关资源
      最近更新 更多