为什么在离开泛型运算符时不推断类型

PKu*_*uhn 9 java generics

我读到自Java 7以来,在第一个语句中创建右侧指定类型的集合是不好的样式,因为编译器可以从左侧推断出类型.

List<Integer> myList = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)

我的问题是,当像这样初始化列表时,编译器找不到类型,我得到一个未经检查的类型警告:

List<Integer> myList = new ArrayList(); 
Run Code Online (Sandbox Code Playgroud)

Kon*_*kov 14

编译器不会推断出类型,因为您正在实例化raw ArrayList.但它足够聪明,可以警告您使用此(原始)对象时可能会出现问题.

值得一提的是这个警告背后的原因.由于类型擦除,关于该参数的参数信息(<Integer>)List将在运行时完全消失,此时变量将保存类型的元素Object.请考虑以下代码段:

List rawList = new ArrayList(); //raw list
rawList.add(new String("hello"));
rawList.add(new Double(12.3d));
List<Integer> intList = rawList; // warning!
Run Code Online (Sandbox Code Playgroud)

此代码段将编译,但会产生很少的警告.有一个原始列表(rawList),您可以添加任何非原始类型到列表中,包括String,Double等等.但是这种分配收集到一个列表,该列表指定举行时只有整数,那么这是一个问题.在运行时,你会得到一个ClassCastException什么时候尝试从中获取一些元素intList,这应该是一个Integer,但实际上是一个String或其他东西.

长话短说 - 不要将原始类型与泛型混合!

在您的情况下,如果您使用了钻石,编译器可能会推断出类型:

List<Integer> list = new ArrayList<>(); //¯\_(?)_/¯
                                  ??
Run Code Online (Sandbox Code Playgroud)


lsc*_*tze 11

因为你忘记了尖括号(称为菱形算子).

List<Integer> myList = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

这在语法上等同于

List<Integer> myList = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)

但不同于

List<Integer> myList = new ArrayList();
Run Code Online (Sandbox Code Playgroud)

在第3个中你说右边是原始类型意味着ArrayList可以容纳每个对象(不仅仅是整数).泛型只是编译时间,并编译为保存类型转换.


sp0*_*00m 7

来自https://docs.oracle.com/javase/7/docs/technotes/guides/language/type-in​​ference-generic-instance-creation.html:

请注意,要在泛型类实例化期间利用自动类型推断,必须指定菱形.[...] HashMap()构造是指HashMap原始类型,而不是Map<String, List<String>>类型.