Java 10:Java 7 的菱形推断是否适用于本地类型推断?

Java 10: Will Java 7's Diamond Inference Work with Local Type Inference?

JEP 286,我们看到我们将能够在 JDK 10 (18.3) 中利用本地类型推断 (var)。 JEP 声明以下编译,这是预期的:

var list = new ArrayList<String>();  // infers ArrayList<String>

我很想知道如果我们尝试以下操作会发生什么:

var list = new ArrayList<>();

我在第二个片段中提出的建议是否可以编译?如果是这样(我怀疑),ArrayList 会接受 Object 作为它的通用类型吗?

我会自己尝试,但我无法访问任何可以安装早期版本的机器。

谢谢!

是的,var和菱形算子可以结合在一起。编译器将推断出最具体的泛型类型:

var list = new ArrayList<>(); // Infers ArrayList<Object>
var list = new ArrayList<>(List.of(1, 2, 3)); // Infers ArrayList<Integer>

您甚至可以将它们与匿名 class:

var list = new ArrayList<>() {};

是的,它会编译。代码中的var

var list = new ArrayList<>();

应被推断为类型 ArrayList<Object> (我相信由于擦除,人们无法准确地确定那里元素的确切类型)这与使用以下代码相同:-

ArrayList list = new ArrayList<>(); 
// without the type of the element of list specified

其中 list 最终被推断为 ArrayList<Object>


来自 Brian 的 FAQ on the mailing list :-

如果我们要求两边推理会怎样?

If you say:

var x = new ArrayList<>() 

then you're asking for the compiler to infer both the type argument to List, and the type of x.

But you've not provided enough type information for the compiler to do a good job.

In most cases, you'll get an informative compiler error telling you that you're asking for your mind to be read. In some cases, we'll fall back to inferring Object, as we currently do with:

Object o = new ArrayList<>()  // always inferred ArrayList<Object> here

"Work with" 是一个模糊的问题,因此您可能会得到模糊的答案。

类型推断不是读心术;这只是约束解决。可用的类型约束越少,您遇到失败或意外结果的可能性就越大(推断出您没有预料到的类型,例如 Object。)

Diamond说:左边应该已经有我需要的类型了,为什么要在右边重复呢

Local variable type inference says: 我需要的类型应该已经在右边了,为什么要在左边重复呢。

通用方法调用说:我需要的类型可能已经存在于参数中,为什么要重复它们作为证人。

如果程序中有足够的类型信息可用,而左侧既没有清单构造函数类型参数也没有目标类型,那么一切都会好起来的。例如:

List<String> anotherList = ...
var list = new ArrayList<>(anotherList);

在这里,编译器可以通过查看构造函数的参数类型(采用 Collection<? extends E> 的参数)来推断 ArrayList 的类型参数。所以它在 RHS 上推断出 T=String,然后能够在 LHS 上推断出 ArrayList<String>

换句话说,编译器将根据您提供的信息做它能做的事情。你给它的信息越少,它就越有可能失败,或者不做你想做的事。

也就是说,我认为您问错了问题。可以省略多少的问题不应该由 "how much will the compiler let me leave out" 驱动,但是 "how much damage am I doing to the readability of my program." 阅读代码比编写代码更重要。遗漏所有可能遗漏的内容不太可能最大限度地提高可读性。你应该努力把 留在 中,以确保没有 reader 在面对你的程序时感到困惑。