Variablen und Operationen

Variablen deklarieren

Variable können an fast jeder Stelle des Quelltextes deklariert werden. Obwohl dies nicht nötig ist, sollten solche Deklarationen wegen der Übersichtlichkeit am Anfang eines Blockes stehen. Eine Deklaration besteht aus dem Typ der Variablen, gefolgt von derem Namen. Die Anweisung wird noch von einem Semikolon abgeschlossen.


  public static void main(String[] args) {
    int a;      // eine Variable a vom Typ int
  }

Es können mehrere Variablen auf einmal deklariert werden, indem man sie durch Kommata abtrennt. Diese Variablen haben dann alle den angegebenen Typ.


    int b, c;

Alle diese Variablen haben noch keinen konkreten Wert. Wenn man sie benutzt, ohne ihnen vorher einen Wert zuzuweisen, dann gibt es schon vom Compiler einen Fehler (z.B. variable c might not have been initialised). Eine Zuweisung besteht aus dem Namen der Variablen, einem Gleichheitszeichen und dem Ausdruck, der ausgewertet und zugewiesen wird. Ein Ausdruck ist entweder eine Konstante, eine andere Variable gleichen Typs, das Ergebnis eines Methodenaufrufs oder eine Verkettung von Ausdrücken mit Operatoren.


    a = 7;
    b = 3;
    c = a / b;

Da der Compiler auch nicht der intelligenteste ist, und eine fehlende Initialisierung nur in Spezialfällen erkennt, sollte grundsätzlich zur Fehlervermeidung ein Anfangwert zugewiesen werden.


    int a = 7;
    int c, b = 3;  // c hat noch keinen Wert
    c = a / b;

Hierbei wird nur der Variablen b ein Wert zugewiesen. c ist nach der zweiten Zeile noch unbelegt. Um keine Verwirrung zu stiften, sollte man eine derartige Deklaration vermeiden.

arithmetische Operationen

Es stehen die üblichen Operatoren zur Verfügung, wobei Punkt- vor Strichrechnung gilt.

Operator Bedeutung
+Addition
-Subtraktion
*Multiplikation
/Division

Wenn der Operator auf zwei Variablen gleichen Typs angewendet werden, dann hat auch das Ergebnis diesen Typ. Falls die beiden Werte einen unterschiedlichen Typ haben, wird der Typ des Ergebnises der grössere der beiden sein. Da im obigen Beispiel beide Variablen a und b ganzzahlig sind, ist auch das Ergebnis ganzzahlig vom Typ int. Die Anweisung


    System.out.println(c);

ergibt also 2 und nicht 2.333333. Selbst wenn c den Typ double hat, wird die Operation a / b ganzzahlig berechnet. Um die Berechnung mit Kommazahlen durchzuführen muss mindestens eine der beiden Zahlen einen Gleitkommatyp haben.


    double d = 7   / 3.0;
           d = 7.0 / 3;
           d = a   / (double) b;

Die ersten beiden Varianten funktionieren identisch. Die letzte Variante kann für Variablen verwendet werden. Dabei wird der Wert von b vor der Division in eine Gleitkommazahl umgewandelt, was dann auch zur Durchführung der Gleitkommadivision führt. Eine solche Typumwandlung nennt man Casting (Lektion 04). Der Wert von d ist in jedem Fall 2.3333333333333335. Das sind die 17 Stellen des Typs double. Der Rundungsfehler der letzten Ziffer liegt daran, dass diese Zahl keine exakte endliche Darstellung im Dualsystem besitzt (schon gar keine, die in die 64 bit von double passt).

Die Berechnung 1 / 0 mit ganzen Zahlen führt zu einer ArithmeticException, d.h. das Programm stürzt ab (zu Exceptions später mehr). Bei Gleitkommazahlen ist das nicht so. Es gibt drei spezielle Werte von Gleitkommazahlen:


  Double.POSITIVE_INFINITY = 1.0 / 0.0;
  Double.NEGATIVE_INFINITY = -1.0 / 0.0;
  Double.NaN = 0.0d / 0.0;

Dabei steht NaN für "not a number". Bei dieser Konstante gibt es noch eine Kuriosität, die man beachten sollte. Der Test auf Gleichheit mit dieser Konstante liefert immer false.


  double x = 0.0 / 0.0;
  System.out.println("x == x ? " + (x == x));

Interessanterweise liefert das die Ausgabe x == x ? false

Dieses Verhalten kann damit begründet werden, das der Vergleich mit einer Zahl, die keine ist, nicht wahr sen kann.

Für ganze Zahlen gibt es noch weitere Operationen.

Operator BezeichnungBedeutung
% modulo Rest der ganzzahligen Division
& and bitweise und-Verknüpfung
| or bitweise oder-Verknüpfung
^ xor bitweise exklusiv-oder-Verknüpfung
! not bitweise Negation (unärer Operator)
<< shift left bitweise nach links schieben
>> shift rightbitweise nach rechts schieben
Vorzeichenbit bleibt erhalten
>>>shift rightbitweise nach rechts schieben
Vorzeichenbit wird mit verschoben

Bei bitweise Verschiebungen ist das Vorzeichen problematisch, da dieses ja im höchsten bit der Zahl abgelegt wird.


    System.out.println(1 << 30);  // ergibt  1073741824
    System.out.println(1 << 31);  // ergibt -2147483648
    System.out.println(1 << 32);  // ergibt           1

Der shift left Operator ist also zyklisch und verschiebt bei positiven Zahlen auch über das Vorzeichenbit. Bei negativen Zahlen hingegen wird das Vorzeichenbit geschützt. Für den shift right Operator gibt es zwei Varianten. -1 besteht in der Binärdarstellung nur aus Einsen, wobei das erste bzw. höchste Bit das Vorzeichen darstellt.

Ausdruck dezimal binär
x -1234567811111000101001000011001011101011
x >> 1 -6172839511111100010100100001100101110101
x >>> 1208575525301111100010100100001100101110101

Dabei entspricht x >> 1 einfach der Division durch 2, also x / 2, wodurch das Vorzeichen erhalten bleibt. Wohingegen x >>> 1 alle bits inclusive Vorzeichen verschiebt. Dies ist dann nützlich, wenn man die Zahl als Bit-Map verwendet.

Vergleichsoperationen

Die üblichen Vergleichsrelationen stehen auch in Java zur Verfügung.

Operator Bedeutung
> grösser
>=grösser oder gleich
< kleiner
<=kleiner oder gleich
== gleich

Es ist zu beachten, dass sich das Symbol für den Vergleich == vom Symbol für eine Zuweisung = unterscheidet.

Boolsche Operationen

Theoretisch arbeiten logische Verknüpfungen von Boolschen Werten genau wie die bitweisen Operationen. Es gibt aber trotzdem eigene Operatoren dafür in Java.

Operator Bedeutung
&&logische und-Verknüpfung
|| logische oder-Verknüpfung
! logische Negation (unärer Operator)

Vergleichsoperatoren haben eine höhere Priorität als logische Verknüpfungen. Deshalb sind die folgenden beiden Ausdrücke gleichwertig:


     a >= 0  &&  a <= 10
    (a >= 0) && (a <= 10)

Für eine bessere Lesbarkeit und um Verwechselungen zu vermeiden, sollte die zweite Variante verwendet werden.


Erstellt von Markus Durzinsky, aktualisiert 2004-05-06
Für Fragen, Probleme oder Anregungen stehe ich gerne zur Verfügung