Согласно моим знаниям на Java, при сужении преобразования типа, если источник в любой константе, находящейся в диапазоне байта, допускается:
byte b=10; // allowed because 10 is in range of byte and 10 is a constant
но когда я набираю это:
byte b=10l; // this is not allowed although 10 is in range of byte and is a constant
Почему так? Можете ли вы рассказать точное правило, с помощью которого эти сужающиеся преобразования происходят на Java.
Технический ответ - потому что спецификация говорит так. §5.2 "Контексты назначения" Спецификации языка Java, Java SE 8 Edition, частично заявляет:
Кроме того, если выражение [в правой части оператора присваивания] является константным выражением (§15.28) типа
byte
,short
,char
илиint
:
- Сужение примитивного преобразования может быть использовано, если тип переменной является
byte
,short
илиchar
, а значение константного выражения представляется в типе переменной.
Что касается того, почему это не позволяет постоянному выражению иметь тип long
, я полагаю, что вы никогда не "случайно" заканчиваете тип long
. Очень удобно записывать byte b = 127
в виде сокращения для byte b = (byte) 127
то время как компилятор мешает вам ошибочно писать byte b = 128
виде сокращения для byte b = (byte) 128
; не так полезно писать byte b = 127L
, в частности, потому что зачем вам это нужно?
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.2:
Кроме того, если выражение является константным выражением (§15.28) типа byte, short, char или int:
- Сужение примитивного преобразования может быть использовано, если тип переменной является байтом, коротким или char, а значение константного выражения представляется в типе переменной.
У вас есть постоянное выражение типа long, и сужение примитивного преобразования не может быть применено в этом случае.
Таким образом, вы можете:
byte b = 10
byte b = (int) 10
char b = (short) 10
byte b = (char) 10L
short b = (int) 10L
Но вы не можете этого сделать:
byte b = 10L
byte b = (long) 10
потому что l
вы привязали к значению, явно говорит компилятору - "слушайте bro. У меня здесь" длинное "поле. Дайте ему пространство для" длинного "поля".
Очевидно, что длинное значение не может вписываться в поле байта. Таким образом, вы получаете ошибку - Cannot Convert from Long to Byte
int
(не long
) констант времени компиляции.
Вы правы, 10 находится в диапазоне байта. Но когда вы используете l
суффикс с константой, java понимает, что эта константа long
. Поскольку long
не может поместиться в byte
, вы получаете ошибку: возможная потеря точности, заявляемая javac.
Однако, byte b = (byte) 10l;
работает, потому что это прямой литой от long
byte
.
byte
, short
, int
или long
. По умолчанию Java пытается присвоить переменной целое число, предполагая, что целое число соответствует размеру типа переменной. Если это не подходит, компилятор вызывает ошибку. Когда вы пишете byte b = 10
, это нормально, потому что 10 помещается в байт и обрабатывается как байт. Однако, если вы попытаетесь использовать byte b = 130
, вы получите ту же ошибку, потому что 130 не находится в диапазоне byte
.
Java - это строго типизированный язык. он неявно обрабатывает преобразование типов из меньших типов в типы Bigger, но в случае преобразований типов от Bigger Type к более мелкому типу вам нужно делать это явно путем литья типов.
Например, long может вмещать int, но int не может иметь достаточного пространства для размещения longs, поэтому компилятор предупреждает вас.
Поэтому в вашем случае вы можете сделать:
byte b= (byte) 10l;
Надеюсь это поможет
byte b = (int) 10l
и int
будет «больше», чем byte
.
byte b = 10
), а не «сужающее преобразование типа » (например,(byte)10
).