Продвижение примитивных типов
У меня есть вопрос о продвижении примитивных типов в 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 трудное время.