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--]))