你不能做什么 List<W> l1 = new ArrayList<String>(); 而这在调用方法时有效



我真的无法理解为什么我在第一种情况下得到编译错误,而在第二种情况下工作良好。

public class GenericsTest3 {
public static <W> void main(String[] args) {
List<W> l1 = new ArrayList<String>();       // compilation error: Type mismatch: cannot convert from ArrayList<String> to List<W>
doSomething1(new ArrayList<String>());      // works fine
}

public static <L> L doSomething1(List<L> list) {
list.get(0);
list.add(list.get(0));
return list.get(1);
}

}

在我的理解中,在这两种情况下,List都定义为类型参数T/W,那么为什么参数化类型new ArrayList<String>()在一种情况下失败而在另一种情况下通过呢?

List<W> l1 = new ArrayList<String>();

这里的问题是,您为类型为W的List声明了一个变量l1,但随后将类型为String的(Array)List赋值给它。

你可以直接使用W作为ArrayList的类型参数,也可以删除它的类型参数。

List<W> l1 = new ArrayList<>();

关于你的下一个问题:

doSomething1(new ArrayList<String>());

在这里,您只需创建一个String类型的新数组列表,并将其作为参数传递给doSomething1。在doSomething1,类型参数L因此将是String。

case 1:

List<W> l1 = new ArrayList<String>();

你正在告诉java创建一个泛型列表,并在同一声明中指定数据类型为String。所以编译器很困惑该怎么做。

Case 2:

<L> L doSomething1(List<L> list) method

在这种情况下,java知道泛型列表是输入。所有的动作都在List界面上完成。所以编译。

一个泛型方法(即一个方法的类型参数是专门为该方法声明的,就像你在这里一样)意味着该方法可以被调用,泛型类型参数是该类型参数范围内的任何类型,并且你保证该方法将工作。因此,调用者可以调用您的main方法,并显式地选择W作为他们选择的特定类型,并且您保证您的方法将与W作为该类型一起工作,甚至不知道W是什么。在这里,这显然不是真的,因为,如果W被选择为String以外的任何值,那么List<W> l1 = new ArrayList<String>();行是无效的。

对于doSomething1方法也是如此——您保证无论调用者为L选择什么类型,该方法都将工作。在这里,这是真的。doSomething1方法内的代码行,无论你用什么代替L,都可以正常工作。

当你从main调用doSomething1方法时,你是调用者,所以你可以为它的L类型参数选择任何你想要的类型。您选择LString(或者编译器为您推断出这个选择)。这很好。

最新更新