我读到自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可以容纳每个对象(不仅仅是整数).泛型只是编译时间,并编译为保存类型转换.
请注意,要在泛型类实例化期间利用自动类型推断,必须指定菱形.[...] 的
HashMap()
构造是指HashMap
原始类型,而不是Map<String, List<String>>
类型.