Читать книгу Algorithmen und Datenstrukturen - Gunter Saake - Страница 57

2.5.2Referenzdatentypen

Оглавление

Referenz null

Die zweite Form von Datentypen in Java sind die Referenzdatentypen. Variablen dieser Typen enthalten nicht die Daten selbst wie bei den primitiven Datentypen, sondern nur einen Verweis (Referenz) auf den Speicherort der Daten. Der Standardwert von Referenzvariablen ist null, der besagt, dass die Variable auf kein Objekt verweist.

Bei Referenzdatentypen lassen sich wiederum zwei Arten unterscheiden:

Feld

 Ein Feld (Array) ist eine Datenstruktur fester Größe, die aus Elementen gleichen Typs (sowohl primitive als auch Referenzdatentypen) aufgebaut ist.

Objektdatentyp

 Ein Objektdatentyp dient dagegen zur Repräsentation von Objekten, die wir erst später behandeln werden.

Felder werden bei der Deklaration durch das Anhängen eckiger Klammern »[]« an den Datentyp oder den Bezeichner gekennzeichnet. So werden im Folgenden zwei Referenzvariablen auf Felder von int-Werten vereinbart:

int einFeld[];

int[] auchEinFeld;

Allokation

Felder erfordern in Java eine explizite Allokation, d.h., der benötigte Speicherplatz muss bereitgestellt werden. Dies erfolgt durch

new -Operator

 Aufruf des new-Operators, wobei hinter dem Operator der Elementtyp und – in Klammern – die Anzahl der Elemente anzugeben sind. So wird durch die Anweisungint[] feld = new int[20];der Variablen feld ein Verweis auf einen Speicherbereich für 20 int-Werte zugewiesen.

Initialisierung

 Initialisierung mit Literalen, die in geschweiften Klammern als Aufzählung angegeben werden. Alle Literale müssen zum Typ der Feldvariablen passen. Die Feldlänge entspricht der Anzahl der angegebenen Literale. Im folgenden Beispiel verweist feld daher auf einen Speicherbereich, in dem die drei angegebenen Werte abgelegt sind:int[] feld = { 5, 23, 42 };

Zuweisung

 Zuweisung, wobei hier eigentlich kein Speicherplatz bereitgestellt wird, sondern die Variable nur mit einem Verweis auf den Inhalt der rechten Seite der Zuweisung belegt wird:

int[] feld = einAnderesFeld;

Referenzvariablen

Eine wichtige Eigenschaft von Referenzvariablen ist die Tatsache, dass Vergleiche (z.B. mittels »==«) und Zuweisungen (über »=«) auf den Referenzen erfolgen. So zeigt im Beispiel in Abbildung 2–6 die Variable feld2 nach der Zuweisung von feld1 ebenfalls auf das Feld und nicht etwa auf eine Kopie!

Abb. 2–6 Zuweisung von Referenzen

Kopieren von Feldern

Das Kopieren des Feldes müsste daher entweder durch Anlegen eines neuen Feldes und das anschließende elementweise Kopieren erfolgen oder unter Nutzung der speziellen Methode arraycopy, deren Anwendung im folgenden Beispiel demonstriert wird:

int[] feld1 = { 1, 2, 3, 4, 5 };

int[] feld2 = new int[feld1.length];

int pdest = 0, psrc = 0;

// Kopiert feld1.length Elemente des Feldes feld2

// von Position psrc nach feld1 an Position pdest

System.arraycopy(feld1, psrc, feld2, pdest,

feld1.length);

Der Zugriff auf ein einzelnes Element eines Feldes erfolgt über die Notation feld [index]. Hierbei ist zu beachten, dass das erste Element den Index 0 besitzt. Die Länge eines Feldes kann über die Eigenschaft feld. length bestimmt werden, so dass der gültige Bereich eines Index des Feldes 0...length-1 beträgt. Zugriffsversuche außerhalb dieses Bereiches werden vom Java-Interpreter erkannt und als Fehler signalisiert.

Betrachten wir als ein weiteres Anwendungsbeispiel von Feldern das bekannte Spiel »Tic Tac Toe« (auch als »Drei gewinnt« bekannt), bei dem zwei Spieler auf einem 3x3-Feld abwechselnd ihre Spielsteine setzen müssen. Ein solches Feld wird in Programmiersprachen typischerweise als ein Feld von Feldern dargestellt – in unserem Fall also als Feld von 3 Feldern aus jeweils 3 char-Elementen (Abbildung 2–7). Dieses Feld mit dem in der Abbildung 2–7 dargestellten Zustand kann daher in Java wie folgt definiert werden:

Abb. 2–7 Tic-Tac-Toe-Spielfeld

char spielfeld[] [] = {

{ ’ ’, ’x’, ’o’ },

{ ’ ’, ’o’, ’x’ },

{ ’ ’, ’ ’, ’ ’ }

};

Der Zustand des mittleren Feldes kann demzufolge durch spielfeld[1][1] ausgelesen werden. Das Setzen eines Spielsteins entspricht dann dem Zuweisen eines Wertes (hier also ’x’ oder ’o’) an ein Feldelement, z.B. unten links:

spielfeld[2][0] = ’o’;

Wir werden später auf dieses Beispiel zurückkommen, um weitere Programmierkonzepte zu illustrieren.

Zeichenketten Erzeugung von Strings

Bei der Vorstellung des Zeichen-Datentyps haben wir bereits erwähnt, dass Zeichenketten in Java nicht durch einen eigenen Datentyp, sondern in Form der Klasse java.lang.String unterstützt werden. Strings sind damit Objekte, die man erzeugen muss und über Methoden manipulieren kann. Genau wie bei Feldern kann die Erzeugung von String-Objekten über den new-Operator, durch Initialisierung mit einem Zeichenkettenliteral oder durch Zuweisung eines anderen String-Objektes erfolgen.

String s1 = new String("Algorithmen");

String s2 = "Datenstrukturen";

String s3 = s2;

String-Methoden

Für die Arbeit mit Strings stehen eine Reihe von Methoden zur Verfügung, so u.a.:

 int length() liefert die aktuelle Länge des Strings (in Zeichen).

 char charAt(int idx) gibt das Zeichen an der Position idx als char-Wert zurück.

 int compareTo(String other) vergleicht das aktuelle String-Objekt mit dem Objekt other und liefert − 1, wenn es lexikographisch kleiner ist, entsprechend +1, wenn es größer ist, und 0 bei Gleichheit.

 int indexOf(int ch) liefert die Position des ersten Auftretens des Zeichens ch im String.

 int lastIndexOf(int ch) liefert die Position des letzten Auftretens des Zeichens ch.

 int indexOf(String s) liefert die Position des ersten Auftretens der Zeichenkette s im String.

 String replace(char oldC, char newC) liefert ein neues String-Objekt, das eine Kopie des ursprünglichen Strings ist, wobei alle Zeichen oldC durch newC ersetzt sind.

 String substring(int begin) liefert ein neues String-Objekt, das aus den Zeichen begin … length ()-1 besteht.

 String substring(int begin, int end) liefert ein neues String-Objekt, das aus den Zeichen begin … end-1 besteht.

 boolean startsWith(String prefix) prüft, ob der String mit dem Präfix prefix beginnt, und liefert in diesem Fall true, andernfalls false.

 boolean endsWith(String suffix) prüft, ob der String mit der Zeichenkette suffix endet.

Konkatenation

Eine Besonderheit der Klasse String ist, dass die Objekte nicht änderbar sind. So liefert beispielsweise die Methode replace ein neues Objekt mit der durchgeführten Ersetzung zurück, das ursprüngliche Objekt bleibt aber unverändert. Allerdings lassen sich mithilfe des +-Operators sehr einfach String-Objekte aneinander hängen:

s3 = s1 + " und " + s2;

Das Ergebnis dieser Anweisung ist ein Objekt s3 mit der Zeichenkette »Algorithmen und Datenstrukturen«. Die Anwendung der verschiedenen Methoden demonstriert das folgende Beispiel anhand der Ersetzung von »und« durch »&«:

String und = "und";

int pos = s3.indexOf(und);

String s4 = s3.substring(0, pos) + "&" +

s3.substring(pos + und.length());

System.out.println(s4);

Textblock

Seit Version 13 akzeptiert Java als Preview auch mehrzeilige Zeichenkettenkonstanten in Form sogenannter Textblöcke. Hierzu muss die mehrzeilige Zeichenkette in dreifache Anführungszeichen eingeschlossen werden, wobei hinter der öffnenden Folge sofort ein Zeilenwechsel stehen muss:

String s = """

Algorithmen und Datenstrukturen

"Eine Einführung mit Java"

""";

Wie das Beispiel zeigt, können in der Zeichenkette auch Anführungszeichen vorkommen, ohne dass diese besonders gekennzeichnet werden müssten (z.B. durch einen Backslash). Gibt man die obige Zeichenkette mit System.out.println(s) aus, wird deutlich, wie Einrückungen behandelt werden:

Algorithmen und Datenstrukturen

"Eine Einführung mit Java"

Aktuell ist zu beachten, dass es sich um ein Preview-Feature handelt und Compiler bzw. JVM mit der Option –enable-preview ausgeführt werden müssen.

Es sei angemerkt, dass es noch eine weitere Klasse java.lang.StringBuffer gibt, die ähnlich wie String aufgebaut ist, jedoch die Änderung der Zeichenkette (Einfügen, Anhängen von Zeichen etc.) erlaubt und in einfacher Weise von und nach String konvertiert werden kann.

Algorithmen und Datenstrukturen

Подняться наверх