Как использовать Java-отражение, чтобы вернуть коллекцию, которая содержит что-то другое, чем объекты - PullRequest
0 голосов
/ 16 мая 2018

Так что моя проблема в том, что я сейчас пытаюсь использовать отражение java для обхода древовидной структуры.Проблема в том, что я знаю о каждой структуре только то, что она может содержать одну из трех вещей.Строки (листья) Другие объекты, или Списки других объектов.Используя отражение, я хочу сделать DFS дерева, пока не найду нужный мне узел.Кажется, моя проблема заключается в том, что когда я использую отражение, чтобы получить поле, которое, как оказалось, имеет тип List, я получаю обратно List, и я не могу привести правильный тип.Вот несколько примеров, которые я попробовал.

Использование полей

Object returnObj = new Object();
Field field = object.getClass().getDeclaredField(fieldClassName);   
field.setAccessible(true);
List<DistributionPartnerRoleType> test = (List<DistributionPartnerRoleType>) field.get(object);

И использование методов

    String methodName = "get" + Character.toUpperCase(fieldClassName.charAt(0)) + fieldClassName.substring(1);
    Method[] getters = object.getClass().getMethods();
    Method getter = getMethod(getters, methodName);
    Type returnType = getter.getGenericReturnType();
    if(returnType instanceof ParameterizedType){
        Type actualType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
        Class actualClass = (Class) actualType;
        returnObj = getter.invoke(object, null);
        List<Object> newList = new ArrayList<Object>();
        for(Object obj : (List<Object>)returnObj){
              newList.add(actualClass.cast(obj));
        }
        returnObj = newList;
    }

Я понимаю, что проблема в том, что объекты действительно имеют типОбъект, но функция и поля явно имеют тип List, как объявлено в коде

protected List<DistributionPartnerRoleType> distributionPartnerRole;

public List<DistributionPartnerRoleType> getDistributionPartnerRole() {
    if (distributionPartnerRole == null) {
        distributionPartnerRole = new ArrayList<DistributionPartnerRoleType>();
    }
    return this.distributionPartnerRole;
}

Если кто-нибудь знает о решении этой проблемы, которое было бы замечательно, Или если мне нужно пойти другим методом, другойзатем рефлексия.

Подводя итог моей проблеме.Invoke возвращает список, но объекты внутри списка на самом деле не относятся к типу, который возвращает эта функция, они относятся к типу java.lang.Object. Есть ли способ обойти это или динамический доступ к объектам списков невозможен?

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Здесь есть более глубокая проблема. Как заявил Луи Вассерман, рефлексия не должна вызывать это, и, похоже, проблема с моим кодом в другом месте.

0 голосов
/ 17 мая 2018

Я не думаю, что использование отражения является хорошей идеей в этом случае.На мой взгляд, очень мало подходящих вариантов использования.Часто это признак того, что вам нужно переосмыслить свой подход.

В этом случае я предлагаю вам взглянуть на шаблон проектирования посетителя .Сам посетитель может включать логику для поиска в глубину, а также для работы с различными типами данных в узлах.

В вашем случае шаблон может выглядеть примерно так:

interface Node {
    void accept(NodeVisitor visitor);
}

class StringNode implements Node {
    public String getValue();

    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }
}

class IntegerNode implements Node {
    public int geValue();

    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }
}

class CompositeNode implements Node {
    public void forEachChild(Consumer<Node> action);

    public void accept(NodeVisitor visitor) {
        visitor.visit(this);
    }
}

interface NodeVisitor {
    default void visit(StringNode node) {}
    default void visit(IntegerNode node) {}
    default void visit(CompositeNode node) {}
}

Теперь ваш алгоритм поиска может выглядеть следующим образом:

class IntegerSearch implements NodeVisitor {
    private final int target;
    private final List<IntegerNode> results = new ArrayList<>();

    void visit(IntegerNode node) {
        if (node.getValue() == target)
            results.add(node);
        }
    }

    void visit(CompositeNode node) {
        node.forEachChild(child -> child.accept(this));
    }
}

Нет отражения, приведения или других хитрых идиом!

Это может не совсем соответствовать вашему случаю (например, возможно, узлы со значениями такжекомпозиты?) но, надеюсь, вы видите общую схему избегания рефлексии.

...