使用泛型和自定义迭代器时出错

时间:2018-10-24 19:01:10

标签: java generics iterator iterable

这是指示的代码:

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;
    }

}

这段代码给我错误:

  

错误:类型不兼容:Object []无法转换为T []           返回新的myClassIterator(n,array);     其中T是类型变量:       T扩展在类myClass中声明的对象   注意:一些消息已简化。用-Xdiags:verbose重新编译以获取完整输出   1个错误

但是在iterator()中创建myClassIterator对象的操作中删除了之后,错误消失了,代码可以正常工作了,现在我问为什么要指定通用类型给我这个错误?

起作用的“正确”代码是这样的:

@Override
public Iterator<T> iterator(){

    return new myClassIterator(n,array);     

}

2 个答案:

答案 0 :(得分:1)

您说:
但是在删除iterator()中的myClassIterator对象中的`之后,错误消失了,代码可以正常工作了

通过删除类型参数<T>,您将使用MyClassIterator中的raw type。该错误消失的原因是

  

为了向后兼容,请将参数化类型分配给其原始数据   类型是允许的。

     

使用原始类型,您基本上会获得泛型行为

在这种情况下,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的实例类型为T吗?这可能是但并非必须如此。但是要调用此构造函数必须如此。

如何填补这一空白?
必须使用组件类型array声明字段T

private T[] array;

但是array = new Object[size];将不起作用because

  

您无法创建参数化类型的数组。

该如何解决?
通过将Class<T>传递到@ohlec suggests之类的构造函数中。

另一个选择是遵循Stream.toArray(IntFunction<T[]> generator)的示例:

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

要创建一个MyClass<String> = n的{​​{1}}实例,我们就这样调用构造函数:

5

在这种情况下,我们将隐式类型参数MyClass<String> strings = new MyClass<>(5, String[]::new); 传递给构造函数。

答案 1 :(得分:0)

MyClassIterator<T>的构造函数被声明为采用T的数组,但是您要传递Object的数组。由于您还使用T参数化了您的外部类,因此实际上您似乎希望array字段是T s的数组

private T array[]

但是,只有将类传递给构造函数,您才能初始化数组:

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