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

Error while using generics and customized iterator

这是被起诉的代码:

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

}

这段代码给我的错误:

error: incompatible types: Object[] cannot be converted to T[] return new myClassIterator(n,array); where T is a type-variable: T extends Object declared in class myClass Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 1 error

但在 iterator() 中创建 myClassIterator 对象时删除 后,错误消失并且代码运行没有问题,现在我问为什么指定泛型会给我这个错误?

有效的 "correct" 代码如下:

@Override
public Iterator<T> iterator(){

    return new myClassIterator(n,array);     

}

MyClassIterator<T> 的构造函数被声明为采用 T 的数组,但您传递的是 Object 的数组。因为你已经用 T 参数化了你的外部 class ,所以看起来你确实希望 array 字段是 Ts

的数组
private T array[]

但是,如果将 class 传递给构造函数,则只能初始化数组,如下所示:

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

你说:
但是在 iterator() 中创建 myClassIterator 对象时删除 ` 后,错误消失,代码运行没有问题

通过删除类型参数 <T>,您将使用 MyClassIteratorraw type。错误消失,因为

For backward compatibility, assigning a parameterized type to its raw type is allowed.

Using raw types, you essentially get pre-generics behavior

在这种情况下,iterator() 会 return 一个 MyClassIterator,其中 return 是 Object 类型的元素。

之所以有效,是因为

if you assign a raw type to a parameterized type, you get a warning:

因此您会收到警告,但不会收到编译时错误。

但是为什么指定泛型会报错?

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

此处您试图将组件类型为 Object 的数组传递给构造函数 MyClassIterator(int n, T[] array)。此构造函数接受 T 类型的数组。 Objects 实例是类型 T 吗?这可以但不必。但是要调用这个构造函数,它必须是。

如何填补这个空白?
字段 array 需要用组件类型 T.

声明
private T[] array;

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

You cannot create arrays of parameterized types.

如何解决?
通过将 Class<T> 传递给 @ohlec .

这样的构造函数

另一种选择是效仿Stream.toArray(IntFunction<T[]> generator)的例子:

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

要使用 n = 5 创建一个 MyClass<String> 实例,我们这样调用构造函数:

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

在这种情况下,我们将类型参数 String 隐式传递给构造函数。