收藏中的泛型

Vik*_*shi 15 java generics

这是我的计划.我不知道为什么我会收到编译时错误.

import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {
    List< ? extends Number > list = new ArrayList<Integer>();

    list.add(6); // Compile Time Error

    System.out.println(list);

  }
}
Run Code Online (Sandbox Code Playgroud)

但是以下程序运行正常

import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {
    List< ? super Number > list = new ArrayList<Number>();

    list.add(6); 

    System.out.println(list);

    }
}
Run Code Online (Sandbox Code Playgroud)

Eclipse出错:

以下是Eclipse的错误描述:

类型List中的方法add(int,capture#1-of?extends Number)不适用于参数(int)

ver*_*ald 18

这是因为你在第一种情况下所做的事情并不是类型安全的.您已声明listList"某个子类Number",然后尝试在其中插入一个Integer.绝对不能保证Integer与基础列表的实际运行时类型兼容.编译器在这里阻止你,因为你正在做的事没有任何意义.

考虑一下,作为极端的例子:

List< ? extends Object > list = new ArrayList<Integer>();
list.add("Hello, World!");
Run Code Online (Sandbox Code Playgroud)

如果这个工作,你会有List<Integer>一个String在其中!

如果你真的希望它能够工作,你必须通过强制转换告诉编译器你知道你在做什么:

((List<Integer>)list).add(6);
Run Code Online (Sandbox Code Playgroud)

但即便如此,您仍会收到关于类型安全的警告.

第二种情况是有效的,因为列表保证是"数字的一些超类".Integer是它的子类Number,因此它可以隐式转换为任何超类(包括Number它自己),因此不存在该值与列表的实际类型不兼容的风险.

有关详细信息,您可能需要阅读协方差和逆变之间的差异.

  • 不,泛型不是用Java实现的.如果你这样做,你最终会得到一个带有`String`的`List <Integer>`,如果你尝试将它作为`Integer`检索,你会得到一个例外.这就是为什么编译器仍然会给你一个警告.(有关详细信息,请参阅[类型擦除](http://en.wikipedia.org/wiki/Type_erasure).) (2认同)
  • 它很复杂,但Java中的泛型只存在于编译时.在运行时(当转换发生时)泛型类型被"擦除",并且`List <Integer>`和`List <String>`都只是`List`s,所以转换工作正常.当您尝试将`String`用作`Integer`时,会发生实际的异常,这肯定不是很好. (2认同)