Warum erfordern Javas zusammengesetzte Zuweisungsoperatoren +=, -=, *=, /= nicht die Umwandlung von long in int?
Lesezeit: 7 Minuten
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.
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.
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
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.
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
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.rajkumar
Sie müssen aus werfen long Zu intexplicitly 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
slevy1
Das Problem liegt hier im Type Casting.
Wenn Sie int und long hinzufügen,
Das int-Objekt wird in long umgewandelt und beide werden addiert und Sie erhalten ein long-Objekt.
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
14506700cookie-checkWarum erfordern Javas zusammengesetzte Zuweisungsoperatoren +=, -=, *=, /= nicht die Umwandlung von long in int?yes
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