Java是否将子类型实例添加到超类型集合?
以下代码编译和运行时没有问题:Java是否将子类型实例添加到超类型集合?,java,generics,Java,Generics,以下代码编译和运行时没有问题: class Solution { public List<List<Integer>> threeSum(int[] nums) { Set<List<Integer>> res = new HashSet<>(); if(nums.length==0) return new ArrayList<>(res); Arrays.sort
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> res = new HashSet<>();
if(nums.length==0) return new ArrayList<>(res);
Arrays.sort(nums);
for(int i=0; i<nums.length-2;i++){
int j =i+1;
int k = nums.length-1;
while(j<k){
int sum = nums[i]+nums[j]+nums[k];
if(sum==0)res.add(Arrays.asList(nums[i],nums[j++],nums[k--]));
else if ( sum >0) k--;
else if (sum<0) j++;
}
}
return new ArrayList<>(res);
}
}
res
类型为HashSet
,类型为Arrays.asList
返回类型为ArrayList
(不是java.util.ArrayList
,而是一个根据java 8内部定义的类,它还实现了java.util.List
)
为什么不将ArrayList
实例添加到列表的集合中
引发异常
尽管前者是后者的子类型,但据我所知,添加操作不应被允许,因为HashSet
不是Set
的子类型?引用您所质疑的兼容性:
列表
与集合
兼容,因为这两种类型是泛型超类型及其泛型子类型的实例化,并且实例化用于相同的类型参数对象
不兼容的类型是具有不同类型参数的类型(相关类型)(如果这些参数类型在其他方面相关/兼容,则为事件)-同一来源:
ArrayList
对象不能作为参数传递给请求ArrayList
的方法,因为这两种类型是相同泛型类型的实例化,但类型参数不同,因此它们彼此不兼容
这:
Arrays.asList(nums[i],nums[j++],nums[k-->)//创建和添加列表
虽然前者是后者的子类型,但据我所知,添加操作不应该被允许,因为
HashSet
不是Set
你有一个错误的事实。Arrays.asList(nums[i],nums[j++],nums[k--])
的静态返回类型不是ArrayList
。它是列表
。您对asList
返回的运行时类有很好的了解,但编译器并不关心这一点(验证代码本身时除外),它停止在asList
的静态类型(声明的返回类型),在本例中为List
确实,HashSet
与Set
不兼容,但这与此无关,因为编译器没有查看实际的运行时类(即使这是用于实例化集的类)。
据我所知,编译器在这里需要强制执行的就是调用
Set.add()
,其参数是列表
,您正在执行此操作。数组列表
是列表
。技巧通常与类型参数有关,而与基类型本身无关:-)您好,请检查我的更新内容,谢谢<代码>数组。asList返回List
,内部返回ArrayList
。来自:所有实现的接口:可序列化、可克隆、可编辑、集合、集合。是的,HashSet
不是Set
的子类型,因为Set
是一个接口,但是HashSet
实现了它。正如@ernest_k所说:ArrayList
是一个列表。在这里,这才是最重要的。我认为您已经了解了这一点,只是您最后一次想到的HashSet…
不是Set…
的子类型是不相关的。您正在将一个列表
添加到哈希集
——这没有什么错。
res.add(Arrays.asList(nums[i],nums[j++],nums[k--]))