以下代码可以编译并正常运行:
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.add(Arrays.asList(nums[i],nums[j++],nums[k--]))
res
的类型为HashSet<List<Integer>>
,Arrays.asList
返回的类型为ArrayList
的值(不是java.util.ArrayList
,而是根据Java 8内部定义的类{ {3}},它也实现了java.util.List
)
为什么 不 将ArrayList
实例添加到List
的集合中会引发异常?
尽管前者是后者的子类型,但据我所知,由于HashSet<ArrayList>
不是Set<List>
的子类型,因此不允许加法运算吗?
答案 0 :(得分:2)
用generics FAQ引用要问的兼容性:
List<Object>
与Collection<Object>
兼容,因为这两种类型是泛型超类型的实例化及其泛型子类型,并且这些实例化是针对同一类型参数Object的。
不兼容的类型是具有不同类型参数的(相关的)类型(如果这些参数类型相关或兼容,则为事件)-相同的来源:
ArrayList<String>
对象不能作为参数传递给要求ArrayList<Object>
的方法,因为这两种类型是相同泛型的实例化,但是对于不同类型的参数,因此,它们彼此不兼容。
此:
Arrays.asList(nums[i],nums[j++],nums[k--]) //creating and adding List<Integer>
正在执行上面的第一种实例化。
尽管前者是后者的子类型,但据我所知,由于
HashSet<ArrayList<Integer>>
不是Set<List<Integer>>
的子类型,因此不允许进行加法运算
您在这里有一个错误的事实。 Arrays.asList(nums[i],nums[j++],nums[k--])
的静态返回类型为 not ArrayList<Integer>
。是List<Integer>
。您对asList
返回的运行时类有很好的了解,但是编译器对此并不关心(除非验证该代码本身),它停留在{{1}的静态类型(声明的返回类型)上},在这种情况下为asList
。
确实List<Integer>
与HashSet<ArrayList<Integer>>
不兼容,但这无关紧要,因为编译器没有查看实际的运行时类(即使这是用于实例化集合的方法)。
据我所知,编译器需要在此处强制执行的所有操作是,您正在使用Set<List<Integer>>
作为参数来调用Set<List<Integer>>.add()
。