我读到,自从Java 7以来,像在第一个语句中一样在右侧创建集合是错误的样式,因为编译器可以从左侧推断出类型。为什么类型没有被推断,当离开泛型运算符
List<Integer> myList = new ArrayList<Integer>();
我的问题是初始化列表这样的情况下,编译器未找到的类型和我得到一个未经检查的类型警告:
List<Integer> myList = new ArrayList();
我读到,自从Java 7以来,像在第一个语句中一样在右侧创建集合是错误的样式,因为编译器可以从左侧推断出类型。为什么类型没有被推断,当离开泛型运算符
List<Integer> myList = new ArrayList<Integer>();
我的问题是初始化列表这样的情况下,编译器未找到的类型和我得到一个未经检查的类型警告:
List<Integer> myList = new ArrayList();
编译器不推断的类型,因为你实例化一个原料ArrayList
。但它足够聪明,可以警告您在使用此(原始)对象时可能会出现问题。
值得一提的是这个警告背后的原因。由于type erasure,关于List
的参数信息(<Integer>
)将在运行时完全消失,此时变量将保存类型为Object
的元素。考虑这个片段:
List rawList = new ArrayList(); //raw list
rawList.add(new String("hello"));
rawList.add(new Double(12.3d));
List<Integer> intList = rawList; // warning!
这段代码会编译,但会产生很少的警告。有一个原始列表(rawList
),您可以添加任何非原始类型的列表,包括String
,Double
,等等。但是,当将此集合分配到列表中,该列表被指定为只包含整数时,则这是问题。在运行时,当您试图从intList
中获取某个元素时,您会得到ClassCastException
,该元素应该是Integer
,但实际上是String
或其他东西。
长话短说 - 不要混合原始类型与泛型!
在你的情况下,编译将可能人推断的类型,如果你已经使用了钻石:
List<Integer> list = new ArrayList<>(); //¯\_(ツ)_/¯
↑↑
因为你已经忘记了尖括号(称为钻石运营商)。
List<Integer> myList = new ArrayList<>();
这是语法上等同于
List<Integer> myList = new ArrayList<Integer>();
但不同于
List<Integer> myList = new ArrayList();
在你说的是,右侧是一个原始类型含义ArrayList中可以容纳每个对象的第3 (不仅是整数)。泛型只是编译时间,并被编译为保存类型转换。
您可以使用钻石操作符推断声明类型为JLS (§15.9)规定。
一个类的实例创建表达式指定一个类被实例化,接着可能类型参数(§4.5.1)或金刚石(“<>”)如果被实例化的类是通用的(§8.1.2 ),然后是构造函数的实际值参数列表(可能为空)。
List<Integer> myList = new ArrayList<>();
注意采取通用 类实例化过程中利用自动类型推断,你必须指定钻石。
HashMap()
构造函数指的是HashMap
原始类型,而不是 的Map<String, List<String>>
类型。
为什么这给编译器更多的信息比列表 myList = new ArrayList(),因为在左边的通用信息可用 –
PKuhn
因为两者在语义上是不同的。在钻石中省略这种类型只是句法上的含义。 – lschuetze