E.G。要创建一个字符串ArrayList,我们必须做类似
的事情List<String> list = new ArrayList<String>();
然而它应该能够推断出构造函数的参数类型,这样我们只需要输入
List<String> list = new ArrayList();
为什么不能像通用方法那样输入类型参数那样输入类型。
答案 0 :(得分:22)
这是一个Java 7改进,也称为钻石运算符。语法为:
List<String> strings = new ArrayList<>();
官方提案accepted for inclusion in Project Coin为Improved Type Inference for Generic Instance Creation
根据Rémi Forax,更改已经存在于mercurial存储库中。
答案 1 :(得分:6)
正如其他人所说,这是on the list for Java 7。但是,我想指出,Google Collections Library已经为各种集合提供了支持,如果您乐意使用静态导入。例如,我经常编写如下代码:
List<String> list = newArrayList();
您只需要静态导入并删除new
和ArrayList()
之间的空格:)
(静态导入将是Lists
类,顺便说一句。地图等有类似的方法。)
答案 2 :(得分:2)
它可以是,它是一个包含在JDK7中的功能。
答案 3 :(得分:2)
除了JDK7功能之外,我猜你可以使用 extends 和 super 。
class Animal {}
class Dog extends Animal {}
List<? extends Animal> anims = new ArrayList<Dog>();
List<? super Dog> superdogs = new ArrayList<Animal>();
你无法在这两种情况下推断出来。
答案 4 :(得分:2)
您想要一个当前Java不支持它的原因。
我只能说Java通常只会采取一些步骤。我猜想有一些技术上的小故障,他们不确定在Java 7之前获得“正确” - 可能与确定它不会在某些旧的或非通用的代码中创建一个模糊的情况有关。
注意罗伯特如何指出语法是这样的:
List<String> strings = new ArrayList<>();
注意空&lt;&gt ;?我猜这是为了消除这种类型的推断与旧的非通用代码的歧义;它可能只是他们一开始没想到的东西。
答案 5 :(得分:1)
可以推断出类型,但作者只是决定最好不要进行类型推断,然后在某些情况下进行一些有限的类型推断。
如果您想在jvm上进行类型推断,请查看scala。
答案 6 :(得分:0)
我不是Java超级专家,所以我不完全确定我会说什么。以下是我的想法:
当Java通过擦除实现泛型时,对于每种泛型类型都有一个底层原始类型。如果您定义泛型类型,则会有一个基础原始类型,它将全部使用Object
。
当您实例化一个新的ArrayList
时,编译器从实例化类(在您的示例中为ArrayList<String>
)中推断出类型参数是错误的,因为有一个具有该确切名称的类,没有类型参数(即原始类型ArrayList
)。我也猜测这就是为什么在java 7中你必须在构造函数调用中添加<>
来告诉编译器推断出类型。
有人可能会争辩说,只有当定义类是原始类型时,编译器才应该实例化原始类型,但我认为这会让人感到困惑。我认为编译器必须从不完整的表达式中推断出在没有给定上下文的情况下是无效的,而new ArrayList()
语句不是这种情况。
我希望这很清楚,如果我错了,有人可以纠正我。
旁注:
另外,请注意原始类与使用Object
作为类型参数的类型不同:
List<String> list = new ArrayList();
有效,其中
List<String> list = new ArrayList<Object>();
不是。在第一种情况下,原始类型可以使用,就好像它是泛型类型,但在第二种情况下,您要求不可用的逆转(不是如果您不使用通配符)。