java - 列表覆盖 toArray 最终为 T1[] toArray
问题描述
我试图通过在一个类中实现 List 接口来稍微调整一个 List。
我可以毫无问题地覆盖和实现所有方法,除了这个:
<T> T[] toArray(T[] a);
Android Studio 在覆盖时向我展示了这段代码,创建了一个新类型T1
。为什么会这样,它有什么影响?
@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 中的一个错误,它无法正确创建该覆盖,还是我错过了什么?
编辑:
这是类的声明,包括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>
谢谢你的帮助。
解决方案
不涉及其他 T
您的QueryList
类声明了一个类型参数,该参数也名为T
,因此 intellij 可能会将覆盖中的参数重命名为T1
以明确显示它是不同的。
请注意,toArray
inList
还声明了它自己的类型参数,这也是正确覆盖所必需的:
<T> T[] toArray(T[] a);
^^^
我猜你的修复也像这样删除了类型参数声明:
T[] toArray(T[] a);
但这将不再使其成为覆盖,因为类型参数必须匹配。根据jls 8.4.8.1:
在类 C 中声明或继承的实例方法 mC,从 C 覆盖在类 A 中声明的另一个方法 mA,如果以下所有条件都为真:
...
- mC的签名是 mA 签名的子签名(第 8.4.2 节)。
并在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.
推荐阅读
- jquery - jquery slicknav中的中心品牌
- r - 为什么 R 将 0 读取为 NA?
- python - 一切正常,但我不知道为什么没有发送消息
- azure-cosmosdb - 在 CosmosDB SQLAPI 中选择正确的分区键的问题
- android - Android Firebase Eventlistener 在数据更改时调用了两次
- c# - 在 Oracle 上从 C# 加载缓慢的 BLOB
- flutter - 列内的 TabBarView 在 Flutter 中给了我错误
- python - python中的文件比较并输出差异
- python - 使用 MirroredStrategy() 恢复 TensorFlow 训练
- git - 列出远程服务器上包含特定提交的所有标签?