Frage

In Java, wenn Sie das tun

int b = 0;
b = b + 1.0;

Sie erhalten einen möglichen Verlust an Präzision Fehler. Aber warum ist es, dass, wenn Sie tun

int b = 0;
b += 1.0;

Es gibt keinen Fehler?

War es hilfreich?

Lösung

Das ist, weil b += 1.0; äquivalent zu b = (int) ((b) + (1.0));. Die Verengung primitive Umwandlung (JLS 5.1.3) wird in der Verbindung Zuweisungsoperation versteckt.

JLS 15.26. 2 Verbindung Zuweisungsoperator (JLS Dritte Ausgabe):

  

Eine Verbindung Zuweisungsausdruck von der Form E1 op = E2 entspricht E1 = (T) ((E1) op (E2)) , wobei T ist die Art von E1 , mit der Ausnahme, dass E1 wird nur einmal ausgewertet.

     

Zum Beispiel der folgende Code korrekt ist:

short x = 3;
x += 4.6;
     

und Ergebnisse in x den Wert 7 hat, weil es entspricht:

short x = 3;
x = (short)(x + 4.6);

Dies erklärt auch, warum die folgenden Code kompiliert:

byte b = 1;
int x = 5;
b += x; // compiles fine!

Aber das bedeutet nicht:

byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!

Sie müssen in diesem Fall explizit Stimmen:

byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!

Es ist erwähnenswert, dass die implizite Umwandlung in Verbindung Zuweisungen ist das Thema Puzzle 9: Tweedledum aus dem wunderbaren Buch Java Puzzlers . Hier sind einige Auszüge aus dem Buch (leicht zur Kürze bearbeitet):

  

Viele Programmierer denken, dass x += i; ist einfach eine Abkürzung für x = x + i;. Das ist nicht ganz richtig: wenn der Typ des Ergebnisses ist breiter als die der variablen, führt die Verbindung Zuweisungsoperator einer stille Verengung primitive Umwandlung

.      

Um unangenehme Überraschungen zu vermeiden, verwenden Sie keine Verbindung Zuweisungsoperator auf Variablen vom Typ byte, short oder char. Bei der Verwendung von Verbindung Zuweisungsoperatoren auf Variablen vom Typ int, sicherzustellen, dass der Ausdruck auf der rechten Seite ist nicht vom Typ long, float oder double. Bei der Verwendung von Verbindung Zuweisungsoperatoren auf Variablen vom Typ float, sicherzustellen, dass der Ausdruck auf der rechten Seite ist nicht vom Typ double. Diese Regeln sind ausreichend, um die Compiler zu erzeugen gefährliche Verengung Abgüsse zu verhindern.

     

Für Sprachdesigner, ist es wahrscheinlich ein Fehler für Verbindung Zuweisungsoperator zu unsichtbaren Abgüsse zu erzeugen; Verbindung Zuweisungen, bei denen die Variablen einen engeren Typen als das Ergebnis der Berechnung haben, sollten wahrscheinlich illegal sein.

Der letzte Absatz ist bemerkenswert: C # viel strenger in dieser Hinsicht ist (siehe C # Language Specification 7.13.2 Verbindung Zuordnung ).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top