Warum ist „kurz dreißig = 3 * 10“ eine legale Zuordnung?

Lesezeit: 3 Minuten

Wenn short wird automatisch befördert int in arithmetischen Operationen, warum ist dann:

short thirty = 10 * 3;

Eine rechtliche Abtretung an die short Variable thirty?

Das wiederum:

short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

so gut wie das:

int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

wird nicht kompiliert, da eine zugewiesen wird int Wert zu a short ist nicht erlaubt, ohne wie erwartet zu werfen.

Gibt es etwas Besonderes bei numerischen Literalen?

  • short thirty = 10 * 3; wird höchstwahrscheinlich ersetzt durch short thirty = 30; vom Compiler, was dann eine gültige Aussage ist. (Ich müsste jedoch den relevanten JLS-Abschnitt nachschlagen).

    – Thomas

    25. August 2015 um 12:02 Uhr


  • Der Compiler rechnet 10 * 3 und initialisiert die Variable mit dem Ergebnis. In Ihrem nicht funktionierenden Beispiel erfolgt die Berechnung zur Laufzeit, wo die JVM den Kurzschluss auslöst.

    – Felix

    25. August 2015 um 12:03 Uhr


  • Ich denke, dies ist ein Duplikat von stackoverflow.com/questions/30346587/java-char-to-byte-casting oder stackoverflow.com/questions/9379983/… . Allerdings: Beachten Sie das final int ten = 10; final int three = 3; short thirty = ten * three; kompiliert gut.

    – Marco13

    25. August 2015 um 12:46 Uhr


  • If short is automatically promoted to int in arithmetic operations – das ist nicht relevant. Weder 10 Noch 3 sind Shorts noch werden sie gefördert, sie sind wörtlich.

    – Matthäus Lesen

    25. August 2015 um 18:36 Uhr

  • @MatthewRead: Aber selbst als Literale müssen sie als bestimmter Datentyp ausgewertet werden, oder? Also stimmt das 10 und 3 werden bewertet als ints vom Compiler?

    – LarsH

    26. August 2015 um 16:31 Uhr

Benutzer-Avatar
DerVerloreneGeist

Weil der Compiler ersetzt 10*3 mit 30 at Kompilierzeit selbst. Also effektiv: short thirty = 10 * 3 wird zur Kompilierzeit berechnet.

Versuchen Sie, sich zu ändern ten und three zu final short (wodurch sie Zeitkonstanten kompilieren) und sehen, was passiert: P

Untersuchen Sie den Bytecode mit javap -v für beide Versionen (10*3 und final short). Sie werden sehen, dass es kaum Unterschiede gibt.

Ok, hier ist also der Bytecode-Unterschied für verschiedene Fälle.

Fall 1 :

Java-Code: main() {short s = 10*3; }

Bytecode:

stack=1, locals=2, args_size=1
         0: bipush        30  // directly push 30 into "s"
         2: istore_1      
         3: return   

Fall -2 :

public static void main(String arf[])  {
   final short s1= 10;
   final short s2 = 3;
   short s = s1*s2;
}

Bytecode:

  stack=1, locals=4, args_size=1
         0: bipush        10
         2: istore_1      
         3: iconst_3      
         4: istore_2      
         5: bipush        30 // AGAIN, push 30 directly into "s"
         7: istore_3      
         8: return   

Fall -3 :

public static void main(String arf[]) throws Exception {
     short s1= 10;
     short s2 = 3;
     int s = s1*s2;
}

Byte-Code :

stack=2, locals=4, args_size=1
         0: bipush        10  // push constant 10
         2: istore_1      
         3: iconst_3        // use constant 3 
         4: istore_2      
         5: iload_1       
         6: iload_2       
         7: imul          
         8: istore_3      
         9: return 

Im oben genannten Fall 10 und 3 werden den lokalen Variablen entnommen s1 und s2

  • gefallen Try changing ten and three to final short Übung 🙂

    – S. Pauk

    25. August 2015 um 12:19 Uhr

  • @SergeyPauk – Das ist wirklich wichtig für das Verständnis von Kompilierzeitkonstanten. Gilt für alle Primitiven (auch Strings..) 🙂

    – TheLostMind

    25. August 2015 um 12:22 Uhr


  • @TheLostMind Ich würde eine bessere Formulierung vorschlagen you will see that there's no difference (between those two lines in the decompiled code) Denn ist das nicht dein Punkt?

    – S. Pauk

    25. August 2015 um 12:59 Uhr


  • Amüsanterweise bedeutet dies auch das case 10*3: und ähnliches ist in einem Switch-Konstrukt zulässig.

    – Deckengecko

    25. August 2015 um 15:33 Uhr

  • Und ähnlich in Aufzählungskonstrukten. Tatsächlich ist die Verwendung von Dingen wie 1 << 5 für Bitfeld-Aufzählungskonstanten idiomatisch.

    – Bathseba

    25. August 2015 um 17:18 Uhr


Benutzer-Avatar
Bathseba

Ja, es gibt etwas Besonderes mit dem wörtlichen Fall: 10 * 3 wird mit bewertet kompilieren Zeit. Sie brauchen also keine explizite (short) Konvertierung für multiplizierte Literale.

ten * three ist nicht zur Kompilierzeit auswertbar und benötigt daher eine explizite Konvertierung.

Es wäre eine andere Sache, wenn ten und three markiert waren final.

Benutzer-Avatar
Nikolaus Henneaux

Die folgende Antwort fügt den JLS-Abschnitt und einige Details zu diesem Verhalten hinzu.

Gem JLS §15.2 – Ausdrucksformen

Einige Ausdrücke haben einen Wert, der zur Kompilierzeit bestimmt werden kann. Dies sind konstante Ausdrücke (§15.28).

1294280cookie-checkWarum ist „kurz dreißig = 3 * 10“ eine legale Zuordnung?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy