Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage
 <<    <     >    >>   API  Kapitel 6 - Ausdrücke

6.7 Sonstige Operatoren



Neben den bisher vorgestellten Operatoren stellt Java noch eine Reihe weiterer Operatoren zur Verfügung, die in diesem Abschnitt erläutert werden sollen.

6.7.1 Weitere Operatoren für primitive Typen

Fragezeichenoperator

Der Fragezeichenoperator ?: ist der einzige dreiwertige Operator in Java. Er erwartet einen logischen Ausdruck und zwei weitere Ausdrücke, die beide entweder numerisch, von einem Referenztyp oder vom Typ boolean sind.

Bei der Auswertung wird zunächst der Wert des logischen Operators ermittelt. Ist dieser wahr, so wird der erste der beiden anderen Operanden ausgewertet, sonst der zweite. Das Ergebnis des Ausdrucks a ? b : c ist also b, falls a wahr ist, und c, falls a falsch ist. Der Typ des Rückgabewerts entspricht dem Typ des größeren der beiden Ausdrücke b und c.

Type-Cast-Operator

Ebenso wie in C gibt es auch in Java einen Type-Cast-Operator, mit dessen Hilfe explizite Typumwandlungen vorgenommen werden können. Der Ausdruck (type) a wandelt den Ausdruck a in einen Ausdruck vom Typ type um. Auch wenn a eine Variable ist, ist das Ergebnis von (type) a ein Ausdruck, der nicht mehr auf der linken, sondern nur noch auf der rechten Seite eines Zuweisungsoperators stehen darf.

Wie in Kapitel 5 erklärt, gibt es verschiedene Arten von Typkonvertierungen in Java. Mit Hilfe des Type-Cast-Operators dürfen alle legalen Typkonvertierungen vorgenommen werden. Der Type-Cast-Operator wird vor allem dann angewendet, wenn der Compiler keine impliziten Konvertierungen vornimmt; beispielsweise bei der Zuweisung von größeren an kleinere numerische Typen oder bei der Umwandlung von Objekttypen.

6.7.2 Operatoren für Objekte

Es gibt in Java einige Ausdrücke und Operatoren, die mit Objekten arbeiten oder Objekte produzieren. Die meisten von ihnen können erst dann erläutert werden, wenn die entsprechenden Konzepte in späteren Kapiteln eingeführt wurden. Der Vollständigkeit halber sollen sie dennoch an dieser Stelle erwähnt werden.

 Hinweis 

String-Verkettung

Der +-Operator kann nicht nur mit numerischen Operanden verwendet werden, sondern auch zur Verkettung von Strings. Ist wenigstens einer der beiden Operatoren in a + b ein String, so wird der gesamte Ausdruck als String-Verkettung ausgeführt. Hierzu wird gegebenenfalls zunächst der Nicht-String-Operand in einen String umgewandelt und anschließend mit dem anderen Operanden verkettet. Das Ergebnis der Operation ist wieder ein String, in dem beide Operanden hintereinander stehen.

In Java ist die Konvertierung in einen String für nahezu jeden Typ definiert. Bei primitiven Typen wird die Umwandlung vom Compiler und bei Referenztypen durch die Methode toString ausgeführt. Die String-Verkettung ist daher sehr universell zu verwenden und ermöglicht (beispielsweise zu Ausgabezwecken) eine sehr bequeme Zusammenfassung von Ausdrücken unterschiedlichen Typs. Ein typisches Beispiel für die Verwendung der String-Verkettung ist die Ausgabe von numerischen Ergebnissen auf dem Bildschirm:

 Tip 

001 /* Listing0603.java */
002 
003 public class Listing0603
004 {
005   public static void main(String[] args)
006   {
007     int a = 5;
008     double x = 3.14;
009 
010     System.out.println("a = " + a);
011     System.out.println("x = " + x);
012   }
013 }
Listing0603.java
Listing 6.3: String-Verkettung

Die Ausgabe des Programms lautet:

a = 5
x = 3.14

Etwas Vorsicht ist geboten, wenn sowohl String-Verkettung als auch Addition in einem Ausdruck verwendet werden sollen, da die in diesem Fall geltenden Vorrang- und Assoziativitätsregeln zu unerwarteten Ergebnissen führen können. Das folgende Programm gibt daher nicht 3 + 4 = 7, sondern 3 + 4 = 34 aus.

 Warnung 

001 /* Listing0604.java */
002 
003 public class Listing0604
004 {
005   public static void main(String[] args)
006   {
007     // Die +-Operatoren werden von innen nach außen und von
008     // links nach rechts ausgewertet     
009     System.out.println("3 + 4 = " + 3 + 4);
010   }
011 }
Listing0604.java
Listing 6.4: Vorsicht bei der String-Verkettung!

Um das gewünschte Ergebnis zu erzielen, müsste der Teilausdruck 3 + 4 geklammert werden:

001 /* Listing0605.java */
002 
003 public class Listing0605
004 {
005   public static void main(String[] args)
006   {
007     // Die +-Operatoren werden von innen nach außen und von
008     // links nach rechts ausgewertet     
009     System.out.println("3 + 4 = " + (3 + 4));
010   }
011 }
Listing0605.java
Listing 6.5: Korrekte String-Verkettung bei gemischten Ausdrücken

Referenzgleichheit und -ungleichheit

Die Operatoren == und != können auch auf Objekte, also auf Referenztypen, angewendet werden. In diesem Fall ist zu beachten, dass dabei lediglich die Gleichheit oder Ungleichheit der Referenz getestet wird. Es wird also überprüft, ob die Objektzeiger auf ein und dasselbe Objekt zeigen, und nicht, ob die Objekte inhaltlich übereinstimmen.

 Hinweis 

Ein einfaches Beispiel ist der Vergleich zweier Strings a und b, die beide den Inhalt »hallo« haben:

001 /* Listing0606.java */
002 
003 public class Listing0606
004 {
005   public static void main(String[] args)
006   {
007     String a = new String("hallo");
008     String b = new String("hallo");
009     System.out.println("a == b liefert " + (a == b));
010     System.out.println("a != b liefert " + (a != b));
011   }
012 }
Listing0606.java
Listing 6.6: Vergleichen von Referenzen

Werden sie zur Laufzeit angelegt (wie in diesem Beispiel), liefert das Programm das erwartete Ergebnis, denn a und b sind Referenzen auf unterschiedliche Objekte, also Zeiger auf unterschiedliche Instanzen derselben Klasse.

a == b liefert false
a != b liefert true

Das ist das erwartete Verhalten für fast alle Objektreferenzen. Werden die Strings als Literale dagegen zur Compile-Zeit angelegt und damit vom Compiler als konstant erkannt, sind sie genau dann Instanzen derselben Klasse, wenn sie tatsächlich inhaltlich gleich sind. Dies liegt daran, dass String-Literale mit Hilfe der Methode String.intern angelegt werden, die einen Puffer von String-Objekten verwaltet, in dem jede Zeichenkette nur einmal vorkommt. Wird ein bereits existierender String noch einmal angelegt, so findet die Methode den Doppelgänger und liefert einen Zeiger darauf zurück. Dieses Verhalten ist so nur bei Strings zu finden, andere Objekte besitzen keine konstanten Werte und keine literalen Darstellungen. Die korrekte Methode, Strings auf inhaltliche Übereinstimmung zu testen, besteht darin, die Methode equals der Klasse String aufzurufen (siehe Listing 6.7).

 Warnung 

001 /* Listing0607.java */
002 
003 public class Listing0607
004 {
005   public static void main(String[] args)
006   {
007     String a = new String("hallo");
008     String b = new String("hallo");
009     System.out.println("a.equals(b) liefert " + a.equals(b));
010   }
011 }
Listing0607.java
Listing 6.7: Vergleichen von Strings mit equals

Der instanceof-Operator

Der instanceof-Operator kann verwendet werden, um herauszufinden, zu welcher Klasse ein bestimmtes Objekt gehört. Der Ausdruck a instanceof b liefert genau dann true, wenn a und b Referenztypen sind und a eine Instanz der Klasse b oder einer ihrer Unterklassen ist. Falls das Ergebnis des instanceof-Operators nicht bereits zur Compile-Zeit ermittelt werden kann, generiert der Java-Compiler Code, um den entsprechenden Check zur Laufzeit durchführen zu können.

Der new-Operator

In Java werden Objekte und Arrays mit Hilfe des new-Operators erzeugt. Sowohl das Erzeugen eines Arrays als auch das Erzeugen eines Objekts sind Ausdrücke, deren Rückgabewert das gerade erzeugte Objekt bzw. Array ist.

Member-Zugriff

Der Zugriff auf Klassen- oder Instanzvariablen wird mit Hilfe des Punkt-Operators ausgeführt und hat die Form a.b. Dabei ist a der Name einer Klasse bzw. der Instanz einer Klasse und b ist der Name einer Klassen- oder Instanzvariable. Der Typ des Ausdrucks entspricht dem Typ der Variable und zurückgegeben wird der Inhalt dieser Variable.

Methodenaufruf

In Java gibt es keine Funktionen, sondern nur Methoden. Der Unterschied zwischen beiden besteht darin, dass Methoden immer an eine Klasse oder die Instanz einer Klasse gebunden sind und nur in diesem Kontext aufgerufen werden können. Die Syntax des Methodenaufrufs gleicht der anderer Programmiersprachen und erfolgt in der (etwas vereinfachten) Form f() bzw. f(parameterliste). Der Typ des Ausdrucks entspricht dem vereinbarten Rückgabetyp der Methode. Der Wert des Ausdrucks ist der von der Methode mit Hilfe der return-Anweisung zurückgegebene Wert.

Methoden können selbstverständlich Nebeneffekte haben und werden in vielen Fällen ausschließlich zu diesem Zweck geschrieben. Ist dies der Fall, so sollte eine Methode als void deklariert werden und damit anzeigen, dass sie keinen Rückgabewert produziert. Die einzig sinnvolle Verwendung einer solchen Methode besteht darin, sie innerhalb einer Ausdrucksanweisung (siehe Kapitel 7) aufzurufen.

Da die Realisierung der Methodenaufrufe in Java recht kompliziert ist (die Sprachspezifikation widmet diesem Thema mehr als zehn Seiten), werden wir in Kapitel 8 noch einmal ausführlich darauf eingehen.

 Hinweis 

Zugriff auf Array-Elemente

Wie in anderen Programmiersprachen erfolgt auch in Java der Zugriff auf Array-Elemente mit Hilfe eckiger Klammern in der Form a[b] (bzw. a[b][c], a[b][c][d] usw. bei mehrdimensionalen Arrays). Dabei ist a der Name eines Arrays oder ein Ausdruck, der zu einem Array ausgewertet wird, und b ein Ausdruck, der zu einem int evaluiert werden kann. Der Typ des Ausdrucks entspricht dem Basistyp des Arrays, zurückgegeben wird der Inhalt des Array-Elements, das sich an Position b befindet. Wie in C und C++ beginnt die Zählung mit dem ersten Element bei Position 0.

6.7.3 Welche Operatoren es nicht gibt

Da es in Java keine expliziten Pointer gibt, fehlen auch die aus C bekannten Operatoren * zur Dereferenzierung eines Zeigers und & zur Bestimmung der Adresse einer Variablen. Des Weiteren fehlt ein sizeof-Operator, denn da alle Typen eine genau spezifizierte Länge haben, ist dieser überflüssig. Der Kommaoperator von C ist ebenfalls nicht vorhanden, er taucht aber als syntaktischer Bestandteil der for-Schleife wieder auf und erlaubt es, im Initialisierungsteil der Schleife mehr als eine Zuweisung vorzunehmen.

 Hinweis 


 Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0
 <<    <     >    >>   API  © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de