vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 1

Tag 4


Arbeiten mit Objekten

Vor zwei Tagen wurde die objektorientierte Programmierung mit Bier verglichen, da der »Geschmack« gewöhnungsbedürftig ist und zur Desorientierung führen kann.

Im heutigen Kapitel können Sie nachschenken lassen. Während Sie in Java mit Objekten arbeiten, werden Sie mit dieser Art der Programmierung vertrauter werden.

Die meisten Dinge, die Sie mit dieser Sprache tun, tun Sie mit Objekten. Sie erzeugen Objekte, modifizieren sie, verschieben sie, verändern deren Variablen, rufen deren Methoden auf und kombinieren sie mit anderen Objekten. Sie werden Klassen entwikkeln, Objekte dieser Klassen erzeugen und sie mit anderen Klassen und Objekten zusammen verwenden.

Sie werden heute sehr ausführlich mit Objekten arbeiten. Die folgenden Themen werden dabei behandelt:

Erstellen neuer Objekte

Wenn Sie ein Java-Programm schreiben, definieren Sie verschiedene Klassen. Wie Sie am 2. Tag gelernt haben, dienen Klassen als Vorlagen für Objekte. Zum großen Teil benutzen Sie die Klassen lediglich, um Instanzen zu erstellen. Dann arbeiten Sie mit diesen Instanzen. In dieser Lektion lernen Sie, wie man ein neues Objekt aus einer Klasse erstellt.

Sie erinnern sich an die Zeichenketten aus der gestrigen Lektion? Sie haben gelernt, daß ein String-Literal - eine Reihe von Zeichen zwischen doppelten Anführungszeichen - eine neue Instanz der Klasse String mit dem Wert der jeweiligen Zeichenkette erzeugt.

Die String-Klasse ist in dieser Hinsicht ungewöhnlich. Es ist zwar eine Klasse, dennoch gibt es eine einfache Möglichkeit, anhand eines Literals Instanzen von dieser Klasse anzulegen. Für die anderen Klassen gibt es diese Abkürzung nicht. Um Instanzen dieser Klassen zu erstellen, müssen sie explizit mit dem Operator new angelegt werden.


Literale für Zahlen und Zeichen erstellen keine Objekte. Die primitiven Datentypen für Zahlen und Zeichen erstellen Zahlen und Zeichen, sind aber aus Effizienzgründen keine Objekte. Sie können sie in Objekt-Wrapper (Hüllklassen) verpacken, wenn Sie sie wie Objekte behandeln wollen (hierüber lernen Sie später mehr).

new

Um ein neues Objekt zu erstellen, benutzen Sie den Operator new mit dem Namen der Klasse, von der Sie eine Instanz anlegen wollen, und Klammern:

String teamName = new String();
Random randInfo = new Random();
Jabberwock j = new Jabberwock();

Die Klammern sind wichtig. Sie dürfen auf keinen Fall weggelassen werden. Die Klammern können leer bleiben. In diesem Fall wird ein ganz einfaches Objekt erstellt. Die Klammern können aber auch Argumente enthalten, die die Anfangswerte von Instanzvariablen oder andere Anfangsqualitäten des Objekts bestimmen:

GregorianCalendar date = new GregorianCalendar(64, 6, 6, 7, 30);
Point pt = new Point(0,0);

Zahl und Typ von Argumenten, die Sie mit new verwenden können, werden von der Klasse anhand einer speziellen Methode namens Konstruktor vorgegeben. Sie lernen später in dieser Woche noch alles über Konstruktor-Methoden. Wenn Sie versuchen eine Instanz einer Klasse über new mit der falschen Anzahl an Parametern zu erzeugen (oder Sie geben keine Parameter an, obwohl welche erwartet werden), tritt ein Fehler auf, sobald Sie versuchen, das Java-Programm zu kompilieren.

Hier nun ein Beispiel für die Erstellung einiger Objekte verschiedener Typen. Diese werden mit unterschiedlicher Anzahl und verschiedenen Typen von Argumenten erzeugt: Die Klasse Random, Teil des Paketes java.util, erzeugt Objekte, mit denen in einem Programm Zufallszahlen erzeugt werden können. Diese Objekte werden als Zufallsgeneratoren bezeichnet. Der Dezimalwert dieser Objekte liegt im Bereich von 0.0 bis 1.0. Zufallszahlen sind in Spielen und anderen Programmen, in denen ein Element der Unvorhersehbarkeit benötigt wird, enthalten.

Das Random-Objekt erzeugt nicht wirklich zufällig Zahlen. Statt dessen pickt es eine Zahl aus einer sehr großen Folge von Zahlen heraus. Dies wird auch als pseudozufällige Erzeugung bezeichnet und in vielen anderen Programmiersprachen verwendet. Um eine andere Zahl aus der zufälligen Folge zu erhalten, muß dem Random-Objekt ein Anfangswert gegeben werden. Dieser Anfangswert wird bei der Erzeugung des Objektes verwendet.

In Listing 4.1 finden Sie ein Java-Programm, das Random-Objekte auf zwei verschiedene Arten erzeugt.

Listing 4.1: Der gesamte Quelltext von RandomNumbers.java

 1: import java.util.Random;
 2:
 3: class RandomNumbers {
 4:
 5:     public static void main(String arguments[]) {
 6:         Random r1, r2;
 7:
 8:         r1 = new Random();
 9:         System.out.println("Random value 1: " + r1.nextDouble());
10:
11:         r2 = new Random(8675309);
12:         System.out.println("Random value 2: " + r2.nextDouble());
13:     }
14: }

Wenn Sie dieses Programm kompilieren und ausführen, sollte folgendes ausgegeben werden:

Random value 1: 0.3125961341023068
Random value 2: 0.754788115099576

In diesem Beispiel werden anhand unterschiedlicher Argumente für new zwei verschiedene Random-Objekte erstellt. Die erste Instanz (Zeile 8) benutzt new Random() ohne Argumente, was ein Random-Objekt mit der aktuellen Zeit als Anfangswert erzeugt. Der Wert in der ersten Zeile Ihrer Ausgabe hängt von dem Zeitpunkt ab, zu dem Sie das Programm ausführen, da der Zufallswert das Fortschreiten der Zeit widerspiegelt. Aus diesem Grund werden die meisten Random-Objekte mit dem Standard-Verfahren, sprich: der Zeit als Anfangswert, erzeugt.

Der Aufruf der Methode nextDouble() des Random-Objekts in den Zeilen 9 bis 12 gibt die nächste Zahl in der pseudozufälligen Zahlenfolge aus.

Bei der Erstellung des Random-Objekts in diesem Beispiel (Zeile 11) wird ein Integer als Argument übergeben. Die zweite Zeile der Ausgabe sollte jedesmal, wenn das Programm ausgeführt wird, denselben Wert (0.754788115099576) anzeigen. Wenn Sie ein Literal als Anfangswert übergeben, dann ist die Folge der Zufallszahlen immer dieselbe. Dies kann für Testzwecke hilfreich sein.


Sie haben vielleicht Probleme damit zu erkennen, wie man mit einer langen Dezimalzahl (z.B. 0.754788115099576) eine Zufallszahl erzeugen kann. Wenn Sie diesen Zufallswert mit einem Integer multiplizieren, dann ist das Produkt eine Zufallszahl zwischen Null und dem Integer selbst. Die folgende Anweisung multlipliziert eine Zufallszahl z.B. mit 12 und speichert das Produkt als Integer:

Random r1 = new Random();
int number = (int)(r1.nextDouble() * 12); 

Die Zahl wird eine Zufallszahl zwischen 0 und 12 sein.

Was new bewirkt

Bei Verwendung des new-Operators passieren mehrere Dinge: Erstens wird die neue Instanz der jeweiligen Klasse angelegt und Speicher dafür allokiert. Zweitens wird eine bestimmte Methode, die in der jeweiligen Klasse definiert ist, aufgerufen. Diese spezielle Methode nennt man Konstruktor.


Ein Konstruktor ist eine spezielle Methode zum Erstellen und Initialisieren neuer Instanzen von Klassen. Konstruktoren initialisieren das neue Objekt und seine Variablen, erzeugen andere Objekte, die dieses Objekt braucht, und führen im allgemeinen andere Operationen aus, die für die Ausführung des Objekts nötig sind.

Sie können in einer Klasse mehrere Konstruktor-Definitionen verwenden. Diese können sich jeweils in der Zahl und dem Typ der Argumente unterscheiden. Beim Aufruf eines Konstruktors bei der Verwendung von new wird dann anhand der übergebenen Argumente der richtige Konstruktor für jene Argumente verwendet. Auf diese Weise war es der Random-Klasse möglich, mit den verschiedenen Versionen von new unterschiedliche Aufgaben zu erfüllen. Wenn Sie eigene Klassen anlegen, können Sie beliebig viele Konstruktoren definieren, um das Verhalten einer Klasse zu bestimmen.

Speichermanagement

Wenn Sie mit anderen objektorientierten Programmiersprachen vertraut sind, werden Sie sich eventuell fragen, ob es zu der new-Anweisung ein Gegenstück gibt, das ein Objekt zerstört, sobald es nicht mehr benötigt wird.

Speichermanagement ist in Java dynamisch und automatisch. Wenn Sie in Java ein neues Objekt erstellen, wird ihm automatisch die richtige Speichermenge zugeteilt. Sie brauchen für Objekte nicht explizit Speicherplatz zuzuteilen. Das übernimmt Java für Sie.

Wenn Sie ein Objekt nicht mehr benötigen, wird der diesem Objekt zugeteilte Speicher ebenfalls automatisch wieder freigegeben. Ein Objekt, das nicht mehr gebraucht wird, hat keine aktiven Referenzen mehr (es ist keinen Variablen mehr zugewiesen, die Sie noch verwenden oder die in Arrays gespeichert sind). Java hat einen Papierkorb (garbage collector), der nach unbenutzten Objekten sucht und den diesen Objekten zugeteilten Speicherplatz zurückfordert. Sie brauchen also Speicherplatz nicht explizit freizustellen. Sie müssen nur sicherstellen, daß keine Objekte, die Sie loswerden wollen, irgendwo verwendet werden.

Verwenden von Klassen- und Instanzvariablen

Nun haben Sie ein eigenes Objekt mit definierten Klassen- oder Instanzvariablen. Wie funktionieren diese Variablen? Ganz einfach! Klassen- und Instanzvariablen verhalten sich genauso wie die lokale Variablen, die Sie gestern gelernt haben. Lediglich die Bezugnahme auf sie unterscheidet sich geringfügig von den üblichen Variablen im Code.

Werte auslesen

Um den Wert einer Instanzvariablen auszulesen, verwenden Sie die Punkt-Notation.

Bei der Punkt-Notation hat die Referenz auf eine Instanz- oder Klassenvariable zwei Teile: das Objekt auf der linken Seite des Punkts und die Variable rechts davon.


Die Punkt-Notation ist eine Methode, um auf Instanzvariablen und Methoden innerhalb eines Objekts mit einem Punkt-Operator (».«) zuzugreifen.

Ist beispielsweise ein Objekt der Variablen myCustomer zugewiesen und hat dieses Objekt eine Variable namens orderTotal, nehmen Sie auf den Wert dieser Variablen wie folgt Bezug:

myCustomer.orderTotal;

Diese Art des Zugreifens auf Variablen ist ein Ausdruck (der einen Wert ausgibt), und was auf beiden Seiten des Punkts steht, ist ebenfalls ein Ausdruck. Das bedeutet, daß Sie den Zugriff auf Instanzvariablen verschachteln können. Beinhaltet die orderTotal- Instanzvariable selbst ein Objekt und dieses Objekt eine eigene Instanzvariable namens layaway, können Sie wie folgt darauf Bezug nehmen:

myCustomer.orderTotal.layaway;

Punktausdrücke werden von links nach rechts ausgewertet, deshalb beginnen sie mit der Variablen orderTotal von myCustomer, das auf ein anderes Objekt verweist, das die Variable layaway enthält. Letztendlich erhalten Sie den Wert der layaway-Variablen.

Werte ändern

Die Zuweisung eines Wertes zu dieser Variablen ist ebenso einfach. Sie setzen einfach einen Zuweisungsoperator rechts neben den Ausdruck:

myCustomer.orderTotal.layaway = true;

Dieses Beispiel setzt den Wert der Variablen layaway auf true.

Listing 4.2 ist ein Beispiel eines Programms, das die Instanzvariablen in einem Point- Objekt testet und ändert. Point ist Teil des Pakets java.awt und bezieht sich auf einen Koordinatenpunkt mit einem x- und einem y-Wert.

Listing 4.2: Der gesamte Quelltext von SetPoints.java

 1: import java.awt.Point;
 2:
 3: class SetPoints {
 4:
 5: public static void main(String arguments[]) {
 6:     Point location = new Point(4, 13);
 7:
 8:     System.out.println("Starting location:");
 9:     System.out.println("X equals " + location.x);
10:     System.out.println("Y equals " + location.y);
11:
12:     System.out.println("\nMoving to (7, 6)");
13:     location.x = 7;
14:     location.y = 6;
15:
16:     System.out.println("\nEnding location:");
17:     System.out.println("X equals " + location.x);
18:     System.out.println("Y equals " + location.y);
19:     }
20: }

Wenn Sie diese Applikation ausführen, sollten Sie die folgende Ausgabe erhalten:

Starting location:
X equals 4
Y equals 13

Moving to (7, 6)

Ending location:
X equals 7
Y equals 6

In diesem Beispiel erstellen Sie zuerst eine Instanz von Point, wobei X gleich 4 und Y gleich 13 ist (Zeile 6). Die Zeilen 9 und 10 geben diese Einzelwerte über die Punkt-Notation aus. Die Zeilen 13 und 14 ändern den Wert von x auf 7 bzw. den Wert von y auf 6. Die Zeilen 17 und 18 geben die Werte von X und Y in der geänderten Form wieder aus.

Klassenvariablen

Wie Sie bereits gelernt haben, werden Klassenvariablen in der Klasse selbst definiert und gespeichert. Deshalb wirken sich ihre Werte auf die Klasse und alle ihre Instanzen aus.

Bei Instanzvariablen erhält jede neue Instanz der Klasse eine neue Kopie der Instanzvariablen, die diese Klasse definiert. Jede Instanz kann dann die Werte dieser Instanzvariablen ändern, ohne daß sich das auf andere Instanzen auswirkt. Bei Klassenvariablen gibt es nur eine Kopie der Variablen. Jede Instanz der Klasse hat Zugang zu der Variablen, jedoch gibt es nur einen Wert. Durch Änderung des Wertes dieser Variablen ändern sich die Werte aller Instanzen der betreffenden Klasse.

Sie deklarieren Klassenvariablen, indem Sie das Schlüsselwort static vor die Variable setzen. Betrachten wir als Beispiel folgende teilweise Klassendefinition:

class FamilyMember {
    static String surname = "Igwebuike";
    String name;
    int age;
}

Instanzen der Klasse FamilyMember haben je einen eigenen Wert für Name (name) und Alter (age). Die Klassenvariable Nachname (surname) hat aber nur einen Wert für alle Familienmitglieder: »Igwebuike«. Ändern Sie surname, wirkt sich das auf alle Instanzen von FamilyMember aus.


Die Bezeichnung statisch (über das Schlüsselwort static) für diese Variablen bezieht sich auf eine Bedeutung des Wortes: ortsfest. Wenn eine Klasse eine statische Variable besitzt, dann hat diese Variable in jedem Objekt dieser Klasse denselben Wert.

Um auf Klassenvariablen zuzugreifen, benutzen Sie die gleiche Punkt-Notation wie bei Instanzvariablen. Um den Wert der Klassenvariablen auszulesen oder zu ändern, können Sie entweder die Instanz oder den Namen der Klasse links neben dem Punkt eingeben. Beide Ausgabezeilen in diesem Beispiel geben den gleichen Wert aus:

FamilyMember dad = new FamilyMember();
System.out.println("Family's surname is: " + dad.surname);
System.out.println("Family's surname is: " + FamilyMember.surname);

Da Sie eine Instanz benutzen können, um den Wert einer Klassenvariablen zu ändern, entsteht leicht Verwirrung über Klassenvariablen und darüber, wo der Wert herkommt (Sie erinnern sich, daß sich der Wert einer Klassenvariablen auf alle Instanzen auswirkt). Aus diesem Grund empfiehlt es sich, den Namen der Klasse zu verwenden, wenn auf eine Klassenvariable verwiesen wird. Dadurch wird der Code besser lesbar, und Fehler lassen sich schneller finden.

Aufrufen von Methoden

Das Aufrufen von Methoden in Objekten läuft ähnlich ab wie die Bezugnahme auf seine Instanzvariablen: Auch in Methodenaufrufen wird die Punkt-Notation benutzt. Das Objekt, dessen Methode Sie aufrufen, steht links neben dem Punkt. Der Name der Methode und ihre Argumente stehen rechts neben dem Punkt:

myCustomer.addToOrder(itemNumber, price, quantity);

Beachten Sie, daß nach jeder Methode Klammern folgen müssen, auch wenn die Methode keine Argumente hat:

myCustomer.cancelAllOrders();

Gibt die aufgerufene Methode ein Objekt zurück, das selbst Methoden hat, können Sie Methoden wie Variablen verschachteln. Das nächste Beispiel ruft die Methode talkToManager() auf. Diese ist in dem Objekt definiert, das von der Methode cancelAllOrders() zurückgegeben wird, die wiederum in dem Objekt myCustomer definiert ist:

myCustomer.cancelAllOrders().talkToManager();

Sie können auch verschachtelte Methodenaufrufe und Referenzen auf Instanzvariablen kombinieren. Im nächsten Beispiel wird die Methode putOnLayaway() aufgerufen. Diese ist in dem Objekt definiert, das in der Instanzvariablen orderTotal gespeichert ist. Die Instanzvariable selbst ist Teil des myCustomer-Objekts:

myCustomer.orderTotal.putOnLayaway(itemNumber, price, quantity);

System.out.println(), die Methode, die Sie bisher in diesem Buch benutzt haben, um Text auszugeben, ist ein gutes Beispiel für die Verschachtelung von Variablen und Methoden. Die System-Klasse (Teil des Pakets java.lang) beschreibt systemspezifisches Verhalten. System.out ist eine Klassenvariable, die eine Instanz der Klasse PrintStream enthält. Diese Instanz zeigt auf die Standardausgabe des Systems. PrintStream-Instanzen enthalten die Methode println(), die eine Zeichenkette an diesen Ausgabestream schickt.

Listing 4.3 zeigt ein Beispiel des Aufrufens einiger Methoden, die in der String-Klasse definiert sind. String-Objekte beinhalten Methoden zum Testen und Ändern von Strings auf ähnliche Weise, wie man sie von einer Stringbibliothek in anderen Sprachen erwarten würde.

Listing 4.3: Der gesamte Quelltext von CheckString.java

 1: class CheckString {
 2: 
 3:     public static void main(String arguments[]) {
 4:         String str = "In my next life, I will believe in reincarnation";
 5:         System.out.println("The string is: " + str);
 6:         System.out.println("Length of this string: "
 7:             + str.length());
 8:         System.out.println("The character at position 7: "
 9:             + str.charAt(7));
10:         System.out.println("The substring from 24 to 31: "
11:             + str.substring(24, 31));
12:         System.out.println("The index of the character x: "
13:             + str.indexOf('x'));
14:         System.out.println("The index of the beginning of the "
15:             + "substring \"will\": " + str.indexOf("will"));
16:         System.out.println("The string in upper case: "
17:             + str.toUpperCase());
18:     }
19: }

Folgendes gibt das Programm auf dem Standardausgabegerät aus:

The string is: In my next life, I will believe in reincarnation
Length of this string: 48
The character at position 7: e
The substring from 24 to 31: believe
The index of the character x: 8
The index of the beginning of the substring "will": 19
The string in upper case: IN MY NEXT LIFE, I WILL BELIEVE IN REINCARNATION

In Zeile 4 erstellen Sie eine neue Instanz von String durch Verwendung eines Zeichenkettenliterals (das ist einfacher, als wenn man new verwendet und die Zeichen dann einzeln eingibt). Der Rest des Programms ruft verschiedene String-Methoden auf, um verschiedene Operationen auf diese Zeichenkette auszuführen:

Klassenmethoden

Klassenmethoden wirken sich wie Klassenvariablen auf die ganze Klasse, nicht auf ihre einzelnen Instanzen, aus. Klassenmethoden werden üblicherweise für allgemeine Utility-Methoden benutzt, die nicht direkt auf eine Instanz der Klasse ausgeführt werden sollen, sondern lediglich vom Konzept her in diese Klasse passen. Die String-Klasse enthält beispielsweise die Klassenmethode valueOf(), die einen von vielen verschiedenen Argumenttypen (Ganzzahlen, boolesche Operatoren, andere Objekte usw.) verarbeiten kann. Die Methode valueOf() gibt dann eine neue Instanz von String aus, die den Zeichenkettenwert des Arguments enthält. Diese Methode wird nicht direkt auf eine vorhandene Instanz von String ausgeführt. Das Konvertieren eines Objekts oder Datentyps in einen String ist definitiv eine Operation, die in die String-Klasse paßt. Deshalb ist es sinnvoll, sie gleich in der String-Klasse zu definieren.

Klassenmethoden sind auch nützlich, um allgemeine Methoden an einer Stelle (der Klasse) zusammenzufassen. Die Math-Klasse, die im Paket java.lang enthalten ist, umfaßt beispielsweise zahlreiche mathematische Operationen als Klassenmethoden. Es gibt keine Instanzen der Klasse Math. Trotzdem können Sie ihre Methoden mit numerischen oder booleschen Argumenten verwenden. Die Klassenmethode Math.max() erwartet z.B. zwei Argumente und gibt das größere der beiden zurück. Sie müssen dafür keine neue Instanz der Klasse Math erzeugen. Sie können diese Methode immer dort aufrufen, wo Sie sie gerade benötigen, wie das im folgenden der Fall ist:

int maximumPrice = Math.max(firstPrice, secondPrice);

Um eine Klassenmethode aufzurufen, benutzen Sie die Punkt-Notation wie bei Instanzmethoden. Ebenso wie bei Klassenvariablen können Sie entweder eine Instanz der Klasse oder die Klasse selbst links neben den Punkt setzen. Allerdings ist die Verwendung des Namens der Klasse für Klassenvariablen aus den gleichen Gründen, die im Zusammenhang mit Klassenvariablen erwähnt wurden, empfehlenswert, da der Code dadurch übersichtlicher wird. Die letzten zwei Zeilen dieses Beispiels produzieren das gleiche Ergebnis - den String »5«:

String s, s2;
s = "foo";
s2 = s.valueOf(5);
s2 = String.valueOf(5);

Referenzen auf Objekte

Wie bei der Arbeit mit Objekten ist die Verwendung von Referenzen, die auf diese Objekte zeigen, ein wichtiger Aspekt.


Eine Referenz ist eine Art Zeiger (Pointer), der auf ein Objekt verweist.

Wenn Sie Objekte Variablen zuweisen oder Objekte als Argumente an Methoden weiterreichen, legen Sie Referenzen auf diese Objekte fest. Die Objekte selbst oder Kopien davon werden dabei nicht weitergereicht.

Ein Beispiel soll dies verdeutlichen. Sehen Sie sich den Code in Listing 4.4 an.

Listing 4.4: Der gesamte Quelltext von ReferencesTest.java

 1: import java.awt.Point;
 2:
 3: class ReferencesTest {
 4:     public static void main (String arguments[]) {
 5:         Point pt1, pt2;
 6:         pt1 = new Point(100, 100);
 7:         pt2 = pt1;
 8:
 9:         pt1.x = 200;
10:         pt1.y = 200;
11:         System.out.println("Point1: " + pt1.x + ", " + pt1.y);
12:         System.out.println("Point2: " + pt2.x + ", " + pt2.y);
13:     }
14: }

Das folgende stellt die Ausgabe des Programms dar:

Point1: 200, 200
Point2: 200, 200

Folgendes passiert im ersten Teil des Programms:

Die Zeilen 9 bis 12 sind der trickreiche Teil. Die Variablen x und y von pt1 werden beide auf 200 gesetzt. Anschließend werden alle Variablen von pt1 und pt2 auf den Bildschirm ausgegeben.

Sie erwarten eventuell, daß pt1 und pt2 unterschiedliche Werte haben. Die Ausgabe zeigt allerdings, daß dies nicht der Fall ist. Wie Sie sehen können, wurden die Variablen von pt2 auch geändert, obwohl nichts unternommen wurde, um diese zu ändern.

Die Ursache dafür ist, daß in Zeile 7 eine Referenz auf das Objekt in pt1 in pt2 erzeugt wird, anstatt pt2 als neues Objekt zu erstellen und pt1 in dieses zu kopieren.

pt2 ist eine Referenz auf dasselbe Objekt, das sich auch in pt1 befindet. Abbildung 4.1 verdeutlicht dies. Jede der beiden Variablen kann dazu verwendet werden, auf das Objekt zuzugreifen oder dessen Variablen zu verändern.


Abbildung 4.1:
Referenzen auf ein Objekt

Wenn Sie wollen, daß pt1 und pt2 sich auf verschiedene Objekte beziehen, verwenden Sie in den Zeilen 6 und 7 new Point()-Anweisungen, wie im folgenden, um diese zu erzeugen:

pt1 = new Point(100, 100);
pt2 = new Point(100, 100);

Die Tatsache, daß Java Referenzen benutzt, gewinnt besondere Bedeutung, wenn Sie Argumente an Methoden weiterreichen. Sie lernen hierüber noch in dieser Lektion mehr.


In Java gibt es keine explizite Zeigerarithmetik oder Zeiger (Pointer), sondern nur Referenzen. Mit Java-Referenzen haben Sie aber die gleichen Möglichkeiten zur Hand wie mit Zeigern, allerdings ohne deren Nachteile.

Casting und Konvertieren von Objekten und Primitivtypen

Etwas werden Sie über Java sehr schnell herausfinden: Java ist sehr pingelig in bezug auf die Informationen, die es verarbeitet. Java erwartet, daß die Informationen eine bestimmte Form haben, und läßt Alternativen nicht zu. Wenn Sie Argumente an Methoden übergeben oder Variablen in Ausdrücken verwenden, dann müssen Sie Variablen mit den richtigen Datentypen verwenden. Wenn eine Methode einen int erwartet, wird der Java-Compiler mit einem Fehler reagieren, falls Sie versuchen einen float-Wert an die Methode zu übergeben. Entsprechendes gilt, wenn Sie einer Variablen den Wert einer anderen zuweisen - beide müssen desselben Typs sein.

Es gibt einen Bereich, in dem der Java-Compiler nicht so pingelig ist: Strings. Die Verarbeitung von Strings in println()-Methoden, Zuweisungen und Methodenargumenten ist durch den Verkettungsoperator (»+«) stark vereinfacht worden. Wenn eine Variable in einer Gruppe von verketteten Variablen ein String ist, dann behandelt Java das Ganze als String. Dadurch wird folgendes möglich:

float gpa = 2.25F;
System.out.println("Honest, dad, my GPA is a " + (gpa+1.5));

Manchmal werden Sie in einem Java-Programm einen Wert haben, der nicht den richtigen Typ für das, was Sie damit tun wollen, hat. Er weist vielleicht die falsche Klasse oder den falschen Datentyp auf - z.B. float, wenn Sie int benötigen.

Um einen Wert von einem Typ in einen anderen zu konvertieren, verwenden Sie das sogenannte Casting.


Casting ist ein Mechanismus, um einen neuen Wert zu erstellen, der einen anderen Typ aufweist als dessen Quelle. Casting ergibt ein neues Objekt oder einen neuen Wert. Casting wirkt sich nicht auf das ursprüngliche Objekt bzw. den ursprünglichen Wert aus.

Obwohl das Casting-Konzept an sich einfach ist, werden die Regeln, die bestimmen, welche Typen in Java in andere konvertiert werden können, durch die Tatsache komplizierter, daß Java sowohl primitive Typen (int, float, boolean) als auch Objekttypen (String, Point, Window usw.) hat. Aufgrund dieser drei Typen gibt es drei Formen von Casting und Umwandlungen, über die wir in dieser Lektion sprechen:

Es ist vielleicht leichter, bei der folgenden Besprechung des Casting von Quellen und Zielen auszugehen. Die Quelle ist die Variable, die in einen anderen Typ gecastet wird. Das Ziel ist das Ergebnis.

Konvertieren von Primitivtypen

Durch Konvertieren zwischen primitiven Typen können Sie den Wert eines Typs in einen anderen primitiven Typ umwandeln, z.B. um eine Zahl eines Typs einer Variablen zuzuweisen, die auf einem anderen Typ basiert. Das Casting tritt bei primitiven Typen am häufigsten bei numerischen Typen auf. Boolesche Werte können nicht in einen anderen Primitivtyp konvertiert werden. Sie können aber 1 oder 0 in boolesche Werte konvertieren.

In vielen Casts zwischen primitiven Typen kann das Ziel größere Werte als die Quelle aufnehmen, so daß der Wert ohne Schwierigkeiten konvertiert werden kann. Ein Beispiel hierfür wäre die Konvertierung eines byte in einen int. Da ein byte nur Werte von -128 bis 127 aufnehmen kann und ein int Werte von -2.1 Millionen bis 2.1 Millionen, ist mehr als genug Platz für den Wert in einem byte.

Meist kann ein byte oder ein char automatisch als int oder ein int als long, ein int als float oder etwas anderes als double behandelt werden. In diesem Fall gehen beim Konvertieren des Wertes keine Informationen verloren, weil der größere Typ mehr Genauigkeit bietet als der kleinere.


Ein Zeichen (char) kann als int verwendet werden, da jedes Zeichen einen korrespondierenden numerischen Wert hat, der die Position des Zeichens innerhalb des Zeichensatzes angibt. Wenn die Variable i den Wert 65 hat, liefert der Cast (char)i das Zeichen 'A'. Der numerische Code für A ist nach dem ASCII-Zeichensatz 65. Der ASCII-Zeichensatz ist Teil der Zeichenunterstützung von Java.

Um einen großen Wert auf einen kleineren Typ zu konvertieren, müssen Sie ein explizites Casting anwenden, weil bei dieser Umsetzung der Wert an Genauigkeit einbüßen kann. Explizites Casting sieht so aus:

(Typname) Wert

In dieser Form ist Typname der Name des Typs, auf den Sie konvertieren (z.B. short, int, float, boolean), und Wert ist ein Ausdruck, der den zu konvertierenden Wert ergibt. Dieser Ausdruck teilt den Wert von x durch den Wert von y und wandelt das Ergebnis in int um:

(int) (x / y);

Da Casting eine höhere Präzedenz hat als Arithmetik, müssen Sie Klammern eingeben, damit das Ergebnis der Division an das konvertierte int übergibt. Ansonsten würde als erstes der Wert von x in einen int gecastet und dieser würde anschließend durch y geteilt werden, was natürlich einen anderen Wert ergeben könnte.

Konvertieren von Objekten

Mit einer Einschränkung können auch Klasseninstanzen in Instanzen anderer Klassen konvertiert werden: Die Quell- und die Zielklasse müssen durch Vererbung miteinander verbunden sein. Eine Klasse muß die Subklasse einer anderen sein.

Wie beim Konvertieren eines primitiven Wertes in einen größeren Typ müssen bestimmte Objekte nicht unbedingt explizit konvertiert werden. Insbesondere, weil die Subklassen von Instanzen normalerweise alle Informationen ihrer Superklassen enthalten, können Sie eine Instanz einer Subklasse überall dort verwenden, wo eine Superklasse erwartet wird.

Nehmen wir z.B. an, Sie haben eine Methode mit zwei Argumenten: eines vom Typ Object und eines vom Typ Window. Sie müssen nun nicht Instanzen dieser beiden Klassen an die Methode übergeben. Für das Object-Argument können Sie jede beliebige Subklasse von Object (anders ausgedrückt, jedes Objekt, da in Java alle Klassen Subklassen der Klasse Object sind) und für das Window-Argument jede Instanz einer beliebigen Subklasse von Window (Dialog, FileDialog und Frame) weitergeben.

Dies gilt an beliebiger Stelle in einem Programm - nicht nur in Methodenaufrufen. Wenn Sie eine Variable vom Typ Window deklariert haben, können Sie ihr Objekte dieser oder einer ihrer Subklassen zuweisen, ohne ein Casting ausführen zu müssen.

Dies gilt auch in der umgekehrten Richtung. Sie können eine Superklasse angeben, wenn eine Subklasse erwartet wird. Da allerdings Subklassen mehr Information als deren Superklassen enthalten, ist dies mit einem Verlust an Genauigkeit verbunden. Die Objekte der Superklassen haben eventuell nicht alle Verhaltensweisen und Eigenschaften, um anstelle eines Objekts der Subklasse zu arbeiten. Wenn Sie z.B. eine Operation verwenden, die Methoden in einem Objekt der Klasse Integer aufruft, kann es sein, daß ein Objekt der Klasse Number diese Methoden nicht beinhaltet, da diese in Integer definiert sind. Es treten Fehler auf, wenn Sie versuchen, Methoden aufzurufen, die das Zielobjekt nicht unterstützt.

Um Objekte einer Superklasse dort zu verwenden, wo eigentlich Objekte von Subklassen erwartet werden, müssen Sie diese explizit casten. Sie werden keine Informationen bei dieser Konvertierung verlieren. Statt dessen erhalten Sie alle Methoden und Variablen, die die Subklasse definiert. Um ein Objekt in eine andere Klasse zu casten, verwenden Sie dieselbe Operation, die Sie auch für primitive Typen verwenden:

(Klassenname) Objekt

In diesem Fall ist Klassenname der Name der Klasse, in die Sie das Objekt konvertieren wollen, und Objekt ist eine Referenz auf das konvertierte Objekt. Das Casting erstellt eine neue Instanz der neuen Klasse mit allen Informationen, die das alte Objekt enthielt. Das alte Objekt besteht unverändert fort.

Nachfolgend ein fiktives Beispiel, in dem eine Instanz der Klasse VicePresident in eine Instanz der Klasse Employee konvertiert wird, wobei VicePresident eine Subklasse von Employee ist, die weitere Informationen definiert (z.B. daß der Vice-President besondere Privilegien in den Waschräumen hat):

Employee emp = new Employee();
VicePresident veep = new VicePresident();
emp = veep; // kein Casting in dieser Richtung nötig
veep = (VicePresident)emp; // muß explizit gecastet werden

Casting ist auch immer dann nötig, wenn Sie die neuen 2D-Zeichenoperationen verwenden, die mit Java 1.2 eingeführt wurden. Sie müssen ein Graphics-Objekt in ein Graphics2D-Objekt casten, bevor Sie auf den Bildschirm Grafikausgaben tätigen können. Das folgende Beispiel verwendet ein Graphics-Objekt namens screen, um ein neues Graphics2D-Objekt zu erzeugen, das den Namen screen2D trägt:

Graphics2D screen2D = (Graphics2D)screen;

Graphics2D ist eine Subklasse von Graphics, und beide befinden sich im Paket java.awt . Sie werden das Thema ausführlich am Tag 9 kennenlernen.

Abgesehen vom Konvertieren von Objekten in Klassen können Sie auch Objekte in Schnittstellen konvertieren, jedoch nur, wenn die Klasse oder eine Superklasse des Objekts die Schnittstelle implementiert. Durch Casting eines Objekts in eine Schnittstelle können Sie dann eine der Methoden dieser Schnittstelle aufrufen, auch wenn die Klasse des Objekts diese Schnittstelle nicht direkt implementiert.

Konvertieren von Primitivtypen in Objekte und umgekehrt

Etwas, was unter keinen Umständen möglich ist, ist die Konvertierung eines Objekts in einen primitiven Datentyp oder umgekehrt. Primitive Datentypen und Objekte sind in Java völlig verschiedene Dinge, und es ist nicht möglich, zwischen diesen automatisch zu konvertieren oder sie im Austausch zu verwenden.

Als Alternative enthält das Paket java.lang mehrere Sonderklassen, die je einem primitiven Datentyp entsprechen: Integer, Float, Boolean usw. Beachten Sie bitte, daß die Namen dieser Klassen mit einem Großbuchstaben und die Namen der primitiven Datentypen mit einem Kleinbuchstaben beginnen. Java behandelt die Datentypen und deren Klassenversionen sehr unterschiedlich, und ein Programm kann nicht erfolgreich kompiliert werden, wenn Sie die eine Variante verwenden und die andere erwartet wird. Mit den in diesen Klassen definierten Klassenmethoden können Sie anhand von new für alle primitive Typen ein Gegenstück in Form eines Objekts erstellen. Die folgenden Codezeilen erstellen eine Instanz der Klasse Integer mit dem Wert 4403:

Integer intObject = new Integer(4403);

Sobald Sie auf diese Art ein Objekt erzeugt haben, können Sie es wie jedes andere Objekt verwenden. Möchten Sie die primitiven Werte zurückkonvertieren, gibt es auch dafür Methoden. Wenn Sie z.B. einen int-Wert aus einem dataCount-Objekt herausziehen wollen, könnten Sie die folgende Anweisung verwenden:

int theInt = intObject.intValue(); // gibt 4403 aus

In Programmen werden Sie sehr häufig die Konvertierung von String-Objekten in numerische Typen, wie Integer, benötigen. Wenn Sie einen int als Ergebnis benötigen, dann können Sie dafür die Methode parseInt() der Klasse Integer verwenden. Der String, der konvertiert werden soll, ist das einzige Argument, das dieser Methode übergeben wird. Das folgende Beispiel zeigt dies:

String pennsylvania = "65000";
int penn = Integer.parseInt(pennsylvania);

Schlagen Sie in der Java-API-Dokumentation über diese speziellen Klassen nach. Sie finden dort Erklärungen der Methoden zum Konvertieren von Primitivtypen in Objekte und umgekehrt. Die Dokumentation können Sie auf der Website von JavaSoft (http://java.sun.com ) online lesen oder sich herunterladen.


Es gibt spezielle Typklassen für Boolean, Byte, Character, Double, Float, Integer, Long, Short und Void.

Objekte vergleichen und mehr

Neben dem Casting gibt es noch weitere Operationen, die Sie auf Objekte anwenden können:

Vergleichen von Objekten

Gestern haben Sie Operatoren zum Vergleichen von Werten kennengelernt: gleich, ungleich, kleiner als usw. Die meisten dieser Operatoren funktionieren nur mit primitiven Typen, nicht mit Objekten. Falls Sie versuchen, andere Werte als Operanden zu verwenden, gibt der Java-Compiler Fehler aus.

Die Ausnahme zu dieser Regel bilden die Operatoren für Gleichheit: == (gleich) und != (ungleich). Wenn Sie diese Operatoren auf Objekte anwenden, hat dies nicht den Effekt, den Sie zunächst erwarten werden. Anstatt zu prüfen, ob ein Objekt denselben Wert wie ein anderes Objekt hat, prüfen diese Operatoren, ob es sich bei den beiden Objekten um dasselbe Objekt handelt.

Um Instanzen Ihrer Klasse zu vergleichen und aussagefähige Ergebnisse zu erzielen, müssen Sie spezielle Methoden in Ihre Klasse implementieren und diese Methoden aufrufen.

Ein gutes Beispiel dafür ist die String-Klasse. Es ist möglich, daß zwei String-Objekte dieselben Werte beinhalten. Nach dem Operator == sind diese zwei String-Objekte aber nicht gleich, weil sie zwar den gleichen Inhalt haben, aber nicht dasselbe Objekt sind.

Um festzustellen, ob zwei String-Objekte den gleichen Inhalt haben, definiert die String-Klasse die Methode equals(), die jedes Zeichen in der Zeichenkette prüft und true ausgibt, wenn die zwei Zeichenketten die gleichen Werte haben. Dies wird in Listing 4.5 verdeutlicht.

Listing 4.5: Der komplette Quelltext von EqualsTest.java

 1: class EqualsTest {
 2:     public static void main(String args[]) {
 3:         String str1, str2;
 4:         str1 = "Free the bound periodicals.";
 5:         str2 = str1;
 6:
 7:         System.out.println("String1: " + str1);
 8:         System.out.println("String2: " + str2);
 9:         System.out.println("Same object? " + (str1 == str2));
10:
11:         str2 = new String(str1);
12:
13:         System.out.println("String1: " + str1);
14:         System.out.println("String2: " + str2);
15:         System.out.println("Same object? " + (str1 == str2));
16:         System.out.println("Same value? " + str1.equals(str2));
17:     }
18: }

Das Programm erzeugt die folgende Ausgabe:

String1: Free the bound periodicals.
String2: Free the bound periodicals.
Same object? true
String1: Free the bound periodicals.
String2: Free the bound periodicals.
Same object? false
Same value? true

Der erste Teil dieses Programms (Zeilen 3 bis 5) deklariert die zwei Variablen str1 und str2, weist das Literal "Free the bound periodicals" str1 und dann diesen Wert str2 zu. Wie Sie von Objektreferenzen her wissen, zeigen str1 und str2 jetzt auf dasselbe Objekt. Das beweist der Test in Zeile 9.

Im zweiten Teil wird ein neues String-Objekt mit dem Wert von str1 erstellt. Jetzt bestehen zwei verschiedene String-Objekte mit dem gleichen Wert. Sie werden mit dem Operator == (in Zeile 15) geprüft, um zu ermitteln, ob sie das gleiche Objekt sind. Die erwartete Antwort wird ausgegeben. Schließlich erfolgt das Prüfen mit der equals()- Methode (in Zeile 16), es liefert auch das erwartete Ergebnis (true - beide haben den gleichen Wert).


Warum kann man anstelle von new nicht einfach ein anderes Literal verwenden, wenn man str2 ändert? String-Literale sind in Java optimiert. Wenn Sie ein String mit einem Literal erstellen und dann ein anderes Literal mit den gleichen Zeichen benutzen, weiß Java genug, um Ihnen das erste String-Objekt zurückzugeben. Die beiden Strings sind das gleiche Objekt. Um zwei separate Objekte zu erstellen, müßten Sie sehr umständlich vorgehen.

Bestimmen der Klasse eines Objekts

Möchten Sie die Klasse eines Objekts ermitteln? Hier ist eine Möglichkeit, dies bei einem Objekt zu erreichen, das der Variablen obj zugewiesen ist:

String name = obj.getClass().getName();

Was geschieht hier? Die Methode getClass() ist in der Klasse Object definiert und als solche für alle Objekte verfügbar. Das Ergebnis dieser Methode ist ein Class-Objekt (wobei Class selbst eine Klasse ist), die die Methode getName() hat. getName() gibt den Namen der Klasse als Zeichenkette aus.

Einen anderen nützlichen Test bietet der Operator instanceof. instanceof hat zwei Operanden: ein Objekt links und den Namen einer Klasse rechts. Der Ausdruck gibt true oder false aus, je nachdem, ob das Objekt eine Instanz der benannten Klasse oder eines der Superklassen dieser Klasse ist:

"swordfish" instanceof String // true
Point pt = new Point(10, 10);
pt instanceof String // false

Der Operator instanceof kann auch für Schnittstellen benutzt werden. Falls ein Objekt eine Schnittstelle implementiert, gibt der instanceof-Operator mit einem Schnittstellennamen auf der rechten Seite true aus.

Klassen und Methoden mit Reflexion inspizieren

Eine der Verbesserungen von Java nach dem Release 1.0.2 ist die Einführung von Reflexion, auch als Introspection bezeichnet. Reflexion bzw. Introspection ermöglicht es einer Java-Klasse - beispielsweise einem von Ihnen geschriebenen Programm - Details über eine beliebige andre Klasse zu ermitteln.

Mit Reflexion kann ein Java-Programm eine Klasse laden, von der es nichts weiß, die Variablen, Methoden und Konstruktoren dieser Klasse ermitteln und damit arbeiten.

Das ergibt wahrscheinlich mehr Sinn, wenn Sie es an einem Beispiel sehen. Listing 4.6 ist eine kleine Java-Applikation namens SeeMethods.

Listing 4.6: Der komplette Text von SeeMethods.java

 1: import java.lang.reflect.*;
 2: import java.util.Random;
 3:
 4: class SeeMethods {
 5:     public static void main(String[] arguments)  {
 6:         Random rd = new Random();
 7:         Class className = rd.getClass();
 8:         Method[] methods = className.getMethods();
 9:         for (int i = 0; i < methods.length; i++) {
10:             System.out.println("Method: " + methods[i]);
11:         }
12:     }
13: }

In diesem Programm wird die java.lang.reflect.*-Klassengruppe genutzt, die Informationen über die Attribute, Methoden und Konstruktor-Methoden beliebiger Klassen liefert.

Die Applikation SeeMethods erzeugt in Zeile 6 ein Random-Objekt und nutzt dann Reflexion zur Anzeige aller öffentlichen Methoden, die ein Teil dieser Klasse sind. Listing 4.7 zeigt die Ausgabe der Applikation.

Listing 4.7: Die Ausgabe der Applikation SeeMethods

 1: Method: public final native java.lang.Class java.lang.Object.getClass()
 2: Method: public native int java.lang.Object.hashCode()
 3: Method: public boolean java.lang.Object.equals(java.lang.Object)
 4: Method: public java.lang.String java.lang.Object.toString()
 5: Method: public final native void java.lang.Object.notify()
 6: Method: public final native void java.lang.Object.notifyAll()
 7: Method: public final native void java.lang.Object.wait(long) throws
java.lang.InterruptedException
 8: Method: public final void java.lang.Object.wait(long,int) throws
java.lang.InterruptedException
 9: Method: public final void java.lang.Object.wait() throws
java.lang.InterruptedException
10: Method: public synchronized void java.util.Random.setSeed(long)
11: Method: public void java.util.Random.nextBytes(byte[])
12: Method: public int java.util.Random.nextInt()
13: Method: public long java.util.Random.nextLong()
14: Method: public float java.util.Random.nextFloat()
15: Method: public double java.util.Random.nextDouble()
16: Method: public synchronized double java.util.Random.nextGaussian()

Durch Reflexion kann die Applikation SeeMethods die einzelnen Methoden der Random -Klasse und alle Methoden, die sie von Random übergeordneten Klassen geerbt hat, kennenlernen. Jede Zeile im Listing zeigt folgende Informationen über eine Methode:

Die Applikation SeeMethods kann mit jeder Objektklasse ausgeführt werden - ändern Sie die Zeile 6 in SeeMethods.java, um ein anderes Objekt zu erzeugen und einen Blick in sein Inneres zu werfen.

Am häufigsten wird Reflexion von Tools wie beispielsweise Klassen-Browsern und -Debuggern eingesetzt, um mehr über die Klassen der durchsuchten oder getesteten Objektklasse zu erfahren. Außerdem wird Reflexion im Zusammenhang mit JavaBeans eingesetzt. Hier ist es bei der Erstellung größerer Anwendungen hilfreich, daß ein Objekt ein anderes Objekt abfragen kann, was es machen kann (und es dann auffordern kann, etwas zu tun). Über JavaBeans erfahren Sie noch mehr während Tag 19.

Das java.lang.reflect-Paket umfaßt folgende Klassen:

Darüber hinaus ist eine Reihe neuer Methoden in einer Objektkasse namens Class verfügbar, die helfen, die verschiedenen Reflexions-Klassen zusammenzuhalten.

Reflexion ist ein fortgeschrittenes Feature, das Sie nicht einfach so in Ihren Programmen einsetzen. Es wird dann besonders nützlich, wenn Sie mit Objektserialisation, JavaBeans und anderen ausgeklügelten Java-Programmiertechniken arbeiten.

Zusammenfassung

Nun da Sie einen großen Schluck aus der Flasche der objektorientierten Programmierung mit Java genommen haben, sind Sie besser in der Lage zu entscheiden, wie nützlich dies für Ihre eigene Programmierung ist.

Wenn Sie zu der Sorte Mensch gehören, für die ein Glas bei der Hälfte halb leer ist, dann ist die objektorientierte Programmierung eine Abstraktionsebene, die sich zwischen Sie und das stellt, für das Sie die Programmiersprache verwenden wollen. Sie lernen in den nächsten Kapiteln mehr darüber, warum die OOP vollkommen in Java integriert ist.

Wenn Sie zu den Halb-voll-Menschen gehören, dann lohnt sich für Sie die Anwendung der objektorientierten Programmierung aufgrund der Vorteile, die Sie bietet: verbesserte Verläßlichkeit, Lesbarkeit und Pflegbarkeit.

Heute haben Sie gelernt, wie Sie mit Objekten umgehen: sie erzeugen, deren Werte lesen und verändern und deren Methoden aufrufen. Sie haben außerdem gelernt, wie Sie Objekte einer Klasse in eine andere Klasse konvertieren bzw. wie Sie von einem Datentyp zu einer Klasse konvertieren.

Schließlich haben Sie einen ersten Blick auf die Reflexion geworfen; damit kann man ein Objekt dazu veranlassen, Details über sich selbst zu zeigen.

An diesem Punkt besitzen Sie die Fähigkeiten, um die meisten einfachen Aufgaben in Java zu bewältigen. Was nun noch fehlt sind Arrays, Bedingungen und Schleifen (die morgen behandelt werden) und wie Sie Klassen definieren und verwenden (wird an Tag 6 durchgenommen).

Fragen und Antworten

Frage:
Mir ist der Unterschied zwischen Objekten und den primitiven Datentypen, z.B. int und boolean, noch nicht ganz klar.

Antwort:
Die primitiven Typen (byte, short, int, long, float, double und char) sind die kleinsten Elemente der Sprache Java. Es sind keine Objekte, obwohl sie auf vielerlei Art wie Objekte gehandhabt werden. Sie können Variablen zugewiesen und zwischen Methoden weitergereicht werden. Die meisten Operationen werden aber auf Objekte ausgeführt.

Objekte stellen normalerweise Klasseninstanzen dar und sind daher viel komplexere Datentypen als einfache Zahlen und Zeichen. Sie enthalten aber meist Zahlen und Zeichen als Instanz- oder Klassenvariablen.

Frage:
Keine Zeiger in Java? Wenn es in Java keine Zeiger gibt, wie kann man dann so Dinge wie verkettete Listen, wo Zeiger von einem Eintrag auf den nächsten verweisen, so daß sie diese durchqueren können, erstellen?

Antwort:
Es stimmt nicht, wenn man sagt, daß es in Java überhaupt keine Zeiger gibt - es gibt keine expliziten Zeiger. Objektreferenzen sind letztendlich Zeiger. Um eine verkettete Liste zu erzeugen, könnten Sie eine Klasse Node erstellen, die eine Instanzvariable vom Typ Node hat. Um Node-Objekte miteinander zu verketten, weisen Sie der Instanzvariablen des Objekts direkt davor in der Liste ein Node-Objekt zu. Da Objektreferenzen Zeiger sind, verhalten sich verkettete Listen, die auf diese Weise erstellt wurden, wie Sie das erwarten.



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Ein Imprint des Markt&Technik Buch- und Software-Verlag GmbH.
Elektronische Fassung des Titels: Java 2 in 21 Tagen, ISBN: 3-8272-5578-3