Использует ли var с литеральным результатом примитивный или примитивный класс-оболочку?

После прочтения и разговора о Java 10s новое зарезервированное имя типа var (JEP 286: Local-Variable Type Inference), один вопрос возник в обсуждении.

При использовании его с литералами типа:

var number = 42;

number теперь int или Integer? Если вы просто используете его с операторами сравнения или как параметр, это обычно не имеет значения благодаря автобоксингам и -unboxing. Но из-за функций-членов Integer это может иметь значение.

Итак, какой тип создается var, примитивным int или классом Integer?

Ответ 1

var просит компилятор вывести тип переменной из типа инициализатора, а естественный тип 42 - int. Таким образом, number будет int. Вот что говорит пример JLS:

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

И я был бы удивлен, если бы он работал каким-то другим способом, когда я пишу что-то вроде этого, я определенно ожидаю примитива.

Если вам нужен var как примитив в штучной упаковке, вы можете сделать:

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

Ответ 2

В соответствии с предлагаемыми изменениями спецификации в 14.4.1 Локальные деклараторы и типы переменных:

Если LocalVariableType является var, то пусть T является типом выражения инициализатора при обработке, как если бы он не отображался в контексте назначения, и, таким образом, являлся автономным выражением (15.2). Тип локальной переменной представляет собой восходящую проекцию T относительно всех синтетических переменных типа, указанных в T (4.10.5).

Другими словами, предполагаемый тип для локальной переменной - это тип, который имел бы выражение инициализатора, если бы он использовался как автономное выражение. 42 как автономное выражение имеет тип int, ergo, переменное 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.

Примечание. Чтобы попробовать дома, используйте значения за пределами <-128, 128). Целые экземпляры в этом диапазоне кэшируются.

Ответ 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"