“数组初始化程序需要一个明确的目标类型” – 为什么?

遵循JEP 286:局部变量类型推断描述

我想知道,引入这种限制的原因是什么,如:

Main.java:199: error: cannot infer type for local variable k var k = { 1 , 2 }; ^ (array initializer needs an explicit target-type) 

所以对我来说逻辑上它应该是:

 var k = {1, 2}; // Infers int[] var l = {1, 2L, 3}; // Infers long[] 

因为Java编译器已经可以正确地推断出数组的类型:

 void decide() { arr(1, 2, 3); // call void arr(int ...arr) arr(1, 2L, 3); // call void arr(long ...arr) } void arr(int ...arr) { } void arr(long ...arr) { } 

那么障碍是什么?

每次我们改进Java中类型推断的范围时,我们都会得到一连串“但你也可以推断出这一点,为什么不呢?” (或者有时候,不太礼貌。)

关于设计类型推理方案的一些一般性观察:

  • 推理方案总是有限制的; 在边缘总是存在我们无法推断答案,或最终推断出令人惊讶的事情的情况。 我们越努力推断一切,我们越有可能推断出令人惊讶的事情。 这并不总是最好的权衡。
  • 很容易挑选出“但在这种情况下你可以推断出来的例子”。 但是,如果这种情况与其他没有明显答案的案例非常相似,我们只是将问题转移到了 – “为什么它适用于X而不是Y,其中X和Y都是Z?”
  • 总是可以使用推理方案来处理增量情况,但是几乎总是存在附带损害,或者是在其他情况下获得更差的结果,增加的不稳定性(看似无关的变化可以改变推断的类型),或者更复杂。 您不希望仅根据您可以推断的案例数进行优化; 您还希望优化受过教育的用户预测哪些有效,哪些无效。 绘制更简单的行(例如,不要试图推断数组初始化器的类型)通常是一个胜利。
  • 鉴于总是存在限制,通常最好选择更小但更好定义的目标,因为这简化了用户模型。 (参见相关问题“为什么我不能对私有方法的返回类型使用类型推断。答案是我们可以做到这一点,但结果将是一个更复杂的用户模型,用于表达小的利益。我们称之为”复杂性很差。“)

来自邮件列表平台-jep-discuss,由Brian Goetz 于星期四(2016年3月10日星期四15:07:54)发送消息Reader Mail Bag :

  1. 当初始化程序是数组初始值设定项时,为什么不能使用var,如:

     var ints = { 1, 2, 3 } 

规则是:我们通过将初始化程序视为独立表达式并派生其类型来派生变量的类型。 但是,数组初始值设定项(如lambda和方法引用)是多重表达式 – 它们需要目标类型才能计算其类型。 所以他们被拒绝了。

我们可以做这个工作吗? 我们可能会。 但它会为该function增加许多复杂性,这对于大多数极端情况都有好处。 我们希望这是一个简单的function。

短手数组初始值设定项从声明中获取其类型信息,但由于此处的声明是var因此必须明确指定。

您需要选择:

 var k = new int[]{ 1 , 2 }; 

要么

 int[] k = { 1 , 2 }; 

允许var k = { 1 , 2 }会改变已经是语法糖的东西的语义。 在int[] n = { 1, 2 }的情况下,类型由声明确定。 如果允许var n = { 1, 2 } ,则初始化程序本身会突然确定类型。 这可能会导致(更容易创建)编译器错误或模糊。