如何使用反射来提取某种类型的所有属性?

时间:2015-02-18 15:45:10

标签: java reflection

我有许多类,可以包含TranslatableText类型的一个或多个属性。此外,某些类可能具有自身包含此类属性的属性,例如List<TranslatableText>Map<String, TranslatableText>

您将如何以有效的方式扫描这些类,同时在通用集合中获取TranslatableText的实例?

class Project{
    String id;
    TranslatableText name;
    List<Action> actions;
}

class Action {
    String id;
    TranslatableText name;
    TranslatableText description;
}

// getter & setters omitted

2 个答案:

答案 0 :(得分:2)

你可以使用像这样的循环

// for super classes, use recursion.
for(Field f : obj.getClass().getDeclaredFields()) {
    Class type = f.getType();
    if (type == String.class || type == TranslatableText.class) {
        Object value = f.get(object);
        if (value != null)
            map.put(f.getName(), value.toString());
    }

答案 1 :(得分:0)

感谢Peter Lawrey最初的想法。这对我来说是有效的(到目前为止)。我不得不避免循环递归,这就是我添加visited列表的原因。扫描ArraysCollectionsMaps,这对我来说已经足够了。

/**
 * Examine class members for TranslatableTexts. Traverse down into
 * properties including Collections and Maps but ignoring java.lang classes
 * 
 * @param obj
 * @return
 */
public static Collection<? extends TranslatableText> getTranslatables(
        Object obj, List<Object> visited)
{
    List<TranslatableText> result = new ArrayList<TranslatableText>();

    if (obj instanceof TranslatableText)
    {
        result.add((TranslatableText) obj);
        return result;
    }

    if(visited.contains(obj))
        return result;

    visited.add(obj);

    for (Field f : obj.getClass().getDeclaredFields())
    {
        f.setAccessible(true);

        Class type = f.getType();
        if (type.isPrimitive() == false
                && (type.getPackage() == null || type.getPackage()
                        .getName().startsWith("java.lang") == false))
        {
            try
            {
                Object value = f.get(obj);
                if (value != null)
                {
                    if (type.isArray())
                    {
                        Class arraytype = type.getComponentType();
                        if (arraytype == TranslatableText.class)
                        {
                            TranslatableText[] tt = (TranslatableText[]) value;
                            if (tt != null)
                            {
                                for (TranslatableText t : tt)
                                {
                                    result.add(t);
                                }
                            }
                        }
                    }
                    else if (type == TranslatableText.class)
                    {
                        TranslatableText tt = (TranslatableText) value;
                        if (tt != null)
                            result.add(tt);
                    }
                    else if (value instanceof Collection)
                    {
                        for (Object o : (Collection<?>) value)
                        {
                            result.addAll(getTranslatables(o, visited));
                        }
                    }
                    else if (value instanceof Map)
                    {
                        for (Object o : ((Map) value).values())
                        {
                            result.addAll(getTranslatables(o, visited));
                        }
                    }
                    else
                    {
                        result.addAll(getTranslatables(value, visited));
                    }
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    return result;
}