Ошибка при использовании шаблонов и настраиваемого итератора - PullRequest
0 голосов
/ 24 октября 2018

Вот обвинительный код:

import java.util.Iterator;

public class MyClass<T> implements Iterable<T> {

    private int n;
    private Object array[];

    public myClass( int size ){
        array = new Object[size];
        n=0;

    }

    @Override
    public Iterator<T> iterator(){
        return new MyClassIterator<T>(n,array); //Here's my error!
    }



    }
    class MyClassIterator<T> implements Iterator<T>{

    private int n;
    private T[] array;

    MyClassIterator( int n, T[] array ){

        this.n = n;
        this.array = array;

    }

    @Override 
    public T next(){
        return array[n++];
    }

    @Override
    public boolean hasNext(){

        return n==array.length;
    }

}

Этот код дает мне ошибку:

ошибка: несовместимые типы: объект [] не может быть преобразован в T [], возвращать новыйmyClassIterator (п, массив);где T - переменная типа: T расширяет объект, объявленный в классе myClass Примечание: некоторые сообщения были упрощены;перекомпилировать с -Xdiags: многословно, чтобы получить полный вывод 1 ошибка

Но после удаления при создании объекта myClassIterator в iterator () ошибка исчезает, и код работает без проблем, теперьЯ спрашиваю, почему конкретный тип дает мне эту ошибку?

"Правильный" код, который работает, будет следующим:

@Override
public Iterator<T> iterator(){

    return new myClassIterator(n,array);     

}

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Вы сказали:
Но после удаления `при создании объекта myClassIterator в iterator () ошибка исчезает и код работает без проблем

При удалении типапараметр <T> вы используете необработанный тип из MyClassIterator.Ошибка исчезает, потому что

Для обратной совместимости разрешено присвоение параметризованного типа его необработанному типу.

Используя необработанные типы, вы, по сути, получаете предварительное поведение

В таком случае iterator() вернет MyClassIterator, который возвращает элементы типа Object.

Это работает, потому что

, если вы назначаете необработанный тип параметризованному типу, вы получаете предупреждение:

Таким образом, вы получаете предупреждение, но неошибка времени компиляции.

Но зачем указывать универсальный тип, дайте мне эту ошибку?

public Iterator<T> iterator() {
  return new MyClassIterator<T>(n, array); // Here's my error!
}

Здесь вы пытаетесь передать массив с компонентомвведите Object в конструктор MyClassIterator(int n, T[] array).Этот конструктор принимает массив типа T.Являются ли Object s экземплярами типа T?Это может быть, но не обязательно.Но чтобы вызвать этот конструктор, он должен быть.

Как заполнить этот пробел?
Поле array должно быть объявлено с типом компонента T.

private T[] array;

Но тогда array = new Object[size]; не будет работать , потому что

Вы не можете создавать массивы параметризованных типов.

Как решить эту проблему?
Либо, передав Class<T> в конструктор, как @ohlec предлагает .

Другой вариант - следовать примеру Stream.toArray(IntFunction<T[]> generator):

public MyClass(int size, IntFunction<T[]> generator) {
  array = generator.apply(size);
  n = 0;
}

Чтобы создать MyClass<String> экземпляр с n = 5, мы вызываем конструктор так:

MyClass<String> strings = new MyClass<>(5, String[]::new);

В этом случае мы передаем неявный аргумент типа String вконструктор.

0 голосов
/ 24 октября 2018

Конструктор MyClassIterator<T> объявлен как принимающий массив T, но вы передаете массив Object.Поскольку вы параметризовали свой внешний класс также с помощью T, похоже, что вы хотите, чтобы поле array было массивом T s

private T array[]

Однако вы можете толькоинициализируйте массив, если вы передадите класс конструктору следующим образом:

public myClass( int size, Class<T> clazz ){
    array = (T[]) Array.newInstance(clazz, size);
}
...