web-dev-qa-db-ja.com

リテラルでvarを使用すると、プリミティブまたはプリミティブラッパークラスになりますか?

Java 10s new reserved type namevarJEP 286:ローカル変数の型推論 )、ディスカッションで1つの質問が生じました。

次のようなリテラルで使用する場合:

var number = 42;

numberintまたはIntegerになりましたか?比較演算子と一緒に、またはパラメーターとして使用するだけの場合は、オートボクシングと-unboxingのおかげで通常は問題になりません。しかし、Integersメンバー関数のため、それが問題になる可能性があります

それでは、プリミティブvarまたはクラスintであるIntegerによって作成されるタイプはどれですか。

33
sweisgerber.dev

varは、初期化子の型から変数の型を推測するようコンパイラーに要求します。42の自然型はintです。したがって、numberintになります。それが JLSの例によると

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

そして、それが他の方法で機能した場合は驚きます。このようなものを書くとき、私は間違いなくプリミティブを期待します。

ボックス化プリミティブとしてvarが必要な場合は、次のようにすることができます。

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

14.4.1の 提案された仕様変更 によるとローカル変数の宣言子と型

LocalVariableTypevarの場合、[〜#〜] t [〜#〜] 割り当てコンテキストに表示されず、スタンドアロン式( 15.2 )であるかのように扱われる場合の初期化式のタイプです。ローカル変数のタイプは、[〜#〜] t [〜#〜]の上方投影であり、[〜#〜] t [〜#〜](4.1​​0.5)。

つまり、ローカル変数の推定型は、初期化式がスタンドアロン式として使用された場合に想定される型です。 42は、スタンドアロン式のタイプがint、ergoであるため、変数numberのタイプはintです。

上方への投影は、仕様変更で定義された用語で、このような単純なケースには適用されません。

10
Jörg W Mittag

テストしてみましょう。 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

最初の比較では、2つの変数は同じではありません。それらは異なるインスタンスです。ただし、2番目の比較は真であるため、intはここで推測されているはずです。

注:自宅で試してみるには、<-128、128以外の値を使用してください。その範囲の整数インスタンスはキャッシュされます。

7
david a.

コンパイラは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"
1
tonyhoan