Продвижение примитивных типов
У меня есть вопрос о продвижении примитивных типов в Java. Как мы видим в следующем примере, один из методов не компилируется из-за ошибки несоответствия типов. Каждый метод возвращает одно и то же значение, но в разных типах.
Версия метода primitive long
работает без ошибок, в то время как версия класса-оболочки Long
терпит неудачу. Это происходит потому, что литерал int
в операторе return
сначала будет переведен в более широкий примитивный тип (например, long
), а затем в соответствующий класс обертки Integer
и так далее. Поскольку Integer
не является подклассом Long
, компилятор выдает ошибку.
Но почему версия класса-оболочки Byte
работает без ошибок? Что именно делает компилятор на этом этапе?
long getPrimitiveLong() {
return 12; // valid
}
Long getWrapperLong() {
return 12; // Error: type mismatch
}
Byte getWrapperByte() {
return 12; // valid
}
4 ответа:
Версия с
Byte
работает через некоторую магию компилятора.В отличие от
long
числовых литералов, которые могут быть построены с помощьюL
, например,12L
, нет такой вещи, какbyte
литерал. Вот почему компилятор Java обрабатывает числовые литералы, которые помещаются в байт, как литералыbyte
. Следовательно,12
в вашем последнем примере рассматривается константа типаbyte
.Спецификация языка Java предлагает описание этого преобразования в разделе 5.2:
Можно использовать сужающее примитивное преобразование с последующим боксерским преобразованием если тип переменной:
Byte
и значение постоянного выражения представимо в видеbyte
.Short
и значение постоянного выражения представимо в видеshort
.Character
и значение постоянного выражения представимо в видеchar
.
Это потому, что Java позволяет 1 преобразование или Автобоксинг, не более.
Java может делать все это:
int i = 5; double d = i; long l = i;
Или autobox:
Integer i = 5; Long l = 5L; Double d = 5.0;
Преобразование дважды дает Java трудное время.