我试图通过在类中实现List接口来稍微调整List。
除了这一方法之外,我可以毫无问题地重写并实现所有方法:
T1
Android Studio会在覆盖时向我显示此代码,并创建新的类型@NonNull
@Override
public <T1> T1[] toArray(@NonNull T1[] a) {
return inner.toArray(a);
}
。
为什么会这样?它有什么作用?
a
将鼠标悬停在java.lang.Object
参数上时,会看到以下棉绒警告:
预期类型为
T[]
的数组
当我尝试将其手动更改回T1[]
而不是T
时,出现此错误:
'QueryList'中的toArray(T [])'与'java.util.List'中的'toArray(T [])'冲突;两种方法具有相同的擦除效果,但都不能覆盖另一种方法
这是Android Studio / intelliJ中的错误,它无法正确创建该覆盖,还是我错过了什么?
编辑:
这是该类的声明,包括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>
及其使用位置。
{{1}}
感谢您的帮助。
答案 0 :(得分:3)
不涉及其他T
您的QueryList
类声明了一个类型参数,该类型参数也称为T
,因此intellij可能会将替代中的参数重命名为T1
,以明确表明它是与众不同的。
请注意,List
中的toArray
也声明了它自己的类型参数,正确覆盖也需要它:
<T> T[] toArray(T[] a);
^^^
我猜您的修复程序也删除了类型参数声明,如下所示:
T[] toArray(T[] a);
但这将不再使其成为替代,因为类型参数必须匹配。根据{{3}}:
在类C中声明或由类C继承的实例方法mC,从C重写在类A中声明的另一方法mA,前提是以下所有条件均成立:
...
- mC的签名是mA签名的子签名jls 8.4.8.1。
在8.4.2
中:
两个方法或构造函数M和N,如果它们具有相同的名称,相同的类型参数(如果有的话) (§8.4.2),并且在改正形式后,则具有相同的签名。 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.