Warum erfordern Javas zusammengesetzte Zuweisungsoperatoren +=, -=, *=, /= nicht die Umwandlung von long in int?

Lesezeit: 7 Minuten

Benutzeravatar von Honza Brabec
Honza Brabec

Bis heute dachte ich zum Beispiel:

i += j;

War nur eine Abkürzung für:

i = i + j;

Aber wenn wir das versuchen:

int i = 5;
long j = 8;

Dann i = i + j; wird aber nicht kompiliert i += j; lässt sich gut kompilieren.

Bedeutet das tatsächlich? i += j; ist eine Abkürzung für so etwas
i = (type of i) (i + j)?

  • Ich bin überrascht, dass Java dies zulässt, da es eine strengere Sprache als seine Vorgänger ist. Fehler bei der Umwandlung können zu einem kritischen Ausfall führen, wie es bei Ariane5 Flight 501 der Fall war, wo eine 64-Bit-Float-Umwandlung in eine 16-Bit-Ganzzahl zum Absturz führte.

    – SQLDiver

    5. Januar 2015 um 16:31


  • In einem in Java geschriebenen Flugsteuerungssystem wäre dies Ihre geringste Sorge @SQLDiver

    – Ross Drew

    2. November 2015 um 9:24

  • Eigentlich i+=(long)j; Lässt sich sogar gut kompilieren.

    – Tharindu Sathischandra

    18. März 2016 um 7:45 Uhr

  • Das ständige Streben einer Gruppe von Entwicklern nach Genauigkeit und einer anderen nach Benutzerfreundlichkeit ist wirklich interessant. Wir brauchen fast zwei Versionen der Sprache, eine erstaunlich präzise und eine einfach zu verwendende. Wenn Java aus beiden Richtungen vorangetrieben wird, wird es für beide Gruppen ungeeignet.

    – Bill K

    19. September 2017 um 16:03 Uhr


  • Wenn es einen Guss erfordern würde, wo würden Sie es hinstellen? i += (int) f; wandelt f vor der Addition um, daher ist es nicht äquivalent. (int) i += f; wandelt das Ergebnis nach der Zuweisung um, auch nicht äquivalent. Es gäbe keinen Platz für eine Umwandlung, die bedeuten würde, dass Sie den Wert nach dem Hinzufügen, aber vor der Zuweisung umwandeln möchten.

    – Norill-Sturm

    24. Okt. 2018 um 13:09 Uhr

Benutzer-Avatar von Lukas Eder
Lukas Eder

Wie immer bei diesen Fragen hält das JLS die Antwort parat. In diesem Fall §15.26.2 Zusammengesetzte Zuweisungsoperatoren. Ein Auszug:

Ein zusammengesetzter Zuweisungsausdruck des Formulars E1 op= E2 ist äquivalent zu E1 = (T)((E1) op (E2))Wo T ist die Art von E1außer dass E1 wird nur einmal ausgewertet.

Ein Beispiel zitiert aus §15.26.2

[…] Der folgende Code ist korrekt:

short x = 3;
x += 4.6;

und führt dazu, dass x den Wert 7 hat, weil es äquivalent ist zu:

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

Mit anderen Worten: Ihre Annahme ist richtig.

  • So i+=j kompiliert, wie ich es selbst überprüft habe, aber es würde zu einem Präzisionsverlust führen, oder? Wenn das der Fall ist, warum lässt es das dann nicht auch in i=i+j zu? Warum uns da nerven?

    – bad_keypoints

    22. September 2012 um 6:07 Uhr

  • @ronnieaka: Ich vermute, dass die Sprachdesigner in einem Fall das Gefühl hatten (i += j), ist es sicherer anzunehmen, dass der Präzisionsverlust erwünscht ist, im Gegensatz zum anderen Fall (i = i + j)

    – Lukas Eder

    22. September 2012 um 8:31 Uhr

Benutzer-Avatar von Peter Lawrey
Peter Lawrey

Ein gutes Beispiel für diese Umwandlung ist die Verwendung von *= oder /=

byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57

oder

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

oder

char ch="0";
ch *= 1.1;
System.out.println(ch); // prints '4'

oder

char ch="A";
ch *= 1.5;
System.out.println(ch); // prints 'a'

  • @AkshatAgarwal ch ist ein Char. 65 * 1,5 = 97,5 -> Verstanden?

    – Sajal Dutta

    5. Mai 2014 um 22:07 Uhr

  • Ja, aber ich kann mir vorstellen, dass ein Anfänger hierherkommt, dies liest und denkt, dass man jedes Zeichen von Großbuchstaben in Kleinbuchstaben umwandeln kann, indem man es mit 1,5 multipliziert.

    – Dawud ibn Kareem

    28. Mai 2014 um 9:25

  • @DavidWallace Jedes Zeichen, solange es ist A 😉

    – Peter Lawrey

    28. Mai 2014 um 12:56

  • @PeterLawrey & @DavidWallace Ich werde deine verraten Geheimnisch += 32 =D

    – Minhas Kamal

    16. März 2016 um 5:29


Thirlers Benutzeravatar
Thirler

Sehr gute Frage. Der Java-Sprachspezifikation bestätigt deinen Vorschlag.

Beispielsweise ist der folgende Code korrekt:

short x = 3;
x += 4.6;

und führt dazu, dass x den Wert 7 hat, weil es äquivalent ist zu:

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

  • Oder lustiger: „int x=33333333; x+=1.0f;“.

    – Superkatze

    20. April 2017 um 19:31 Uhr

  • @supercat , was für ein Trick ist das? Eine erweiternde Konvertierung, die falsch gerundet ist, gefolgt von einer Addition, die das Ergebnis nicht wirklich verändert, wird erneut in int umgewandelt, um ein Ergebnis zu erzeugen, das für den normalen menschlichen Verstand höchst unerwartet ist.

    – neXus

    21. September 2018 um 12:33 Uhr

  • @neXus: Meiner Meinung nach hätten die Konvertierungsregeln behandelt werden sollen double->float als Erweiterung, auf der Grundlage dieser Werte des Typs float identifizieren reelle Zahlen weniger spezifisch als solche vom Typ double. Wenn man es sich ansieht double als vollständige Postanschrift und float B. eine fünfstellige Postleitzahl, ist es möglich, eine Anfrage nach einer Postleitzahl mit einer vollständigen Adresse zu erfüllen, es ist jedoch nicht möglich, eine Anfrage nach einer vollständigen Adresse mit nur einer Postleitzahl genau zu spezifizieren. Das Konvertieren einer Straßenadresse in eine Postleitzahl ist ein verlustbehafteter Vorgang. Aber

    – Superkatze

    21. September 2018 um 15:05 Uhr

  • …jemand, der eine vollständige Adresse benötigt, würde im Allgemeinen nicht nur nach einer Postleitzahl fragen. Konvertierung von float->double entspricht der Umwandlung der US-Postleitzahl 90210 in „US Post Office, Beverly Hills CA 90210“.

    – Superkatze

    21. September 2018 um 15:07 Uhr

Benutzeravatar von Umesh Awasthi
Umesh Awasthi

Ja,

im Grunde, wenn wir schreiben

i += l; 

Der Compiler konvertiert dies in

i = (int)(i + l);

Ich habe gerade nachgeschaut .class Dateicode.

Wirklich gut zu wissen

dku.rajkumars Benutzeravatar
dku.rajkumar

Sie müssen aus werfen long Zu int explicitly im Falle von i = i + l Dann wird es kompiliert und liefert die korrekte Ausgabe. wie

i = i + (int)l;

oder

i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.

aber im Falle von += Es funktioniert einfach gut, weil der Operator implizit die Typumwandlung vom Typ der rechten Variablen zum Typ der linken Variablen durchführt und daher keine explizite Umwandlung erfordert.

  • In diesem Fall könnte die „implizite Besetzung“ verlustbehaftet sein. In Wirklichkeit, wie @LukasEder in seiner Antwort feststellt, ist die Besetzung so int ist durchgeführt nach Die +. Der Compiler würde (sollte?) eine Warnung ausgeben, wenn er das tatsächlich umgesetzt hätte long Zu int.

    – Romain

    3. Januar 2012 um 10:17


Benutzeravatar von slevy1
slevy1

Das Problem liegt hier im Type Casting.

Wenn Sie int und long hinzufügen,

  1. Das int-Objekt wird in long umgewandelt und beide werden addiert und Sie erhalten ein long-Objekt.
  2. aber ein langes Objekt kann nicht implizit in int umgewandelt werden. Sie müssen das also explizit tun.

Aber += ist so codiert, dass es eine Typumwandlung durchführt. i=(int)(i+m)

  • In diesem Fall könnte die „implizite Besetzung“ verlustbehaftet sein. In Wirklichkeit, wie @LukasEder in seiner Antwort feststellt, ist die Besetzung so int ist durchgeführt nach Die +. Der Compiler würde (sollte?) eine Warnung ausgeben, wenn er das tatsächlich umgesetzt hätte long Zu int.

    – Romain

    3. Januar 2012 um 10:17


In Java werden Typkonvertierungen automatisch durchgeführt, wenn der Typ des Ausdrucks auf der rechten Seite einer Zuweisungsoperation sicher auf den Typ der Variablen auf der linken Seite der Zuweisung heraufgestuft werden kann. Somit können wir sicher zuordnen:

 byte -> short -> int -> long -> float -> double. 

Andersherum wird es nicht funktionieren. Beispielsweise können wir einen Long-Wert nicht automatisch in einen Int-Wert umwandeln, da der erste mehr Speicherplatz benötigt als der zweite und daher möglicherweise Informationen verloren gehen. Um eine solche Konvertierung zu erzwingen, müssen wir eine explizite Konvertierung durchführen.
Typ – Konvertierung

  • Hey, aber long ist 2 mal größer als float.

    – Anzeigename

    30. August 2013 um 10:17 Uhr

  • A float kann nicht alles mögliche halten int Wert und a double kann nicht alles mögliche halten long Wert.

    – Alex MDC

    9. September 2013 um 20:41

  • Was meinst du mit „sicher konvertiert“? Aus dem letzten Teil der Antwort kann ich schließen, dass Sie die automatische Konvertierung (implizite Umwandlung) gemeint haben, was im Fall von float -> long natürlich nicht zutrifft. float pi = 3,14f; langes b = pi; führt zu einem Compilerfehler.

    – Lukas

    7. November 2013 um 13:21 Uhr


  • Es wäre besser, Gleitkomma-Primitivtypen von Ganzzahl-Primitivtypen zu unterscheiden. Sie sind nicht dasselbe.

    – ThePyroEagle

    22. Dezember 2015 um 20:59

  • Java verfügt über vereinfachte Konvertierungsregeln, die die Verwendung von Umwandlungen in vielen Mustern erfordern, bei denen das Verhalten ohne Umwandlungen sonst den Erwartungen entsprechen würde, in vielen Mustern, die normalerweise fehlerhaft sind, sind jedoch keine Umwandlungen erforderlich. Ein Compiler akzeptiert dies beispielsweise double d=33333333+1.0f; klaglos, auch wenn das Ergebnis 33333332.0 wahrscheinlich nicht das sein würde, was beabsichtigt war (übrigens wäre die rechnerisch korrekte Antwort von 33333334.0f als eines von beiden darstellbar). float oder int).

    – Superkatze

    20. April 2017 um 19:40 Uhr

1450670cookie-checkWarum erfordern Javas zusammengesetzte Zuweisungsoperatoren +=, -=, *=, /= nicht die Umwandlung von long in int?

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

Privacy policy