Frage

Zu meinem Erstaunen stellt sich heraus, dass der folgende Code ohne Warnungen kompiliert wird:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value += increment;
}

Dies führt jedoch erwartungsgemäß zu einem Fehler bei der Kompilierung:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value = value + increment;
}

Ich habe es überprüft und tatsächlich hat das JLS (Abschnitt 15.26.2) Folgendes zu sagen:

Eine Verbindungszuordnungsexpression des Formulars E1 Op = E2 entspricht E1 = (t) ((E1) op (e2)), wobei t die Art von E1 ist, außer dass E1 nur einmal bewertet wird.

Das kommt mir lächerlich vor.Warum hatten sie das Bedürfnis, hier explizit zu besetzen?Es scheint, dass die automatische Typkonvertierung die Erweiterung sowieso bewältigt hätte, und eine automatische Verengung auf diese Weise führt mit ziemlicher Sicherheit zu einem Ganzzahlüberlauf.

War es hilfreich?

Lösung

hier ist einsErläuterung:

Wenn Sie einen Auftrag (das erste Code-Snippet) durchführen, erzwingt die Java das Tippen, da die LHS und RHS sehr gut voneinander unabhängig sein können.

aber der Compound-Operator ist mehr ein inkrementeller Betreiber.Das +=. ändert den Wert der Variablen beteiligt, anstatt ein neues zuzuweisen Wert auf die Variable.Wenn Sie sich ändern ein Byte erwartet ein Byte als Ergebnis.Um das Leben zu erleichtern, tut Java eine implizite Typumwandlung für Compound-Operatoren, weil sie sind Modifikatoren.

Andere Tipps

Die zusammengesetzten Zuweisungsoperatoren werden vom JLS angegeben (15.26.2) wie folgt:

„Ein zusammengesetzter Zuweisungsausdruck der Form E1 op= E2 ist äquivalent zu

      E1 = (T)((E1) op (E2))`, 

wobei T der Typ von E1 ist, mit der Ausnahme, dass E1 nur einmal ausgewertet wird.“

In diesem Fall ist E1 vom Typ int E2 ist vom Typ long, und op ist +.Das ist also äquivalent zu:

value = (int)(value + increment);

Die Hinzufügung eines int und ein long gibt ein long das wird dann auf an zurückgeworfen int vor dem Einsatz.Das ist alles in Ordnung, daher kein Kompilierungsfehler.

Der Unterschied zwischen dieser und der einfachen Zuweisung (d. h. value = value + increment;), liegt darin, dass die einfache Zuweisung keine Typumwandlung hat.


OK, also Warum haben sie es so definiert?

Ich denke, der Grund liegt darin, dass Beispiele wie dieses funktionieren:

    byte b = ...
    b += 1;

Ohne die Typisierung, b += 1 wäre ein Kompilierungsfehler und Sie müssten ihn wie folgt schreiben:

    b += (byte) 1;

Dieser Link hat das Problem analysiert, das Sie aufgenommen haben.

Variierendes Verhalten für mögliche Präzisionsverluste

, um unangenehme Überraschungen zu vermeiden, nicht Verwenden Sie zusammengesetzte Zuordnungsbediener auf Variablen des Typbytes, kurz oder verkohlen.Bei Verwendung der zusammengesetzten Zuordnung Betreiber auf Variablen des Typs int, Stellen Sie sicher, dass der Ausdruck auf der rechte Seite ist nicht vom Typ Long, Schwimmen oder doppelt.Bei Verwendung der Verbindung Zuweisungsbetreiber auf Variablen von Typ Float, sorgen dafür, dass der Ausdruck auf der rechten Seite ist nicht der Typ doppelt.Diese Regeln reichen aus ausreichen verhindern, dass der Compiler generiert gefährliche Verengungsgüsse.

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