Java Generic? extends String

时间:2016-07-13 06:58:51

标签: java generics

当我经历一些泛型问题时,我遇到了这个例子。请问您解释为什么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;
}

}

3 个答案:

答案 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>)用于输入和输出集合(getput是安全的,但是最不宽容的。)

即。这很好:

void appendTo(List<? super String> l) {
  l.append("nonempty");
}

appendTo(new ArrayList<Object>());