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

And*_*niy 25 java arrays local-variables java-10

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

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

Main.java:199: error: cannot infer type for local variable k

    var k = { 1 , 2 };
        ^   
(array initializer needs an explicit target-type)
Run Code Online (Sandbox Code Playgroud)

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

var k = {1, 2}; // Infers int[]
var l = {1, 2L, 3}; // Infers long[]
Run Code Online (Sandbox Code Playgroud)

因为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) {
}
Run Code Online (Sandbox Code Playgroud)

那么障碍是什么?

Bri*_*etz 30

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

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

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


Mar*_*eel 21

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

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

    var ints = { 1, 2, 3 }
    
    Run Code Online (Sandbox Code Playgroud)

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

我们可以做这个工作吗?我们可能会.但它会为这个功能增加很多复杂性,这是为了一个大多数情况下的好处.我们希望这是一个简单的功能.

短手数组初始值设定项从声明中获取其类型信息,但是这里的声明var必须明确指定.

您需要选择:

var k = new int[]{ 1 , 2 };
Run Code Online (Sandbox Code Playgroud)

要么

int[] k = { 1 , 2 };
Run Code Online (Sandbox Code Playgroud)

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

  • 大概`var n = 1;`工作并假设`int`?如果是这样,为什么`var a = {1,2};`不假设`int []`?我,程序员,如果我需要,我当然可以指定别的东西. (5认同)
  • 请注意,在左侧使用清单类型或在右侧使用"new"表达式的选择与将"var"与"diamond"组合使用的选择没有什么不同,因为有几种方法可以提供所需的类型信息,而你可以选一个.(它不是一个完美的比较,有时你可以用'var`和钻石,但原则是相同的:不知何故,你必须以一种或另一种形式提供足够的类型信息.) (4认同)
  • @TJCrowder在Java 9及更早版本中,有可能`double [] a = {1,2}`因此,数组的类型也不是从数字文字的类型推断出来的,并且它们保留了该规则.但是,是的,你可以扩展一个论点,即如果`var a = 1`推断int,那么`var a = {1,2}`推断`int []`也应如此.但是缺少`var`的设计师之一在这里添加他的评论,我认为他们在这里选择了保守的路线. (3认同)
  • @Andremoniy因为你在技术上要求我们阅读Java语言设计师的思想(或通过讨论线程跋涉)来推断它. (3认同)
  • @Andremoniy无论如何,我找到了Brian Goetz的相关引用,并从我的回答中删除了我自己的一些看法. (3认同)
  • 鉴于该提案的成功标准,显然有一个*具体的原因,他们不得不推断`int []`.我认为问题在于具体原因是什么; 大概这是在某处记录的.无论如何,我会退后一步,不想做出嘈杂的评论部分.:-)*(编辑:这是对您之前评论的回复,而不是此评论上方的评论.:-))* (2认同)
  • *我们可能会.但是这会给这个功能带来很多复杂性,因为大多数情况下都会受到影响* - 哈哈.好的,这是有道理的;) (2认同)