为什么这个简单的Java泛型函数不能编译?
虽然为什么这个简单的Java泛型函数不能编译?,java,generics,Java,Generics,虽然f1可以编译,但非常相似的f2不会编译,我无法解释原因。 (在Intellij 9和Eclipse 3.6上测试) 我真的以为我已经解决了这类问题 import java.util.*; public class Demo { public List<? extends Set<Integer>> f1(){ final List<HashSet<Integer>> list = null; retu
f1
可以编译,但非常相似的f2
不会编译,我无法解释原因。
(在Intellij 9和Eclipse 3.6上测试)
我真的以为我已经解决了这类问题
import java.util.*;
public class Demo {
public List<? extends Set<Integer>> f1(){
final List<HashSet<Integer>> list = null;
return list;
}
public List<List<? extends Set<Integer>>> f2(){
final List<List<HashSet<Integer>>> list = null;
return list;
}
}
import java.util.*;
公开课演示{
公共列表列表
不可分配给列表“不要将通配符类型用作返回类型。它会强制用户在客户端代码中使用通配符类型,而不是为用户提供额外的灵活性。”-Joshua Bloch,第5章,第28项。这太长了,无法用于评论。我只是想说,这样声明没有任何意义。您也可以执行以下操作:
public List<List<Set<Integer>>> f2() {
List<List<Set<Integer>>> list = new ArrayList<List<Set<Integer>>>();
List<Set<Integer>> nestedList = new ArrayList<Set<Integer>>();
list.add(nestedList);
Set<Integer> set = new HashSet<Integer>();
nestedList.add(set);
return list;
}
这可以通过将接口(Set
在本例中)而不是实现(HashSet
在本例中)声明为泛型类型来解决。因此:
public List<Map<Integer, Set<Integer>>> getOutcomes() {
Map<Set<Integer>, Integer> map = new HashMap<Set<Integer>, Integer>();
List<Map<Integer, Set<Integer>>> outcomes = new ArrayList<Map<Integer, Set<Integer>>>();
for (Map.Entry<Set<Integer>, Integer> entry : map.entrySet()) {
outcomes.add(asMap(entry.getValue(), entry.getKey()));
// add() now compiles fine.
}
return outcomes;
}
public List getoutcouts(){
Map Map=newhashmap();
列表结果=新的ArrayList();
对于(Map.Entry:Map.entrySet()){
add(asMap(entry.getValue(),entry.getKey());
//add()现在可以正常编译。
}
回报结果;
}
在未来的问题中,试着问如何解决一个特定的问题,而不是如何实现一个特定的解决方案(这可能不是正确的解决方案).找到不兼容的类型:java.util.List required:java.util.List为什么不在所有位置使用List
?这也是正常的方法。您希望声明接口,而不是实现。正在尝试在该列表中添加com.google.common.collect.ImmutableSet。"出于同样的原因,列表将不可分配给List@lacroix1547:不,我没有随机尝试不同的东西。我会在答案中添加更多细节。列表是列表的一个子类型。这只是一个深入的私有方法,不是任何api的一部分。这是合理的。我无意显得挑剔;我只是想引用这个原则。+1,一个非常重要的原则我知道,但它解决了import Java.util.*;公共类Demo2{public List getoutlets(){Map Map Map=new HashMap();List outlets=new ArrayList();for(Map.Entry:Map.entrySet()){outlets.add(asMap(Entry.getValue(),Entry.getKey());}返回结果;}公共映射asMap(kk,vv){Map result=new HashMap();result.put(K,V);return result;}}我现在就去读劳伦斯的协变函数,也许它会让我明白。你总是把实现而不是接口声明为泛型类型。例如,替换Map=new HashMap();
byMap=newhashmap()
。是的,我试图保留实现,它实际上是一个ImmutableSet,看看会发生什么。如果可以的话,我很高兴看到ImmutableSet而不是Set。它是实验性的,也不是主要主题。@lacroix1547:将您的代码发布到pastebin.com,然后在评论中添加一个链接。
public List<List<Set<Integer>>> f2() {
List<List<Set<Integer>>> list = new ArrayList<List<Set<Integer>>>();
List<Set<Integer>> nestedList = new ArrayList<Set<Integer>>();
list.add(nestedList);
Set<Integer> set = new HashSet<Integer>();
nestedList.add(set);
return list;
}
public List<Map<Integer, Set<Integer>>> getOutcomes() {
Map<HashSet<Integer>, Integer> map = new HashMap<HashSet<Integer>, Integer>();
List<Map<Integer, Set<Integer>>> outcomes = new ArrayList<Map<Integer, Set<Integer>>>();
for (Map.Entry<HashSet<Integer>, Integer> entry : map.entrySet()) {
outcomes.add(asMap(entry.getValue(), entry.getKey()));
// add() gives compiler error: The method add(Map<Integer,Set<Integer>>)
// in the type List<Map<Integer,Set<Integer>>> is not applicable for
// the arguments (Map<Integer,HashSet<Integer>>)
}
return outcomes;
}
public <K, V> Map<K, V> asMap(K k, V v) {
Map<K, V> result = new HashMap<K, V>();
result.put(k, v);
return result;
}
public List<Map<Integer, Set<Integer>>> getOutcomes() {
Map<Set<Integer>, Integer> map = new HashMap<Set<Integer>, Integer>();
List<Map<Integer, Set<Integer>>> outcomes = new ArrayList<Map<Integer, Set<Integer>>>();
for (Map.Entry<Set<Integer>, Integer> entry : map.entrySet()) {
outcomes.add(asMap(entry.getValue(), entry.getKey()));
// add() now compiles fine.
}
return outcomes;
}