2014-09-08 1 views
5

Когда мы объявляем static final, компилятор Java кажется достаточно умны, чтобы обнаружить из-за границы диапазона номеров:Почему суженные длинные значения в дальнем конце неявно конвертируются? (? Или предварительный компилятор)

public class Test { 
    // setup variables: 
    public static final int i_max_byte = 127; 
    public static final int i_max_byte_add1 = 128; 
    public static final int i_max_short = 32767; 
    public static final int i_max_short_add1 = 32768; 
    public static final int i_max_char = 65535; 
    public static final int i_max_char_add1 = 65536; 
    public static final char c_max_byte = 127; 
    public static final char c_max_byte_add1 = 128; 
    public static final char c_max_short = 32767; 
    public static final char c_max_short_add1 = 32768; 
    public static final short s_min_char = 0; 
    public static final short s_min_char_sub1 = -1; 
    public static final short s_max_byte = 127; 
    public static final short s_max_byte_add1 = 128; 

    // all these are OK: 
    public static final byte b1 = i_max_byte; 
    public static final byte b2 = s_max_byte; 
    public static final byte b3 = c_max_byte; 
    public static final byte b4 = (short) i_max_byte; 
    public static final byte b5 = (char) i_max_byte; 
    public static final char c1 = i_max_char; 
    public static final char c2 = s_min_char; 
    public static final short s1 = i_max_short; 
    public static final short s2 = c_max_short; 

    // pre-compiler complains "type-mismatch": 
    public static final byte _b1 = i_max_byte_add1; 
    public static final byte _b2 = s_max_byte_add1; 
    public static final byte _b3 = c_max_byte_add1; 
    public static final byte _b4 = (short) i_max_byte_add1; 
    public static final byte _b5 = (char) i_max_byte_add1; 
    public static final char _c1 = i_max_char_add1; 
    public static final char _c2 = s_min_char_min_us1; 
    public static final short _s1 = i_max_short_add1; 
    public static final short _s2 = c_max_short_add1; 
} 

Код выше доказывает, что для int, short и char значения , компилятор только жалуется, когда значение вне диапазона для типа назначенной переменной.

Однако для long значений, компилятор жалуется, даже если номера находятся в диапазоне:

public class Test2 { 
    public static final long l_max_byte = 127; 
    public static final long l_max_byte_add1 = 128; 
    public static final long l_max_char = 32767; 
    public static final long l_max_char_add1 = 32768; 
    public static final long l_max_short = 65535; 
    public static final long l_max_short_add1 = 65536; 
    public static final long l_max_int = 2147483647; 
    public static final long l_max_int_add1 = 2147483648L; 

    // "type-mismatch" for all: 
    public static final byte b1 = l_max_byte; 
    public static final byte b2 = l_max_byte_add1; 
    public static final char c1 = l_max_char; 
    public static final char c2 = l_max_char_add1; 
    public static final short s1 = l_max_short; 
    public static final short s2 = l_max_short_add1; 
    public static final int i1 = l_max_int; 
    public static final int i2 = l_max_int_add1; 
} 

Почему компилятор только умный в диапазоне детекции для int, short и char значения?

Почему компилятор не определяет дальность обнаружения для значений long?

+0

Компиляторы делают это из-за более старой конструкции java и только в ограниченном диапазоне (-128 - 127). Расширяется только работа. – Hannes

+0

@ Ханнес, расширение у вас прекрасное (так как это хорошо, всегда в пределах диапазона). Это сужающаяся часть странная. Как-то обнаружение диапазона активируется только тогда, когда сужение значения имеет тип 'int',' short' или 'char'. – Pacerier

ответ

3

Ответ не может быть удовлетворительным, но ...

Java Language Specification, Section 5.2, говорит:

Назначение контексты позволяют значение выражения для назначения (§15.26) переменной ; тип выражения должен быть преобразован в тип переменной.

...

Кроме того, если выражение является постоянным выражением (§15.28) типа байт, короткий, полукокса, или INT:

  • сужению примитивные преобразования может быть использован, если тип переменной является байтом, коротким или char, а значение константного выражения представляется в типе переменной.

Для случаев, которые собирают в порядке, постоянное выражение всегда типа short, char или int, а значение представляется в целевом типе. Для типа long такое преобразование просто не допускается в соответствии со спецификацией.


Ответ не может быть удовлетворительным, потому что следующий очевидный вопрос:

Почему они пишут спецификации, как это?

Это может частично ответить на примере, который также приведены в связанном разделе JLS: Это неявное преобразование, скорее всего, предназначен в основном для случая, когда вы хотите, чтобы написать заявление, как

byte b = 42; 

, потому что в противном случае, вам придется привести значение 42 int до байта, как в

byte b = (byte)42; 

случая, который вы хотите инициализировать byte от значения long просто не так распространено в этом смысле.