Создание универсального массива против Array.newInstance () - PullRequest
0 голосов
/ 17 сентября 2010

Я пишу класс, который имеет два поля ArrayList. Один для содержания пользовательских объектов. Другой предназначен для хранения пользовательских объектов коллекции (которые также могут иметь следующие поля):

private ArrayList<SomeClass> myObjList;                  // Just objects
private ArrayList<SomeCollectionClass> myCollectionList; // Collections of objects

Для реализации интерфейса Collection<E> я написал метод iterator():

public Iterator<SomeClass> iterator() { ... }

Но для удобства я также начал писать deepIterator (), который возвращает Iterators для каждой из коллекций в myCollectionList - коллекции Iterators - и все очень быстро запуталось:

public Iterator<SomeClass>[] deepIterator() {
    int numIterators = this.myCollectionList.size();
    Iterator<SomeClass>[] iters = (Iterator<SomeClass>[]) new Iterator<SomeClass>[numIterators]; // not allowed
    for (int i = 0; i <= numIterators; i++) {
        iters[i] = this.myCollectionList.get(i).iterator();
    }
    return iters;
}

и компилятор выдает ошибку "generic array creation". Я понимаю, почему это происходит, но я не понимаю, почему:

    public Iterator<SomeClass>[] deepIterator() {
    int numIterators = this.myCollectionList.size();
    Iterator<SomeClass>[] iters = (Iterator<SomeClass>[])(Array.newInstance(Iterator.class, numIterators)); // allowed
    for (int i = 0; i <= numIterators; i++) {
        iters[i] = this.myCollectionList.get(i).iterator();
    }
    return iters;
}

компилируется просто отлично. Кто-нибудь может объяснить? Меня не особо интересуют преимущества array[] по сравнению с некоторым Collection<E> классом (ArrayList или чем-то еще) в качестве возвращаемого типа, я просто озадачен этой строкой объявления / создания / инициализации. Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 17 сентября 2010

Поможет ли вам, если вы объявите свой второй товар, как этот?

private ArrayList<Collection<SomeClass>> myCollectionList;

Работа с массивами и итераторами выглядит как боль в $$. У меня есть вложенные коллекции внутри коллекций, использующих подобные дженерики, и это прекрасно работает. Затем я просто использую вызовы API обычных коллекций, чтобы перебрать его с вложенными циклами for.

0 голосов
/ 17 сентября 2010

Разница в том, что в первом фрагменте вы указываете параметр типа итератора при создании массива, а во втором - нет.Если вы используете неограниченный подстановочный знак для параметра типа:

Iterator<SomeClass>[] iters = (Iterator<SomeClass>[]) new Iterator<?>[numIterators];

или необработанный тип:

Iterator<SomeClass>[] iters = (Iterator<SomeClass>[]) new Iterator[numIterators];

, он компилируется так же, как и второй фрагмент, то есть он просто выдаст непроверенное предупреждение.

PS: Создание массива типов компонентов, не подлежащих повторному определению, запрещено Спецификацией языка Java, §15.10 .

PPS: Лично я был бы раздраженесли бы API без необходимости заставлял меня иметь дело с объектами Iterator, так как нельзя использовать расширенный цикл for для итерации.Если вы хотите раскрыть списки, почему бы не использовать Collection (или хотя бы Iterable)?Это проще для вас и вашего абонента.

...