差异为<?方法和变量声明中的super/extends String>

Dáv*_*áve 10 java generics collections extends super

鉴于:

import java.util.*;

public class Hancock {
    //insert code here
        list.add("foo");
    }
}
Run Code Online (Sandbox Code Playgroud)

在第5行独立插入的哪两个代码片段将在没有警告的情况下编译?(选择两个)

A. public void addString(List list) {
B. public void addString(List<String> list) {
C. public void addString(List<? super String> list) {
D. public void addString(List<? extends String> list) {
Run Code Online (Sandbox Code Playgroud)

正确答案是B&C.

答案A和B对我来说非常清楚.对于答案C&D我知道继承的方式,但是我无法理解为什么答案D不能在Eclipse中编译,而所有其他人都这样做(A有关于通用的警告,B&C没有warrings).

Eclipse中答案D的错误是The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String).

另一方面,这编译:

public void addString() {
    List<? extends String> list1 = new ArrayList<String>();
    List<? super String> list2 = new ArrayList<String>();
}
Run Code Online (Sandbox Code Playgroud)

为什么?为什么<? super String>在变量声明中编译时不在方法声明中编译.

我知道这String是最后一堂课,不能被任何其他班级扩展,但这并没有向我解释这里发生了什么.

Kon*_*kov 9

首先,让我们看看答案C:

public void addString(List<? super String> list) {
    list.add("foo");
}
Run Code Online (Sandbox Code Playgroud)

此方法声明表示您将被允许传递List由某些超类参数化的对象String,例如StringObject.所以:

  1. 如果传递List<String>list.add("foo")将是完全有效的.
  2. 如果传递List<Object>list.add("foo")将是完全有效的,因为"富"是String(你可以添加StringList<Object>).

这意味着答案C是正确的.


现在让我们看看答案D.

如果您有这样的方法声明:

public void addString(List<? extends String> list) {

}
Run Code Online (Sandbox Code Playgroud)

这意味着您将能够传递List某个未知子类型参数化的对象String.因此,当您执行list.add("foo");此操作时,编译器将不会知道所提供的对象是否具有与未知子类型匹配的类型,String因此会引发编译时错误.


当你有:

public void addString() {
    List<? extends String> list1 = new ArrayList<String>();
    List<? super String> list2 = new ArrayList<String>();
}
Run Code Online (Sandbox Code Playgroud)

这个片段编译得很好,因为它list1被定义为List包含某些未知子类型的对象String,包括它String自身,这就是它有效的原因.问题是你将无法添加任何东西,除了null.

至于list2,变量可以保存List由某些超类型(String包括其String自身)参数化的对象.


更多信息:

  • 仔细阅读我写的内容并告诉我在哪里可以添加`Object`实例?我已经说过你可以传递`List <Object>`,而不是你可以添加`Object`s :) (2认同)
  • 我想我应该得到一个赞成票:P xD (2认同)