Unerwünschte Autobox-Magie auf Zahlen

8

Das folgende Programm druckt jeweils 'false' und 'true':

%Vor%

Es wird also kein Long, sondern ein Double sein. Es funktioniert jedoch wie vorgesehen in normalen Klassen: Haben

%Vor%

Dies wird 'wahr' drucken:

%Vor%

bedeutet, dass es nicht wie im obigen Beispiel funktioniert.

Ich bin mir sicher, dass etwas mit Autoboxen zu tun hat, aber ist es wirklich so, wie es funktionieren sollte? Warum benutzt sie Boxen, wenn die Number-Klasse eine Superklasse von Long und Double ist, sodass der Ausdruck zu Number? Ausgewertet werden kann?

Es ist wirklich ein Schmerz, denn wenn man das n druckt, druckt es als ein doppelter Wert. (Ich weiß, es ist leicht zu umgehen, aber hat mich verrückt gemacht)

    
poroszd 08.10.2012, 20:20
quelle

2 Antworten

7

Nehmen wir das Sprachanwaltsbuch hier heraus: JLS § 15.25

  

Der Typ eines bedingten Ausdrucks wird wie folgt bestimmt:

     
  • Wenn der zweite und der dritte Operand den gleichen Typ haben (was der Null-Typ sein kann), dann ist das der Typ des bedingten Ausdrucks.
  •   

Long und Double sind nicht vom selben Typ - trifft nicht zu.

  
  • Wenn einer der zweiten und dritten Operanden vom primitiven Typ T ist und der Typ des anderen Operators das Ergebnis der Anwendung der Boxenkonvertierung ist   (§5.1.7) zu T, dann ist der Typ des bedingten Ausdrucks T.
  •   

Kein Wert ist primitiv - trifft nicht zu.

  
  • Wenn einer der zweiten und dritten Operanden vom Null-Typ ist und der Typ des anderen ein Referenz-Typ ist, dann ist der Typ des   Bedingter Ausdruck ist dieser Referenztyp.
  •   

Kein Wert ist null - trifft nicht zu.

  
  • Andernfalls, wenn der zweite und der dritte Operand konvertierbare Typen haben ( §5.1.8 ) zu numerischen Typen, dann gibt es mehrere Fälle:      
    • [... Sonderfälle für byte / short / char und ihre Box-Äquivalente ...]
    •   
    • Andernfalls binäre numerische Werbung (§ 5.6. 2 ) wird auf die Operandentypen angewendet, und der Typ des bedingten Ausdrucks ist der hochgestufte Typ des zweiten und dritten Operanden.
    •   
  •   

Diese Regel trifft hier zu, was bedeutet, dass der Ergebnistyp des Bedingungsoperators so aussieht, als ob beide Werte entkoppelt wären. Die Annahme dahinter ist, dass sonst Number n = bool ? 1 : 2.0 und Number n = bool ? new Long(1) : new Double(2.0) andere Werte haben. Dieses Verhalten wäre auch unerwartet und - schlimmer - inkonsistent.

    
nd. 08.10.2012, 20:46
quelle
2

Es ist einfach  Schauen Sie auf den Byte-Code und Sie werden sehen (einfach Ihr Beispiel geändert)

%Vor%

Bytecode

_new 'java / lang / Lang'

%Vor%

Hauptpunkt ist l2d macht die nächsten Schritte

  

Nimmt eine lange Ganzzahl vom Stapel ab und wandelt sie in eine doppelte Genauigkeit um   Fließkommazahl, und schiebt den Doppelpunkt zurück auf den Stapel.   Beachten Sie, dass dies zu einem Verlust der Genauigkeit führen kann (der Signifikanz in a   Double ist 54 Bit, verglichen mit 64 Bit für den Long), aber nicht Verlust   von der Größenordnung (da der Bereich eines Doppelten größer ist als der Bereich von   eine lange). Die Rundung erfolgt im IEEE 754-Modus "Round-To-Nearest".

Und danach ist alles gut, also haben Sie Double Instanz, aber mit Long Value ! Wenn Sie in den Debug-Modus schauen, werden Sie sehen, dass unsere Nummer Double ist, aber Wert von Long. Sie beschreibt oben im Byte-Code

Wir können es im Byte-Code sehen

%Vor%     
Sergii Zagriichuk 08.10.2012 20:50
quelle

Tags und Links