Java 10:Java 7 的 Diamond Inference 是否适用于 Local Type Inference?

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

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

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

var list = new ArrayList<>();

我在第二个片段中提出的内容会编译吗?如果是这样(我怀疑),会接受作为其通用类型吗?ArrayListObject

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

谢谢!


答案 1

是的,钻石操作员可以组合在一起。编译器将推断出最具体的泛型类型:var

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

您甚至可以将它们与匿名类组合在一起:

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

答案 2

“使用”是一个模糊的问题,所以你很可能会得到模糊的答案。

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

戴蒙德说:我需要的类型可能已经出现在左手边,为什么要在右手边重复它们。

局部变量类型推断说:我需要的类型可能已经出现在右侧,为什么要在左侧重复它们。

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

如果程序中有足够的类型信息,但没有清单构造函数类型参数或左侧的目标类型,则一切正常。例如:

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

在这里,编译器能够通过查看构造函数(采用 的参数)的参数类型来推断的类型参数。因此,它在RHS上推断,然后能够在LHS上进行推断。ArrayListCollection<? extends E>T=StringArrayList<String>

换句话说,编译器将在给定您提供的信息的情况下尽其所能。你给它的信息越少,它就越有可能失败,或者不做你想做的事情。

也就是说,我认为你问错了问题。你能遗漏多少的问题不应该是由“编译器会让我遗漏多少”来驱动的,而是“我对程序的可读性造成了多大的损害”。阅读代码比编写代码更重要。省略所有可能遗漏的内容不太可能最大限度地提高可读性。您应该努力留下足够的内容,以确保没有读者面对您的程序时感到困惑。


推荐