Как я могу избежать неконтролируемого бросить предостережение в мой родовой рекурсивный итератор?


Это несколько странно, что основу коллекции в Java не имеет никакого итератора для рекурсивных структур данных. Так как мне нужно что-то вроде этого, я написал свой собственный. Во-первых, мне нужно рекурсивных элементов:

public interface RecursiveElement<T>
{
    public Iterator<T> getChildrenIterator();
}

И тогда итератор:

public class RecursiveIterator<T> implements Iterator<T>
{
    private Deque<Iterator<T>> stack;
    private Iterator<T> currentStackItem;

    /**
     * Creates a new instance
     * 
     * @param root
     *            all children of this node are iterated. The root node itself
     *            is not returned
     * @throws NullPointerException
     *             if root is null
     */
    public RecursiveIterator(final RecursiveElement<T> root)
    {
        if (root == null)
            throw new NullPointerException(
                    "root argument to this iterator must not be null");
        stack = new LinkedList<Iterator<T>>();
        currentStackItem = root.getChildrenIterator();
    }

    @Override
    public boolean hasNext()
    {
        return currentStackItem != null;
    }

    @Override
    public T next()
    {
        final T result = currentStackItem.next();
        if (result instanceof RecursiveElement)
        {
            stack.addLast(currentStackItem);
             // Here is the warning:
            currentStackItem = ((RecursiveElement<T>)result).getChildrenIterator();
        }
        while (currentStackItem != null && !currentStackItem.hasNext())
            currentStackItem = stack.pollLast();
        return result;
    }

    @Override
    public void remove()
    {
        currentStackItem.remove();
    }
}

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



19013
9
задан 26 июня 2011 в 08:06 Источник Поделиться
Комментарии
2 ответа

Я не думаю, что вы можете сделать что-нибудь об этом. У вас есть, чтобы бросить здесь, и в процессе вы потеряете всю информацию о типе параметра: компилятор не может знать, что если у вас есть RecursiveElement, это всегда RecursiveElementи "благодаря" стирания типа он не может проверить тип во время выполнения.

5
ответ дан 27 июня 2011 в 07:06 Источник Поделиться

Чекер тип маркировки здесь реальная проблема. Для визуализации этого, заменить RecursiveElement с родовым итерируемый, который обеспечивает одинаковые гарантии типа.

Когда разные слои смешивать различные типы, RecursiveIterator , к сожалению, ломается. Вот пример:

public class Main {
public static void main(String[] args) {
final RecursiveIterator<IntElem> itr = new RecursiveIterator<IntElem>(new MixedRecursiveElem());
while ( itr.hasNext() ) {
IntElem elm = itr.next();
}
}
}

class IntElem implements RecursiveElement<Integer> {
public Iterator<Integer> getChildrenIterator() {
return Arrays.asList(1, 2, 3).iterator();
}
}

class MixedRecursiveElem implements RecursiveElement<IntElem> {
public Iterator<IntElem> getChildrenIterator() {
return Arrays.asList(new IntElem(), new IntElem()).iterator();
}
}

Output:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to IntElem
at Main.main(Main.java:7)

Ваши варианты:


  • попробовать спихнуть ответственность рекурсией к вашему фактическому элементов;

  • попробуй немного волшебства, чтобы принять конечное количество рекурсии путем добавления переменных типа;

  • падения тип безопасности и завернуть в фильтрации итератора.

2
ответ дан 16 апреля 2014 в 04:04 Источник Поделиться