"数组初始值设定项需要一个明确的目标类型" - 为什么?

时间:2018-03-06 15:14:04

标签: java arrays local-variables java-10

关注JEP 286: Local-Variable Type Inference说明

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

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) {
}

那么障碍是什么?

2 个答案:

答案 0 :(得分:30)

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

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

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

答案 1 :(得分:21)

来自邮件列表平台-jep-discuss,Brian Goetz的消息Reader Mail Bag for Thursday (Thu Mar 10 15:07:54 UTC 2016)

  
      
  1. 为什么在初始化程序是数组初始化程序时无法使用var,如:

    var ints = { 1, 2, 3 }
    
  2.         

    规则是:我们通过处理变量得到变量的类型   初始化程序作为独立表达式,并派生其类型。   但是,数组初始值设定项(如lambdas和方法引用)是 poly   表达式    - 他们需要一个目标类型来计算他们的类型。所以他们被拒绝了。

         

    我们可以制作这项工作吗?我们可能会。但它会增加很多   为了大多数角落案例的利益,该功能的复杂性。   我们希望这是一个简单的功能。

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

您需要选择:

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

int[] k = { 1 , 2 };

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