Die Zuweisung als Wirkoperator in Java
Eine Variable ist ein Teil des Speichers, der zu jedem Zeitpunkt genau einen Wert des Typs der Variablen speichern kann.
Die Auswertung eines Zuweisungsausdrucks hat auch eine Wirkung:
Der Wert der rechten Seite wird zum neuen Wert der Variablen, deren Name auf der linken Seite angegeben ist.
Der Wert einer Variablen, die als Ausdruck verwendet wird, ist der zuletzt durch eine Initialisierung oder eine Zuweisung in die Variable geschriebene Wert.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 7;
java.lang.System.out.println( v );
java.lang.System.out.println( v = 4 );
java.lang.System.out.println( v = 5 );
java.lang.System.out.println( v ); }}transcript
7
4
5
5
Bei der Zuweisung wird zuerst die rechte Seite ausgewertet. Dann wird der Wert, der sich bei der Auswertung der rechten Seite ergeben hat, in den Typ der Variablen auf der linken Seite gewandelt und in die Variable auf der linken Seite geschrieben. Die Zuweisung wird also von rechts nach links abgearbeitet.
Die Zuweisung ist ein Wertwirkoperator : Sie hat einen Wert und eine Wirkung zugleich.
Das Gleichheitszeichen in einer Zuweisung hat darin auch nicht dieselbe Bedeutung wie das Gleichheitszeichen in einer mathematischen Gleichung.
Lesen und Schreiben
Bei der Auswertung des Namens einer Variablen innerhalb eines Ausdrucks kommt es in der Regel zu einer Leseoperation, also einem Lesezugriff auf die Variable, in dessen Zuge der Wert der Variablen ausgelesen und als Wert des Namens verwendet wird.
Falls der Name einer Variablen jedoch auf der linken Seite eines Zuweisungsausdrucks verwendet wird, kommt es bei der Auswertung dieses Zuweisungsausdruckes zu einer Lösch- und Schreiboperation, bei welcher der Wert des Ausdrucks der rechten Seite nach einer Wandlung in den Typ der Variablen in die Variable geschrieben wird.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 7;
java.lang.System.out.println( v /* <-- Leseoperation */ );
java.lang.System.out.println( v = 4 /* <-- Loesch- und Schreiboperation */ );
java.lang.System.out.println( v /* <-- Leseoperation */ ); }}transcript
7
4
4
Die Schreiboperation einer Variablen ist auch gleichzeitig immer eine Löschoperation, da durch sie der vorige Wert der Variablen verloren geht. (Sogar, wenn der gleiche Wert wieder in die Variable geschrieben wird, kann dabei unter Umständen die Information, daß dies der frühere Wert war, verlorengehen.)
Der Wert einer Zuweisung
Der Wert einer Zuweisung ist der Wert der Variablen der linken Seite nach der Zuweisung.
(Zuvor wurde dies beschrieben, indem gesagt wurde, daß der Wert einer Zuweisung der Wert der rechten Seite gewandelt in den Typ der linken Seite sei.)
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ double v = 7;
java.lang.System.out.println( v = 2 ); }}transcript
2.0
Konstanten und Variablen
Wir sehen eine Konstante, die mit beispielsweise »final int n = 9;« deklariert wurde, als einen Namen für einen Wert an.
Eine Variable, die mit beispielsweise »int n = 9;« deklariert wurde, ist hingegen ein Name für einen Speicherplatz.
Die Bezeichnung „Konstante“ ist in Java für eine final-Variable nicht allgemein üblich, aber man kann auf jeden Fall eines sagen:
Die Kennzeichnung einer Variablen mit »final« innerhalb ihrer Deklaration verbietet es, daß der Name jener Variablen im Güitigkeitsbereich jener Deklaration als linke Seite einer Zuweisung verwendet wird.
Wir haben jetzt gesehen, daß der Wert einer Variablen veränderlich ist. Der Typ einer Variablen (und auch ihr Name) kann hingegen grundsätzlich nicht verändert werden.
Typ einer Variablen
Während der Wert einer Variablen unter gewissen Umständen verändert werden kann, ist der Typ einer Variablen nicht veränderlich.
Typregeln
Der Typ einer Variablen auf der linken Seite einer Zuweisung muß ein Obertyp des Typs des Ausdrucks auf der rechten Seite der Zuweisung sein.
Jeder Typ gilt als Obertyp seiner selbst, und außerdem gilt »double« als Obertyp von »int«.
Die folgende Tabelle beschreibt noch einmal, welche Ausdrucktypen auf der rechten Seite einer Zuweisung an eine Variable gestattet sind.
Variablentyp Ausdrucktyp
der linken Seite der rechten Seitendouble int, long, double
long int, long
int int
java.lang.String java.lang.String
Der Typ des gesamten Zuweisungsausdrucks ist der Typ der Variablen auf der linken Seite.
ℛ Substitutionsprinzip Wird ein Ausdruck eines Typs (wie beispielsweise »double«) erwartet, so kann ein Ausdruck eines Untertyps (wie beispielsweise »int«) angegeben werden.
Allgemein muß beim Kopieren eines Wertes der Typ des Ausdrucks, der den Wert angibt, eine Untertyp des Typs des Ausdrucks, der das Ziel des Kopierens angibt, sein. Als Spezialfälle dieser Regel ergeben sich:
- Der Typ eines Argumentausdrucks muß ein Untertyp des Parametertyps sein.
- Der Typ eines Initialisierungsausdrucks in einer Variablendeklaration muß ein Untertyp des Typs der Variablen sein.
- Der Typ der rechten Seite einer Zuweisung muß ein Untertyp des Typs der linken Seite der Zuweisung sein. (Der Typ eines Initialisierungsausdrucks in einer Variablendeklaration muß daher auch ein Untertyp des Typs der Variablen sein.)
Übungsfragen
? Zuweisung (1) →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 2;
java.lang.System.out.println( v );
java.lang.System.out.println( v = 3 );
java.lang.System.out.println( v ); }}
? Zuweisung (2) → →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 3;
java.lang.System.out.println( v );
java.lang.System.out.println( v = 2 );
java.lang.System.out.println( v = 5 );
java.lang.System.out.println( v ); }}
? Zuweisung (3) → →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 1;
java.lang.System.out.println( v );
java.lang.System.out.println( v = v );
java.lang.System.out.println( v ); }}
? Zuweisung (4) →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 1;
java.lang.System.out.println( v );
java.lang.System.out.println( v = 2 * v );
java.lang.System.out.println( v ); }}
? Zuweisung (5) → →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 7;
java.lang.System.out.println( 3 +( v = v - 2 ));
java.lang.System.out.println( v ); }}
? Zuweisung (6) → →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 1;
int w = 2;
java.lang.System.out.println( v =( w = 5 ));
java.lang.System.out.println( v );
java.lang.System.out.println( w ); }}
? Zuweisung (7)
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 1;
int w = 2;
java.lang.System.out.println( v );
java.lang.System.out.println( w );
java.lang.System.out.println( v = v + w );
java.lang.System.out.println( w = v + w ); }}
? Zuweisung (8) →
Was gibt das folgende Programm aus?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 1;
java.lang.System.out.println( java.lang.Double.sum( ( v = 2 )+ v, v ));
java.lang.System.out.println( v ); }}
Variablen als Laufzeitentitäten ⃗
Die folgenden Abbildungen veranschaulichen das Laufzeitmodell von Variablen.
Der Variablenname (wie beispielsweise »v«) und sein Typ (wie beispielsweise »int«) gehören zum Quelltextmodell.
Diese sind an eine Variable mit einem Wert gebunden. Die Variable, ihr Wert und die Bindung gehören zum Laufzeitmodell.
- Variable nach Ausführung von »int v = 7;«
Laufzeitmodell
:
Quelltextmodell :
:
:
:
: Bindung .---.
v ==============================>| 7 |
Bezeichner : '---'
Typ: int : Variable
: mit Wert
:
:
:
Durch die Auswertung des Zuweisungsausdrucks »v = 4« wird zur Laufzeit der Wert »4« in die Variable geschrieben, während sich an der Bindung zwischen dem Namen »v« und seiner Variablen nichts ändert.
- Dieselbe Variable nach Auswertung von »v = 4«
Laufzeitmodell
:
Quelltextmodell :
:
:
:
: Bindung .---.
v ==============================>| 4 |
Bezeichner : '---'
Typ: int : Variable
: mit Wert
:
:
:
Referentielle Transparenz *
Wenn „referentielle Transparenz“ gilt, dann kann man einen Namen durch seinen Wert ersetzen. Wir haben gesehen, daß dies bei Verwendungen von final-Variablen auch stets gilt.
Auf der linken Seite einer Zuweisung darf ein Variablenname jedoch nicht durch seinen Wert ersetzt werden.
Wir können in dem obenstehenden Programm also nicht »7« für das »v« in der letzten Zeile einsetzen.
Main.txt
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v = 7;
java.lang.System.out.println( 7 = 2 ); }}- Ausgabe (übersetzt)
Main.txt:4: Fehler: unerwarteter Typ
java.lang.System.out.println( 7 = 2 ); }}
^
benötigt: Variable
gefunden: Wert
1 Fehler
Dies liegt daran, daß der Name »v« auf der linken Seite einer Zuweisung nicht für den Wert der Variablen, sondern für die Variable selber steht.