2015-08-25 1 views
100

Wenn short automatisch auf int in arithmetischen Operationen gefördert, warum ist dann:Warum ist "short thirty = 3 * 10" eine legale Aufgabe?

short thirty = 10 * 3; 

Eine rechtliche Zuordnung zum short Variable thirty?

wiederum folgt aus:

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

sowie das:

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

nicht kompilieren, weil ein int Wert zu einem short Zuordnung ist nicht erlaubt, ohne wie erwartet zu Gießen.

Gibt es etwas besonderes über numerische Literale?

+23

'short dreißig = 10 * 3;' wird sehr wahrscheinlich durch 'short 30 = 30;' durch den Compiler ersetzt, was dann eine gültige Aussage ist. (Ich müsste allerdings den relevanten JLS Abschnitt nachschlagen). – Thomas

+0

Der Compiler berechnet '10 * 3' und initialisiert die Variable mit dem Ergebnis. In Ihrem nicht funktionierenden Beispiel findet die Berechnung zur Laufzeit statt, wo die JVM die Abkürzung abgibt. – Felix

+1

Nicht ganz ein Betrogener. Dies ist mehr über Kompilierzeitliterale. – Bathsheba

Antwort

136

Da der Compiler ersetzt 10*3 durch 30 bei Kompilierzeit selbst. Also effektiv: short thirty = 10 * 3 wird zur Kompilierzeit berechnet.

Try ten und three-final short Veränderung (so dass sie Zeitkonstanten kompilieren) und sehen, was passiert: P

Untersuchen Byte-Code für beide verisions mit javap -v (10*3 und final short). Sie werden sehen, dass es wenig Unterschied gibt.

Ok, Also, hier ist der Byte-Code-Unterschied für verschiedene Fälle.

Fall -1:

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

Byte-Code:

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

Kasten -2:

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

Byte-Code:

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 

Hülle -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 obigen Fall, 10 und 3 werden von den lokalen Variablen genommen s1 und s2

+16

gemocht werden. Versuchen Sie, zehn und drei zu" final short "Übungen zu ändern :) –

+1

@SergeyPauk - Das ist wirklich wichtig beim Verständnis der Kompilierzeit Konstanten .. gilt für alle Primitiven (Strings als auch ..) :) – TheLostMind

+1

@TheLostMind Ich würde vorschlagen, eine bessere Formulierung 'Sie werden sehen, dass es keinen Unterschied (zwischen diesen beiden Zeilen in der dekompilierten Code)' Ursache ist das nicht dein Punkt? –

18

Ja, es ist etwas Besonderes mit dem literalen Fall passiert: 10 * 3 wird bei compile Zeit ausgewertet werden. Sie benötigen 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 mit final markiert wären.

0

Die folgende answer fügt den JLS Abschnitt und einige Details über dieses Verhalten.

Per JLS §15.2 - Forms of Expressions

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

Verwandte Themen