当我经历一些泛型问题时,我遇到了这个例子。请问您解释为什么list.add("foo")
和list = new ArrayList<Object>()
包含对象问题?
在我的理解中? extends String
表示&#34;扩展字符串&#34;的东西列表,但字符串是最终的?只能是String。在list.add()中我们添加&#34; foo&#34;这是一个字符串。那为什么这个编译问题呢?
public class Generics {
public static void main(String[] args) {
}
public static void takelist(List<? extends String> list){
list.add("foo"); //-- > error
/*
* The method add(capture#1-of ? extends String) in the
* type List<capture#1-of ? extends String> is not applicable
* for the arguments (String)
*/
list = new ArrayList<Object>();
/*
* Type mismatch: cannot convert from ArrayList<Object> to List<? extends String>
*/
list = new ArrayList<String>();
Object o = list;
}
}
答案 0 :(得分:2)
对于初学者来说,java.lang.String
类是 final ,这意味着什么都不能扩展它。因此,没有类可以满足通用要求? extends String
。
我相信这个问题会导致你看到的所有编译器错误/警告。
list.add("foo"); // String "foo" does not extend String
list = new ArrayList<Object>(); // list cannot hold Object which does not extend String
答案 1 :(得分:1)
你说的是真的。字符串是最终的。因此,您可以推断List<? extends String>
只能是字符串列表。
但是编译器不会进行那种分析。也就是说,编译器不会评估String的最终或非最终性质(请参阅注释)。编译器只允许您将null放入列表中。
你可以把东西拉出来。
String s = list.get(0);
答案 2 :(得分:1)
虽然String是最终的,但此信息未使用。
事实上,对于Java 9,它可能不再是最终的(有传言说Java 9最终可能会获得更高效的String类型)。
不知道它是最终的,List<? extends String>
可以是例如一个List<EmptyString>
个必须为空的字符串。
void appendTo(List<? extends String> l) {
l.append("nonempty");
}
appendTo(new ArrayList<EmptyStrings>());
会违反通用类型。
根据经验,总是使用:
? extends Type
输入集合(get
是安全的)? super Type
输出集合(put
是安全的)Type
(或者<T>
)用于输入和输出集合(get
和put
是安全的,但是最不宽容的。)即。这很好:
void appendTo(List<? super String> l) {
l.append("nonempty");
}
appendTo(new ArrayList<Object>());