Использует ли 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"