List<String> list = new ArrayList<String>();
相反,它应该能够推断构造函数的参数类型,以便我们只需键入
List<String> list = new ArrayList();
为什么不能像泛型方法中推断类型参数一样推断类型呢?
这是Java 7的一个改进,也被称为菱形操作符。语法如下:
List<String> strings = new ArrayList<>();
官方提案已被接受纳入Project Coin,该提案是改进泛型实例创建类型推断。
根据Rémi Forax的说法,这一变更已经在Mercurial代码库中。
就像其他人所说的那样,这是Java 7的列表之一。但是,我想指出Google Collections Library已经支持各种集合的这种排序,如果您愿意使用静态导入。例如,我经常编写以下代码:
List<String> list = newArrayList();
new
和 ArrayList()
之间的空格 :)Lists
类。类似的方法也适用于映射等。)class Animal {}
class Dog extends Animal {}
List<? extends Animal> anims = new ArrayList<Dog>();
List<? super Dog> superdogs = new ArrayList<Animal>();
你想知道为什么当前的Java不支持它。
我只能说Java通常会尽可能采取小步骤。我猜测在Java 7之前,他们可能遇到了一些小的技术问题,他们不确定是否能够“正确”解决,可能与确保不会在一些旧的或非泛型代码中创建模糊不清的情况有关。
请注意罗伯特指出的语法将是这样的:
List<String> strings = new ArrayList<>();
类型可以被推断,但作者们决定完全不使用类型推断比在某些情况下有一些有限的类型推断更好。
如果您想在JVM上使用类型推断,请查看scala。
我不是Java超级专家,所以我不能完全确定我将要陈述的内容。以下是我的想法:
由于Java通过擦除实现泛型,因此对于每个泛型类型都有一个基础的原始类型。如果您定义了一个泛型类型,那么将会有一个基础的原始类型,它将在所有地方使用Object
。
当您实例化一个新的ArrayList
时,编译器从实例化类(例如您的示例中的ArrayList<String>
)中推断出类型参数是错误的,因为存在一个具有该确切名称且没有类型参数的类(即原始类型ArrayList
)。我还猜测这就是为什么在Java 7中,您必须在构造函数调用中添加<>
来告诉编译器推断类型的原因。
有人可能会认为,只有在定义类为原始类型时,编译器才应该实例化原始类型,但我认为这会让人感到困惑。我认为编译器必须从不完整的表达式中推断出无法给出上下文的无效表达式,而这不适用于new ArrayList()
语句。
我希望这很清楚,如果我错了,希望有人可以纠正我。
小提示:
另外,请注意原始类与使用 Object
作为类型参数的类型不同:
List<String> list = new ArrayList();
是有效的,而
List<String> list = new ArrayList<Object>();
不是这样的。在第一种情况下,原始类型可以像泛型类型一样使用,但在第二种情况下,您要求逆变性,这是不可用的(除非您使用通配符)。
ArrayList<String> list = new();
。 - Cecil Has a NameArrayList<String> strings = new ArrayList<String>();
和ArrayList<String> strings = new MyCustomArrayList();
,而new ArrayList<>();
就比较清晰。 - Robert Munteanu