Die Java-Fun Serie behandelt komische oder fragwürdige Eigenheiten der Programmiersprache Java.
♨️
Eine häufiges Szenario in der Programmierung ist, dass man zu einer Variablen etwas dazuaddieren oder davon abziehen möchte:
int balance = 100;int amount = 20;// guthaben auf konto einzahlenbalance = balance + amount;System.out.println("balance: " + balance);// balance: 120
Um solche Statements abzukürzen, gibt es in vielen Programmiersprachen, darunter auch in Java, den Compound Assignment Operator (Verbundzuweisungsoperator).
// lange Variante:balance = balance + amount;// kurze Variante mit Compound Assignment Operator:balance += amount;
Java ist eine streng typisierte Sprache und verhindert durch Typendefinitionen, dass wir als Programmierer offensichtliche Fehler machen. Ein Beispiel für einen solchen Fehler wäre das Addieren einer Dezimalzahl (float) zu einer Ganzzahl (int), da dies zum Verlust des Dezimalanteils führen würde. Java beschwert sich deshalb beim Kompilieren:
int balance = 100;float amount = 10.5f;// 💀 java: incompatible types: possible lossy conversion from float to intbalance = balance + amount;System.out.println("balance: " + balance);
Im oberen Beispiel wurde die lange Variante der Addierung genutzt.
Wie verhält sich der Compiler bei der kurzen Variante mit dem Compound Assignment Operator?
Man würde erwarten, dass es ebenfalls zu einer incompatible types
Fehlermeldung führt.
int balance = 100;float amount = 10.5f;// 💀?balance += amount;System.out.println("balance: " + balance);
Aber überraschenderweise funktioniert die Kompilierung 🤨 und das Ergebnis ist:
balance: 110
Die 0.5
sind also verloren gegangen.
Die Erklärung, warum dies funktioniert, findet sich in der JLS (Java Language Specification):
A compound assignment expression of the form
E1 op= E2
is equivalent toE1 = (T) ((E1) op (E2))
,where
T
is the type ofE1
, except thatE1
is evaluated only once
Zusammengefasst: Compound Assignment Operators führen automatisch eine verdeckte Typenumwandlung durch.
int balance = 100;float amount = 10.5f;// so steht es im codebalance += amount;// das macht der compiler darausbalance = (int)(balance + amount);
Ein weiteres WTF Beispiel:
char c = 'A';c *= 1.5;System.out.println(c);// 'a'
¯\_(ツ)_/¯
In anderen Sprachen wie C#, funktioniert das nicht so einfach.
Siehe auch: