【问题标题】:Does using var with a literal result in a primitive or a primitive wrapper class?将 var 与文字一起使用会导致原始包装类还是原始包装类?
【发布时间】:2018-03-22 09:00:53
【问题描述】:

看完Java 10s新的保留类型名var (JEP 286: Local-Variable Type Inference),讨论中出现了一个问题。

将它与以下文字一起使用时:

var number = 42;

number 现在是 int 还是 Integer?如果您只是将它与比较运算符或作为参数一起使用,它通常无关紧要,这要归功于自动装箱和 -unboxing。 但由于 Integers 的成员函数,它可能很重要

那么var创建的类型是原始的int还是类Integer

【问题讨论】:

  • 尽管如此,一种方法是肯定尝试一下,您可以尝试看到 number instanceof Integer 不适用于您的情况(因为 instanceof 不适用于原始类型) .另一方面,如果数字将被转换为(Integer) 42It would have worked.

标签: java type-inference local-variables java-10


【解决方案1】:

var 要求编译器从初始化器的类型推断变量的类型,42 的自然类型是int。所以number 将是int。那就是JLS example says

var a = 1;  // a has type 'int' 

如果它以任何其他方式工作,我会感到惊讶,当我写这样的东西时,我绝对期待一个原始的。

如果您需要 var 作为盒装原语,您可以这样做:

var x = (Integer) 10;  // x is now an Integer

【讨论】:

  • 拥有通用var 类型 IMO 的唯一“好处”是能够为其分配动态属性,类似于 C# 和 JS。就像var a = {}; a.arbitraryProperty = "hey!"; - 然而,这似乎是不可能的(虽然我可能错了)。
  • @BackSlash 你可以做到这一点var x = new Object() { int y; int z; }; int test = x.y; 这只有编译器推断的类型才有可能,另见stackoverflow.com/questions/49410939/…
  • @BackSlash:你说的是动态类型。这个问题是关于隐式输入。这是两个完全不同的东西。
  • @Eugene 您错误地使用了“语法糖”一词。这不是纯粹的句法转换。
  • 好吧,var x = (Integer) 10;Integer x = 10; 需要更多的按键,所以我可能会继续使用后者。
【解决方案2】:

根据 14.4.1 中的proposed specification changes局部变量声明符和类型

如果 LocalVariableTypevar,那么当将 T 视为初始化表达式的类型时,就好像它没有出现在赋值上下文中一样,因此一个独立的表达式 (15.2)。局部变量的类型是T相对于T(4.10.5)提到的所有合成类型变量的向上投影。

换句话说,局部变量的推断类型是初始化表达式用作独立表达式时的类型。 42 作为独立表达式的类型为 int,因此,变量 number 的类型为 int

向上投影是规范更改中定义的术语,不适用于此类简单情况。

【讨论】:

  • 我不确定它是否需要进入答案本身,但我很好奇 upward projection 实际上是什么,因为这个答案只告诉你一件事它不是.链接规范中的一句话摘要更改为向上投影:“初始化器的类型使用'向上投影'映射到超类型,消除了任何捕获变量或匿名类。”
【解决方案3】:

让我们测试一下。使用 jshell:

jshell> Integer boxed1 = 42000;
boxed1 ==> 42000

jshell> Integer boxed2 = 42000;
boxed2 ==> 42000

jshell> System.out.println(boxed1 == boxed2);
false

jshell> var infered1 = 42000;
infered1 ==> 42000

jshell> var infered2 = 42000;
infered2 ==> 42000

jshell> System.out.println(infered1 == infered2);
true

第一次比较,两个变量不一样;它们是不同的实例。然而,第二个比较是正确的,因此这里必须推断出一个 int。

注意:要在家尝试,请使用

【讨论】:

  • 这是一个非常迂回的证明。而且您依赖于整数缓存的实现细节......更好的证明是var i = 10,然后是i instanceof Integer。你会得到 ERROR: unexpected type 因为它是一个 int 而不是一个引用。
  • 仅供参考,您不需要System.out.println。只需自行评估 infered1 == infered2
  • 迈克尔,是的,我想到了 instanceof,但没有尝试。我应该有:)
  • 一般来说,我喜欢代码的“证明”,但对于更一般的答案,JLS 仍然更好。除非在 JLS 中写入,否则可以更改实现。但是因为我从来没有想过什么时候使用Jshell,所以我喜欢这个答案!
  • @AxelH 同意。如果答案是基于经验主义的,我会说您应该始终说明您正在测试的版本。
【解决方案4】:

编译器对var number = 42; 的处理与int number = 42; 类似

public void method(Integer i) {
    System.out.print("Integer method");
}
public void method(int i) {
    System.out.print("int method");
}

var n = 42; // n has type 'int' 
method(n); // => "int method"

并在以下情况下自动装箱:

public void method(Integer i) {
    System.out.print("Integer method");
}

var n = 42; // a has type 'int'
method(n); // => "Integer method"

【讨论】:

    猜你喜欢
    • 2013-04-11
    • 2018-06-26
    • 2021-09-11
    • 2010-12-06
    • 2013-03-20
    • 1970-01-01
    • 2014-05-25
    • 2012-07-02
    • 1970-01-01
    相关资源
    最近更新 更多