Java reflection: how to get field value from an ob

2019-08-31 22:40发布

我说,我有一个返回一个自定义的方法List了一些对象。 他们返回Object给我。 我需要从这些对象某个字段的值,但我不知道该对象的类。

有没有办法通过Reflecion或在某种程度上还能做什么呢?

Answer 1:

假设一个简单的例子,在那里你的领域是public

List list; // from your method
for(Object x : list) {
    Class<?> clazz = x.getClass();
    Field field = clazz.getField("fieldName"); //Note, this can throw an exception if the field doesn't exist.
    Object fieldValue = field.get(x);
}

但是,这是很丑陋,我离开了所有的尝试,渔获物,并提出了一些假设(公共领域,反射可用,很好的安全管理器)。

如果你可以改变你的方法返回一个List<Foo> ,这变得非常容易,因为迭代器则可以让你输入信息:

List<Foo> list; //From your method
for(Foo foo:list) {
    Object fieldValue = foo.fieldName;
}

或者,如果你就吃下一个Java 1.4接口,其中仿制药不可,但你知道,应该是在列表中的对象的类型...

List list;
for(Object x: list) {
   if( x instanceof Foo) {
      Object fieldValue = ((Foo)x).fieldName;
   }
}

没有任何反映需要:)



Answer 2:

如果你知道现场是什么类上,你可以使用反射访问它。 本实施例中(它是在Groovy但该方法调用是相同的)得到一个Field对象的类Foo和获取其值为对象b 。 这表明你不必关心确切具体类的对象,重要的是你知道类的字段上,并且该类要么是具体类或对象的超类。

groovy:000> class Foo { def stuff = "asdf"}
===> true
groovy:000> class Bar extends Foo {}
===> true
groovy:000> b = new Bar()
===> Bar@1f2be27
groovy:000> f = Foo.class.getDeclaredField('stuff')
===> private java.lang.Object Foo.stuff
groovy:000> f.getClass()
===> class java.lang.reflect.Field
groovy:000> f.setAccessible(true)
===> null
groovy:000> f.get(b)
===> asdf


Answer 3:

我强烈建议您使用Java泛型指定为在该列表中,即什么类型的对象。 List<Car> 。 如果你有汽车和卡车,你可以使用的通用超/接口这样的List<Vehicle>

但是,你可以使用Spring的ReflectionUtils使场访问,即使是私人像下面运行的例子:

List<Object> list = new ArrayList<Object>();

list.add("some value");
list.add(3);

for(Object obj : list)
{
    Class<?> clazz = obj.getClass();

    Field field = org.springframework.util.ReflectionUtils.findField(clazz, "value");
    org.springframework.util.ReflectionUtils.makeAccessible(field);

    System.out.println("value=" + field.get(obj));
}

运行此具有的输出:

值= [C @ 1b67f74
值= 3



Answer 4:

public abstract class Refl {
    /** Use: Refl.<TargetClass>get(myObject,"x.y[0].z"); */
    public static<T> T get(Object obj, String fieldPath) {
        return (T) getValue(obj, fieldPath);
    }
    public static Object getValue(Object obj, String fieldPath) {
        String[] fieldNames = fieldPath.split("[\\.\\[\\]]");
        String success = "";
        Object res = obj;
        for (String fieldName : fieldNames) {
            if (fieldName.isEmpty()) continue;
            int index = toIndex(fieldName);
            if (index >= 0) {
                try {
                    res = ((Object[])res)[index];
                } catch (ClassCastException cce) {
                    throw new RuntimeException("cannot cast "+res.getClass()+" object "+res+" to array, path:"+success, cce);
                } catch (IndexOutOfBoundsException iobe) {
                    throw new RuntimeException("bad index "+index+", array size "+((Object[])res).length +" object "+res +", path:"+success, iobe);
                }
            } else {
                Field field = getField(res.getClass(), fieldName);
                field.setAccessible(true);
                try {
                    res = field.get(res);
                } catch (Exception ee) {
                    throw new RuntimeException("cannot get value of ["+fieldName+"] from "+res.getClass()+" object "+res +", path:"+success, ee);
                }
            }
            success += fieldName + ".";
        }
        return res;
    }

    public static Field getField(Class<?> clazz, String fieldName) {
        Class<?> tmpClass = clazz;
        do {
            try {
                Field f = tmpClass.getDeclaredField(fieldName);
                return f;
            } catch (NoSuchFieldException e) {
                tmpClass = tmpClass.getSuperclass();
            }
        } while (tmpClass != null);

        throw new RuntimeException("Field '" + fieldName + "' not found in class " + clazz);
    }

    private static int toIndex(String s) {
        int res = -1;
        if (s != null && s.length() > 0 && Character.isDigit(s.charAt(0))) {
            try {
                res = Integer.parseInt(s);
                if (res < 0) {
                    res = -1;
                }
            } catch (Throwable t) {
                res = -1;
            }
        }
        return res;
    }
}

它支持抓取领域和阵列的物品,如:

System.out.println(""+Refl.getValue(b,"x.q[0].z.y"));

有圆点和括号之间没有什么区别,他们只是分隔符,空字段名被忽略:

System.out.println(""+Refl.getValue(b,"x.q[0].z.y[value]"));
System.out.println(""+Refl.getValue(b,"x.q.1.y.z.value"));
System.out.println(""+Refl.getValue(b,"x[q.1]y]z[value"));


Answer 5:

还有一个办法,我得到了同样的情况在我的项目。 我解决了这个方法

List<Object[]> list = HQL.list();

在上述Hibernate查询语言,我知道哪个地方有什么是我的对象,所以我所做的是:

for(Object[] obj : list){
String val = String.valueOf(obj[1]);
int code =Integer.parseint(String.valueof(obj[0]));
}

这样您可以轻松获得混合的对象,但你应该提前知道哪个地方有什么价值你得到或者你可以通过打印知道的值进行检查。 遗憾的英文不好,我希望这种帮助



文章来源: Java reflection: how to get field value from an object, not knowing its class