2014-09-08 7 views
5

Wenn wir ein static final, die Java-Compiler erklären scheint intelligent genug, um Out-of-Range-Nummern zu erkennen:Warum werden im Bereich beschränkte lange Werte nicht implizit konvertiert? (? Oder Pre-Compiler)

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; 
} 

Der Code beweist darüber für int, short und char Werte Der Compiler beschwert sich nur, wenn der Wert für den Typ der zugewiesenen Variablen außerhalb des zulässigen Bereichs liegt.

jedoch für long Werte, beschwert sich der Compiler selbst wenn die Zahlen in Reichweite sind:

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; 
} 

Warum ist der Compiler nur smart auf Range-Erkennung für int, short und char Werte?

Warum verwendet der Compiler keine Range-Erkennung für long Werte?

+0

Die Kompilierung macht dies aufgrund des älteren Java-Designs und nur in begrenzten Bereichen (-128 - 127). Verbreiterung funktioniert aber nur. – Hannes

+0

@Hannes, ja Erweiterung ist in Ordnung (da es gut ist, immer innerhalb des Bereichs). Es ist die Verengung, die merkwürdig ist. Irgendwie ist die Bereichserkennung nur dann aktiviert, wenn der zu verengende Wert vom Typ "int", "short" oder "char" ist. – Pacerier

Antwort

3

Die Antwort nicht zufriedenstellend sein kann, aber ...

Die Java Language Specification, Section 5.2, sagt:

Zuordnung Kontexten der Wert eines Ausdrucks erlauben einer Variablen zugewiesen (§15.26) werden ; Der Typ des Ausdrucks muss in den Typ der Variablen konvertiert werden.

...

Zusätzlich, wenn der Ausdruck eine Konstante ist Ausdruck (§15.28) vom Typ Byte, short, char oder int:

  • eine Verengung primitive Umwandlung verwendet werden kann, wenn Der Typ der Variablen ist Byte, Kurz oder Char, und der Wert des Konstantenausdrucks kann im Typ der Variablen dargestellt werden.

Für die Fälle, die in Ordnung zu kompilieren, ist der konstante Ausdruck immer vom Typ short, char oder int, und der Wert ist in dem Zieltyp darstellbar. Für den Typ long ist eine solche Umwandlung gemäß der Spezifikation einfach nicht erlaubt.


Die Antwort kann nicht zufrieden sein, denn die nächste offensichtliche Frage ist:

Warum haben sie die Spezifikation wie das schreiben?

Dies wird durch das Beispiel teilweise beantwortet werden kann, die auch in dem verknüpften Abschnitt des JLS gegeben: Diese implizite Umwandlung höchstwahrscheinlich in erster Linie für den Fall vorgesehen ist, dass Sie eine Erklärung wie

byte b = 42; 
schreiben wollen

denn sonst würden Sie den int Wert 42 Byte wie in

byte b = (byte)42; 

Der Fall, dass Sie eininitialisieren möchten werfen müssenvon einem long Wert ist in diesem Sinne einfach nicht so üblich.