it-swarm.com.de

Warum erfordern Javas Operatoren für + =, - =, * =, / = zusammengesetzte Zuweisungen kein Casting?

Bis heute dachte ich, dass 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 wird i = i + j; nicht kompiliert, aber i += j; wird gut kompiliert.

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

3515
Honza Brabec

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

Ein zusammengesetzter Zuweisungsausdruck der Form E1 op= E2 entspricht E1 = (T)((E1) op (E2)), wobei T der Typ von E1 ist, mit der Ausnahme, dass E1 nur einmal ausgewertet wird.

Ein Beispiel aus §15.26.2

[...] der folgende Code ist korrekt:

short x = 3;
x += 4.6;

und ergibt x mit dem Wert 7, weil es äquivalent ist zu:

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

Mit anderen Worten, Ihre Annahme ist richtig.

2375
Lukas Eder

Ein gutes Beispiel für dieses Casting 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'
467
Peter Lawrey

Sehr gute frage Die Java Language Spezifikation bestätigt Ihren Vorschlag.

Der folgende Code ist beispielsweise korrekt:

short x = 3;
x += 4.6;

und ergibt x mit dem Wert 7, weil es äquivalent ist zu:

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

Ja,

im Grunde, wenn wir schreiben

i += l; 

der Compiler konvertiert dies in

i = (int)(i + l);

Ich habe gerade den .class -Dateicode überprüft.

Wirklich eine gute Sache zu wissen

177
Umesh Awasthi

sie müssen von long nach intexplicitly im Falle von i = i + l umwandeln, dann wird es kompiliert und gibt die korrekte Ausgabe. mögen

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.

im Fall von += funktioniert dies jedoch einwandfrei, da der Operator implizit die Typumwandlung von Typ der rechten Variablen zu Typ der linken Variablen ausführt und daher nicht explizit umgewandelt werden muss.

89
dku.rajkumar

Das Problem hierbei ist das Typgießen.

Wenn Sie int und long hinzufügen,

  1. Das int-Objekt wird in long umgewandelt und beide werden hinzugefügt, und Sie erhalten ein long-Objekt.
  2. long object kann aber nicht implizit nach int geworfen werden. Also muss man das explizit machen.

Aber += ist so codiert, dass es Typ-Casting ausführt. i=(int)(i+m)

60

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

 Byte -> kurz -> int -> lang -> float -> double. 

Das gleiche wird nicht umgekehrt funktionieren. Zum Beispiel können wir ein Long nicht automatisch in ein Int konvertieren, da das Erste mehr Speicherplatz benötigt als das Zweite und folglich Informationen verloren gehen können. Um eine solche Konvertierung zu erzwingen, müssen wir eine explizite Konvertierung durchführen.
Typumwandlung

51
tinker_fairy

Manchmal kann eine solche Frage bei einem Interview gestellt werden.

Zum Beispiel, wenn Sie schreiben:

int a = 2;
long b = 3;
a = a + b;

es gibt keine automatische Typumwandlung. In C++ gibt es keinen Fehler beim Kompilieren des obigen Codes, aber in Java erhalten Sie etwas wie Incompatible type exception.

Um dies zu vermeiden, müssen Sie Ihren Code folgendermaßen schreiben:

int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
43
Stopfan

Der Hauptunterschied besteht darin, dass bei a = a + b keine Typumwandlung stattfindet, und der Compiler wird deshalb wütend, wenn Sie keine Typumwandlung durchführen. Aber mit a += b tippt es tatsächlich b in einen Typ, der mit a kompatibel ist. Also, wenn du es tust

int a=5;
long b=10;
a+=b;
System.out.println(a);

Was Sie wirklich tun, ist:

int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);
21
takra

Feiner Punkt hier ...

Es gibt eine implizite Typumwandlung für i+j, wenn j ein Double und i ein Int ist. Java ALWAYS wandelt eine Ganzzahl in ein Double um, wenn zwischen ihnen eine Operation besteht.

Zur Verdeutlichung von i+=j, wobei i eine Ganzzahl und j ein Double ist, kann beschrieben werden als

i = <int>(<double>i + j)

Siehe: diese Beschreibung des impliziten Castings

In diesem Fall sollten Sie aus Gründen der Übersichtlichkeit j in (int) tippen.

11
Gabe Nones

Java Language Specification definiert E1 op= E2 als äquivalent zu E1 = (T) ((E1) op (E2)), wobei T eine Art von E1 ist und E1 einmal ausgewertet wird .

Das ist eine technische Antwort, aber Sie fragen sich vielleicht, warum das so ist. Betrachten wir das folgende Programm.

public class PlusEquals {
    public static void main(String[] args) {
        byte a = 1;
        byte b = 2;
        a = a + b;
        System.out.println(a);
    }
}

Was druckt dieses Programm?

Hast du 3 erraten? Schade, dieses Programm lässt sich nicht kompilieren. Warum? Nun, es kommt vor, dass das Hinzufügen von Bytes in Java definiert ist, um ein int zurückzugeben . Ich glaube, das lag daran, dass die virtuelle Maschine Java keine Byte-Operationen definiert, um Byte-Codes zu speichern (es gibt immerhin eine begrenzte Anzahl davon). Die Verwendung von Ganzzahloperationen ist stattdessen ein Implementierungsdetail in a Sprache.

Aber wenn a = a + b nicht funktioniert, würde dies bedeuten, dass a += b niemals für Bytes funktioniert, wenn E1 += E2 als E1 = E1 + E2 definiert wurde. Wie das vorige Beispiel zeigt, wäre dies tatsächlich der Fall. Als Hack, mit dem der Operator += für Bytes und Shorts funktioniert, ist eine implizite Besetzung erforderlich. Es ist kein so großartiger Hack, aber während der Arbeit an Java 1.0 lag der Fokus darauf, die Sprache von Anfang an zu veröffentlichen. Aus Gründen der Abwärtskompatibilität konnte dieser in Java 1.0 eingeführte Hack nicht entfernt werden.

2
Konrad Borowski