1. Referenzdatentypen: Felder und Strings Referenz

Werbung
1. Felder und Strings
Eigenschaften von Referenzdatentypen
1. Referenzdatentypen: Felder und Strings
• Referenzdatentypen sind Konstrukte, mit deren Hilfe wir aus einfachen Datentypen
neue “eigene” Typen erzeugen können.
• In Java gibt es prinzipiell zwei Arten von Referenzdatentypen: Felder und Klassen.
• In diesem Kapitel lernen wir den Umgang mit Feldern und die Benutzung der Klassen String und StringBuffer.
• Die Nutzung von Klassen ist Thema des nächsten Kapitels.
• Die Definition eigener Klassen ist Thema des übernächsten Kapitels.
1. Felder und Strings
Eigenschaften von Referenzdatentypen
• Im Unterschied zum einfachen Datentyp wird der Wert 124 der Variablen r nicht als
numerischer Wert interpretiert, sondern als Adresse für eine andere Speicherzelle.
Dort findet sich der “eigentliche” Wert bzw. unser “eigentliches” Objekt.
• Mit der Literalkonstanten null repräsentieren wir eine Referenz, die auf nichts (in
das Nirgendwo) verweist.
Wenn die Variable r von einem Referenztyp ist, dann sind
r = null;
...
if ( r == null )
...
gültige Anweisungen.
• Grafische Notation für Variablen:
b
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
10
1. Felder und Strings
Eigenschaften von Referenzdatentypen
Referenz- vs. einfache Datentypen
b
Adresse im Speicher
...
Inhalt
...
Typ
96
4711
int
r
...
104
...
124
...
...
r
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
12
Einfache Datentypen
Rückblick: Einfache Datentypen (1)
• einfacher Datentyp: Eine Speicherzelle, die mit einer Variablen assoziiert ist,
enthält den Wert der Variablen (direkter Zugriff).
• Referenztyp: Eine Speicherzelle, die mit einer Variablen assoziiert ist, enthält eine
Referenz (Verweis, Zeiger) auf eine andere Speicherzelle, die den Wert enthält
(indirekter Zugriff).
symbolische Adresse
4711
124
...
...
• Ganzzahlige Datentypen
long int short byte
Repräsentation: Zweierkomplement
• Gleitkommatypen
double float
Repräsentation: 32 bzw. 64 Bit im IEEE 754 Standard
• char
Repräsentation: als vorzeichenloser 16-Bit Integerwert
• boolean
Referenz
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
11
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
13
1. Felder und Strings
Einfache Datentypen
Rückblick: Einfache Datentypen (2)
1. Felder und Strings
Einfache Datentypen
• Die folgende Anweisung dagegen liefert einen Fehler beim Compilieren:
int i = 3.0;
Grund: 3.0 ist eine double-Zahl. Bei einer Umwandlung nach int geht eventuell
Information verloren.
Zu einem einfachen Datentyp gehört
• Stattdessen könnten wir eine explizite Typkonvertierung (explicite Typecast)
durchführen. Hierzu schreibt man den Zieldatentyp in Klammern vor die entsprechende Zahl oder Ausdruck.
• sein Wertebereich,
• sein lexikalischer Bereich (Literale) und
• die zur Verfügung stehenden Operationen.
(int) 3.14
Hier würde der Compiler die Nachkommastellen abschneiden.
• Eine Umwandlung von boolean in einen anderen Datentyp ist nicht möglich.
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
14
Einfache Datentypen
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
16
Eindimensionale Felder
Felder
Einfache Datentypen: Implizite und explizite Typumwandlung
• Wir wollen die Addition
92233720366854775000L + 807
durchführen. Der Plus-Operator ist aber nur für Werte des gleichen Typs definiert.
Was tun?
• Der Java-Compiler erkennt, daß der Datentyp zur linken Zahl einen Wertebereich
hat, der den der rechten Zahl umfasst. So wird die 807 vom Compiler in eine
automatisch long-Zahl umgewandelt.
☞ implizite Typkonvertierung (implicite typecast)
• Implizite Typkonvertierungen treten immer dann auf, wenn ein kleinerer Zahlenbereich in einen größeren Zahlenbereich abgebildet wird.
byte → short → int → long
char → int
float → double
• Ganzzahlige Datentypen können auch implizit in Gleitkommatypen umgewandelt
werden, obwohl dabei Rundungsfehler auftreten können.
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
15
• Felder (Arrays) gestatten es, mehrere Variablen durch einen gemeinsamen Namen
anzusprechen und lediglich durch einen Index zu unterscheiden.
• Alle diese indizierten Variablen haben dabei den gleichen Typ (Komponententyp,
Basistyp).
• Die Variablen selbst werden als Komponenten des Feldes bezeichnet.
• Der Index zum Ansprechen der Komponenten ist vom Typ int. Hierbei sind nur
nichtnegative Werte erlaubt.
• Wir können uns vorstellen, daß die Komponenten eines Feldes aufeinanderfolgend
im Speicher des Rechners abgelegt sind.
• Der Index für eine Komponente ergibt sich dabei aus der Position innerhalb des
Feldes, von Null aufwärts gezählt.
• Beispiel:
– Repräsentation eines Vektors des IRn: Feld mit double als Komponententyp
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
17
1. Felder und Strings
Eindimensionale Felder
Deklaration von Feldern
1. Felder und Strings
Eindimensionale Felder
Deklaration und Erzeugung können auch zusammen erfolgen. Beispiele:
int[]
zahlenfolge = new int[20];
double[] vektor = new double[3];
Syntax:
Komponententyp[] Variablenname;
Bitte beachten Sie:
Beispiele:
int[]
zahlenfolge;
double[] vektor;
• Die eckigen Klammern machen deutlich, daß die Variable ein Feld referenziert, mit
dem Typ links von [] als Komponententyp.
• Als Komponententyp sind nicht nur einfache Datentypen, sondern auch Referenztypen erlaubt.
☞ Die Größe eines Feldes ist nicht Bestandteil des Typs. Sie wird erst bei der Erzeugung des Feldes festgelegt.
☞ Die Feldlänge kann durch einen Ausdruck angegeben werden.
☞ Einer Feld-Variable können jederzeit andere Felder gleichen Typs zugewiesen werden.
double[] vektor = new double[3];
double[] vektor2 = new double[7];
String[] wortliste;
vektor = new double[3];
vektor = new double[5];
vektor = vektor2;
• Insbesondere sind auch Feldtypen als Komponententyp erlaubt (hierzu später
mehr).
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
18
Eindimensionale Felder
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
Erzeugung von Feldern
20
Eindimensionale Felder
Komponentenzugriff und -initialisierung
double[] vektor = new double[3];
☞ Die Deklaration einer Feld-Variablen erzeugt kein Feld!
• Nach der Deklaration existiert eine Variable, die eine Referenz auf ein Feld als
Wert aufnehmen, kann.
• Das eigentliche Feld existiert aber noch nicht.
Welchen Wert haben die Feldkomponenten nach der Erzeugung?
Syntax zur Erzeugung von Feldern:
•
•
•
•
•
Variablenname = new Komponententyp [ Feldlänge ];
Beispiele:
Dies ist für jeden möglichen Komponententyp festgelegt:
ganzzahlige Typen: 0
char: ’\0’
double bzw. float: 0.0 bzw. 0.0f
boolean: false
Referenztyp: null
zahlenfolge = new int[20];
vektor
= new double[3];
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
19
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
21
1. Felder und Strings
Eindimensionale Felder
Syntax für die Wertzuweisung an eine Komponente:
1. Felder und Strings
Eindimensionale Felder
• Statt Erzeugung mit new und anschließender Initialisierung durch Wertzuweisungen ist auch eine verkürzte Schreibweise möglich.
• Beispiele:
Variablenname[Index] = Wert;
int[]
lottozahlen = { 6, 11, 19, 21, 30, 40 };
double[] vektor = { 1.0, 2.0, -1.0 };
String[] wortliste = { "ganz", "viele", "Wörter" };
Beispiel:
vektor[0] = 1.0; vektor[1] = 2.0; vektor[2] = -1.0;
• Index muß ein Ausdruck sein, der einen int-Wert liefert.
• Der Wert für Index muß zwischen 0 und Feldlänge-1 liegen.
• Wert kann natürlich ein beliebiger Ausdruck passend zum Komponententyp sein.
int[] quadratFolge = new int[100];
• Die geklammerten Ausdrücke heißen Feld-Initialisierer (array initializer).
• Nur Literale oder Konstanten dürfen als Wert in einem Feld-Initialisierer auftreten.
• Diese Schreibweise ist nur in Verbindung mit einer Deklaration erlaubt, nicht für
eine gewöhnliche Zuweisung.
for (int i=0 ; i<100 ; i++ )
quadratFolge[i] = i*i;
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
22
Eindimensionale Felder
Syntax für den Zugriff auf den Wert einer Komponente (als Ausdruck):
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
24
Eindimensionale Felder
Ermittlung der Länge von Feldern
Variablenname[Index]
Beispiel:
• Bei der Erstellung eines Feldes wird dessen Länge in einem zusätzlichem Element
vom Typ int abgespeichert.
• Auf dieses Element kann mit
double summe = 0.0;
for (int i=0 ; i<3 ; i++ ) {
System.out.println( "vektor[" + i + "] = " + vektor[i] );
summe = summe + vektor[i] * vektor[i];
}
System.out.println("Laenge des Vektors: " + Math.sqrt( summe ));
Variablenname.length
zugegriffen werden.
• Beispiel:
double[] vektor = { 1.0, 2.0, -1.0 };
for (int i=0 ; i<vektor.length ; i++ )
System.out.println( "vektor[" + i + "] = " + vektor[i] );
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
23
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
25
1. Felder und Strings
Eindimensionale Felder
1. Felder und Strings
Eindimensionale Felder
2. Nutzung der Methode System.arraycopy:
Kopieren und Vergleichen von Referenzen
System.arraycopy( Quelle, QuelleStartIndex,
Ziel, ZielStartIndex,
Anzahl );
double[] v = { 1.0, 3.0, 5.0, 10.0 };
double[] q = v;
for ( int i=0 ; i<q.length ; i++ )
q[i] = q[i]*q[i];
for ( int i=0 ; i<q.length ; i++ )
System.out.println( "Das Quadrat von " + v[i] + " ist " + q[i] );
Was wird ausgegeben und warum?
Hierbei ist:
• Quelle: Feld, von dem kopiert werden soll
• QuelleStartIndex: Index, ab der Quelle übertragen werden soll
• Ziel: Feld, in das kopiert werden soll
• ZielStartIndex: Index, ab dem die Eintragungen erfolgen sollen
• Anzahl: Anzahl der zu kopierenden Komponenten
3. Nutzung der vordefinierten Methode clone. Hierzu später mehr.
☞ Alle diese Möglichkeiten legen eine sogenannte flache Kopie an.
☞ D.h. für die Komponenten selbst wird die übliche Zuweisung durchgeführt.
☞ Dies kann problematisch sein, wenn der Komponententyp selbst eine Referenzdatentyp ist (Referenzkopie).
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
26
1. Felder und Strings
Eindimensionale Felder
• Die Zuweisung q = v; führt zu einer sogenannten Referenzkopie.
• Es wird keine Kopie des Feldes angelegt, sondern q erhält die Referenz, die in v
hinterlegt ist.
• Wirkung: q und v verweisen auf das gleiche Feld.
v
1.0
3.0
5.0
10.0
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
28
1. Felder und Strings
Eindimensionale Felder
• int[] feld1 = { 1, 2, 3 };
int[] feld2 = { 1, 2, 3 };
• Der Ausdruck feld1 == feld2 liefert false!
• Begründung: Bei Referenzdatentypen bedeutet == nicht, daß die Inhalte der referenzierten Felder (oder Objekte) verglichen werden.
• Stattdessen wird geprüft, ob die Referenzen die gleiche Speicherstelle adressieren.
feld1
1
2
3
feld2
1
2
3
q
Für die Herstellung einer “echten Kopie” haben wir die folgenden Möglichkeiten:
• Wie vergleicht man dann die Inhalte von Feldern?
☞ Ausprogrammieren
• Achtung: Der Komponententyp kann wieder ein Referenztyp sein!
1. Wir benutzen eine Schleife:
double[] v2 = new double[ v.length ];
for ( int i=0 ; i<v.length ; i++ )
v2[i] = v[i];
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
27
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
29
1. Felder und Strings
Mehrdimensionale Felder
Mehrdimensionale Felder
Mehrdimensionale Felder sind vom Prinzip her leicht zu definieren: Der Komponententyp ist selbst ein Feld.
Beispiele:
double[][] matrix;
int[][]
folgeVonFolgen;
String[][] listeVonStringListen;
Sollen alle “inneren” Felder die gleiche Länge aufweisen, können wir wiederum den
new-Operator in einfacher Weise verwenden:
matrix = new double[3][4];
folgeVonFolgen = new int[3][50];
listeVonStringListen = new String[5][30];
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
1. Felder und Strings
30
Mehrdimensionale Felder
Beispiele für “innere” und “äußere” Feldlängen:
• matrix.length liefert 3.
• matrix[0].length liefert 4.
• matrix[2].length liefert ebenfalls 4.
Die “inneren” Felder können eine unterschiedliche Länge aufweisen.
int[][] folgeVonFolgen = new int[3][];
for ( int i=0 ; i<folgeVonFolgen.length ; i++ )
folgeVonFolgen[i] = new int[10*(i+1)];
• folgeVonFolgen.length liefert 3.
• folgeVonFolgen[0].length liefert 10.
• folgeVonFolgen[2].length liefert 30.
Peter Becker, Programiersprache Java — FH Bonn-Rhein-Sieg, SS 08
31
Herunterladen