2013-06-12 6 views
6

Bestimmte Funktionalität des Compilers verwirrt mich (Oracle JDK 1.7 mit Eclipse).Java - warum wird char implizit in ein Byte (und kurzes) primitiv umgewandelt, wenn nicht?

So habe ich dieses Buch, das besagt, dass Char primitive explizit auf kurze und Byte umgewandelt werden muss und dies alles Sinn macht, da die zulässigen Bereiche der Datentypen nicht überlappen.

Mit anderen Worten unter Code funktioniert (aber wäre ohne den expliziten Typen wirft nicht):

char c = '&'; 
byte b = (byte)c; 
short s = (short)c; 

Druck b oder s zeigt korrekt die Nummer 38, die das numerische Äquivalent (&) in Unicode.

Was bringt mich zu meiner eigentlichen Frage. Warum funktioniert das Folgende auch?

byte bc = '&'; 
short sc = '&'; 
System.out.println(bc); // Correctly displays number 38 on the console 
System.out.println(sc); // Correctly displays number 38 on the console 

Jetzt würde ich sicherlich verstehen, die folgende (was auch funktioniert):

byte bt = (byte)'&'; 
System.out.println(bt); // Correctly displays number 38 on the console 

Aber diese no-Compiler-Warnung char Byte (und kurz) "Sneak conversion" scheint nicht direkt zu mir.

Kann jemand erklären, warum dies erlaubt ist?

Könnte der Grund in der Interpretation der '<char>' selbst sein, so dass es tatsächlich nie zu einem Char primitiven Zustand, sondern wird als numerischer Wert (oktal oder hexadezimal etc.) behandelt?

+0

Einfach ausgedrückt, kann der Compiler bestimmen, ob eine Konstante sicher eingegrenzt werden kann. Es wird einen kompilierten Zeitfehler erzeugen, wenn die Präzision verloren geht, versuchen Sie dies zum Vergleich: byte b = '\ u20AC'; – Durandal

Antwort

5

Grundsätzlich gibt die specification of assignment conversion dass

Zusätzlich, wenn der Ausdruck eine Konstante ist Ausdruck (§15.28) von Typenbyte, short, char oder int:

eine Verengung primitiven Umwandlungs kann verwendet werden, wenn der Typ der -Variablen Byte, Kurz oder Char ist und der Wert des Konstanten-Ausdrucks im Typ der Variablen dargestellt werden kann.

Ihre '&' gerade "ein konstanter Ausdruck vom Typ byte, short, char oder int".

+1

Obwohl der Verweis korrekt ist (zur Zuweisungsspezifikation), ist der erste zitierte Absatz _nicht_ relevant. In diesen Zuordnungsbeispielen gibt es keine parametrisierten Typen. Nur der zweite Absatz gilt. –

1

Warum funktioniert das Folgende auch?

Da '&' ein konstanter Ausdruck ist, dessen Wert in byte passt.

JLS 14.4.2

Wenn ein declarator ein Initialisierungssignal Ausdruck hat, wird der Ausdruck ausgewertet, und sein Wert wird der Variablen zugewiesen.

JLS 5,2

Zuordnung Umwandlung erfolgt, wenn der Wert eines Ausdrucks zugeordnet ist (§15.26) auf eine Variable: die Art des Ausdrucks muß dem Typ der Variablen umgewandelt werden.

....

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

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

ich nicht diese explaination weiß, ist genug oder nicht, aber dieses Verhalten in der JLS definiert ist. Vom JLS, section 5.2:

Darüber hinaus, wenn der Ausdruck ein konstanter Ausdruck ist (§15.28) vom Typ byte, short, char oder int:

  • Eine Verengung primitive Umwandlung kann verwendet werden Wenn der Typ der Variablen byte, short oder char und der Wert ist, ist der konstante Ausdruck im Typ der Variablen darstellbar.
  • eine Verengung primitive Umwandlung durch eine Umwandlungs boxing gefolgt kann verwendet werden, wenn die Art der die Variable:
    • Byte und der Wert des konstanten Ausdrucks darstellbare in dem Typ-Byte ist.
    • Kurz und der Wert der Konstante Ausdruck ist in der Art kurz darstellbar.
    • Zeichen und der Wert der konstante Ausdruck ist darstellbar im Typ char.
+0

Es kommt von JLS, nicht von JVMS. – johnchen902

+0

Danke für die Erinnerung. @ johnchen902 – StarPinkER

0

Der Ausdruck '&', die für die variable bc in Ihrem Initialisierer ist ein konstanter Ausdruck. Der Ausdruck c, der in Ihrem Initialisierer für die Variablen b und s steht, ist kein konstanter Ausdruck. Java führt implizit einschränkende Konvertierungen von Primitiven durch, wenn der Kontext erfordert, wenn der Wert nur das Ergebnis eines konstanten Ausdrucks ist.

6

Dies wird Compile-Time-Verengung der Konstanten genannt. Es ist in Abschnitt 5 beschrieben.Language Specification 2 des Java:

Die Kompilierung-Verengung der Konstanten bedeutet, dass Code wie:

byte theAnswer = 42; 

erlaubt. Ohne die Einengung würde die Tatsache, dass das Integer-Literal 42 den Typ int hat, bedeuten, dass eine Umwandlung in Byte erforderlich wäre.

Das Gleiche gilt für Zeichenliterale: wenn sein Wert in einem byte passt, ist keine Konvertierung erforderlich ist; Wenn der Wert nicht passt, müssen Sie einen Cast einfügen oder Sie erhalten einen Kompilierungsfehler.

Zum Beispiel würde dies nicht kompilieren:

byte bc = '\uff12'; // Does not compile without a cast 

aber kompiliert fein:

byte bc = (byte)'\uff12'; 
Verwandte Themen