List<T>中的override toArray最终成为T1[] toArray。

4

我正在尝试通过在类中实现List接口来微调一个List。

我可以轻松地覆盖和实现所有方法,除了这个:

<T> T[] toArray(T[] a);

当覆盖/创建一个新类型T1时,Android Studio会显示这段代码。为什么会这样,它有什么影响呢?

@NonNull
@Override
public <T1> T1[] toArray(@NonNull T1[] a) {
    return inner.toArray(a);
}

当我悬停在“a”参数上时,我看到了这个lint警告:
“应该使用类型为java.lang.Object的数组”
当我试图手动将其改回T []而不是T1 []时,我收到了以下错误:
“QueryList中的toArray(T [])与java.util.List中的toArray(T [])冲突;两种方法具有相同的消除效果,但都没有覆盖另一种方法。”
这是否是Android Studio / IntelliJ中无法正确创建重写的bug,还是我错过了什么?
编辑: 以下是类的声明,包括T及其使用位置。
public class QueryList<T> implements List<T> {

//<editor-fold desc="inner list & constructors">
protected final List<T> inner;

public QueryList() {
    inner = new ArrayList<>();
}

public QueryList(int initialCapacity) {
    inner = new ArrayList<>(initialCapacity);
}

public QueryList(@NonNull Collection<? extends T> c) {
    inner = new ArrayList<>(c);
}
//</editor-fold>

感谢任何帮助。

请展示一下 inner 的声明。谢谢。 - Gennadii Saprykin
protected final List<T> inner; and in the constructor instanciated as new ArrayList<>(); - Grisgram
我猜你在一个封闭类中还有另一个类型参数也被命名为 T - Jorn Vernee
1
@Grisgram “没有其他的T参与” 你的QueryList类声明了一个类型参数,也叫做T,所以Intellij可能会将覆盖中的那个重命名为T1,以明确显示它是不同的。 - Jorn Vernee
Jorn Vernee做得很好。我不确定为什么List接口定义了像它这样的toArray方法,但它使用的是与List接口不同的类型参数。因此,您可以执行以下操作: Integer[] array = new ArrayList<String>().toArray(new Integer[0]); - Daniel Beer
显示剩余2条评论
1个回答

3

没有其他涉及到T的内容

您的 QueryList 类声明了一个名为 T 的类型参数,因此 Intellij 可能会将覆盖中的那个参数重命名为 T1,以明确表明它是不同的。

请注意,在 ListtoArray 也声明了自己的类型参数,这也是正确覆盖所需的:

<T> T[] toArray(T[] a);
^^^

我猜测你的修复还移除了类似这样的类型参数声明:
T[] toArray(T[] a);

但这样就不再是重写了,因为类型参数必须匹配。根据 jls 8.4.8.1

如果在类C中声明或继承的实例方法mC,覆盖了类A中声明的另一个方法mA,则当且仅当以下所有条件均为真时,mC才算是覆盖从A继承而来的方法:

...

而在 8.4.2 中:

如果方法或构造函数M和N具有相同的名称、相同的类型参数(如果有)(§8.4.4),并且在将N的形式参数类型适应为M的类型参数后,具有相同的形式参数类型,则它们具有相同的签名。子签名的概念对于强调部分也不再宽松。
当我将其更改为<T> T[] toArray(T[] a)时,会收到警告,提示声明的类型参数T正在隐藏封闭类中的那个类型参数,但将名称更改为T1则可以解决此问题。
至于为什么签名是这样的,一个解释是您希望使用超类型数组来收集列表的元素。例如:
class A {}
class B extends A {}

List<B> list = ...
A[] elements = list.toArray(new A[0]); // should still work, no need to pass a `B[]` strictly.

是的。例如,如果您检查java.util.ArrayList,您会发现类类型参数为EArrayList<E> implements List<E>),但<T>仅适用于此T[] toArray(T[] a)方法。还有一个Object[] toArray()方法,但没有E[] toArray() - Actine
非常感谢您所有的快速答复! - Grisgram

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接