Previous Page TOC Index Next Page See Page

7

Mehr über Methoden



von
Laura Lemay

Methoden zählen zu den wichtigsten Teilen jeder objektorientierten Sprache. Während Klassen und Objekte den Rahmen bilden und Klassen- und Instanzvariablen Attribute und Zustände dieser Klasse oder Objekte aufnehmen, sind es die Methoden, die das Verhalten eines Objekts bestimmen und definieren, wie ein Objekt mit anderen im System interagiert.

Gestern haben Sie ein wenig über das Definieren von Methoden gelernt. Mit diesem Grundwissen können Sie bereits verschiedene Java-Programme schreiben, jedoch würden ihnen einige Merkmale von Methoden fehlen, durch die Java-Programme erst richtig leistungsstark werden. Durch sie werden Ihre Objekte und Klassen effizienter und übersichtlicher. Heute lernen Sie alles über diese zusätzlichen Merkmale, darunter:

Methoden mit dem gleichen Namen, aber anderen
Argumenten erstellen

Gestern haben Sie gelernt, wie Methoden mit einem Namen und einer Signatur erstellt werden. In Java können Methoden darüber hinaus auch »überladen« werden. Das bedeutet, daß Sie Methoden mit dem gleichen Namen, jedoch anderen Signaturen und anderen Definitionen erstellen können. Durch das Überladen von Methoden können Instanzen einer Klasse eine einfachere Schnittstelle für andere Objekte haben (es besteht keine Notwendigkeit für völlig unterschiedliche Methoden, die im Grunde das gleiche bewirken) und sich je nach Eingabe in die Methode anders verhalten.

Beim Aufrufen einer Methode in einem Objekt prüft Java den Methodennamen sowie Zahl und Typ der Argumente ab, um zu ermitteln, welche Methodendefinition auszuführen ist.

Um eine Methode zu überladen, legen Sie lediglich mehrere unterschiedliche Methodendefinitionen in einer Klasse an, die alle den gleichen Namen, jedoch unterschiedliche Parameter (entweder in bezug auf die Zahl oder den Typ der Argumente) und unterschiedliche Rümpfe haben. Java erkennt überladene Methoden daran, daß die einzelnen Parameterlisten für jeden Methodennamen eindeutig sind.

Java unterscheidet überladene Methoden mit dem gleichen Namen anhand der Zahl und des Typs der Parameter für die jeweilige Methode, nicht anhand des Rückgabetyps. Das heißt, wenn Sie zwei Methoden mit dem gleichen Namen, der gleichen Parameterliste, jedoch unterschiedlichen Rückgabetypen erstellen, erhalten Sie einen Kompilierfehler. Die für jeden Parameter einer Methode gewählten Variablennamen sind nicht relevant, nur die Zahl und der Typ zählen.

Im folgenden Beispiel wird eine überladene Methode erstellt. Listing 7.1 zeigt eine einfache Klassendefinition für die Klasse MyRect, die eine Rechteck definiert. Die Klasse MyRect hat vier Instanzvariablen, die die obere linke und untere rechte Ecke des Rechtecks definieren: x1, y1, x2 und y2.


Warum habe ich die Klasse MyRect genannt? Im awt-Paket von Java ist eine Klasse namens Rectangle enthalten, die einen Großteil des gleichen Verhaltens implementiert. Um zu vermeiden, daß die zwei Klassen verwechselt werden, habe ich diese Klasse MyRect genannt.

Listing 7.1: Die MyRect-Klasse

class MyRect {

int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
}


Versuchen Sie nicht dieses Beispiel an dieser Stelle bereits zu kompilieren. Es wird zwar kompiliert werden ohne Fehler zu erzeugen, allerdings wird es nicht laufen, da es (noch) keine main()-Methode besitzt. Wenn das die Klassendefinition fertig ist, wird die endgültige Version sich sowohl kompilieren als auch ausführen lassen.

Wird eine neue Instanz von der Klasse MyRect erstellt, werden alle ihre Instanzvariablen mit 0 initialisiert. Wir definieren nun die Methode buildRect(), die die Größe des Rechtecks anhand von vier Integer-Argumenten auf die entsprechenden Werte abändert, so daß das Reckteckobjekt richtig ausgegeben wird (da die Argumente den gleichen Namen als Instanzvariablen haben, müssen Sie sicherstellen, daß auf sie mit this verwiesen wird):

MyRect buildRect (int x1, int y1, int x2, int y2) {

this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
return this;
}

Was nun, wenn man nun die Dimensionen des Rechtecks auf andere Weise definieren will, z.B. durch Verwendung von Point-Objekten anstelle der einzelnen Koordinaten? In diesem Fall überladen Sie buildRect(), so daß dessen Parameterliste zwei Point-Objekte erhält (Sie müssen die Point-Klasse an den Anfang Ihrer Quelldatei importieren, damit Java sie findet):

MyRect buildRect (Point topLeft, Point bottomRight) {

x1 = topLeft.x;
y1 = topLeft.y;
x2 = bottomRight.x;
y2 = bottomRight.y;
return this;
}

Eventuell möchten Sie das Rechteck mit einer oberen Ecke sowie einer bestimmten Breite und Höhe definieren. Hierfür schreiben Sie einfach eine andere Definition für buildRect():

MyRect buildRect (Point topLeft, int w, int h) {

x1 = topLeft.x;
y1 = topLeft.y;
x2 = (x1 + w);
y2 = (y1 + h);
return this;
}

Um dieses Beispiel zu beenden, erstellen wir eine Methode zum Ausgeben der Koordinaten des Recktecks und eine main()-Methode zum Testen aller Werte (einfach um zu beweisen, daß das tatsächlich funktioniert). Listing 7.2 zeigt die fertige Klassendefinition mit allen Methoden.

Listing 7.2: Die fertige MyRect-Klasse

import java.awt.Point;


class MyRect {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;

MyRect buildRect (int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
return this;
}
MyRect buildRect(Point topLeft, Point bottomRight) {
x1 = topLeft.x;
y1 = topLeft.y;
x2 = bottomRight.x;
y2 = bottomRight.y;
return this;
}
MyRect buildRect(Point topLeft, int w, int h) {
x1 = topLeft.x;
y1 = topLeft.y;
x2 = (x1 + w);
y2 = (y1 + h);
return this;
}
void printRect() {
System.out.print("MyRect: "= + x1 + ", " + y1);
System.out.println(", " + x2 + ", " + y2 + ">");
}
public static void main (String args[]) {
MyRect rect = new MyRect();

System.out.println("Calling buildRect with coordinates 25,25 50,50:");
rect.buildRect(25, 25, 50, 50);
rect.printRect();
System.out.println("- – - – - – - – - -");

System.out.println("Calling buildRect w/points (10,10), (20,20):");
rect.buildRect(new Point(10,10), new Point(20,20));
rect.printRect();
System.out.println("- – - – - – - – - -");

System.out.print("Calling buildRect w/1 point (10,10),");
System.out.println(" width (50) and height (50)");

rect.buildRect(new Point(10,10), 50, 50);
rect.printRect();
System.out.println("- – - – - – - – - -");
}
}

Die Ausgabe dieses Java-Programms ist wie folgt:

Calling buildRect with coordinates 25,25 50,50:

MyRect: <25, 25, 50, 50>
- – - – - – - – - -
Calling buildRect w/points (10,10), (20,20):
MyRect: <10, 10, 20, 20>
- – - – - – - – - -
Calling buildRect w/1 point (10,10), width (50) and height (50)
MyRect: <10, 10, 60, 60>
- – - – - – - – - -

Wie Sie an diesem Beispiel sehen, funktionieren alle buildRect()-Methoden auf der Grundlage der Argumente, mit denen sie aufgerufen werden. Sie können in Ihren Klassen beliebig viele Versionen einer Methode definieren, um das für die jeweilige Klasse benötigte Verhalten zu implementieren.

Konstruktor-Methoden

Zusätzlich zu den üblichen Methoden können Sie in einer Klassendefinition auch Konstruktor-Methoden definieren.


Eine Konstruktor-Methode oder auch nur Konstruktor ist eine besondere Methodenart, die beim Erstellen eines Objekts bestimmt, wie ein Objekt initialisiert wird.

Im Gegensatz zu den üblichen Methoden können Sie einen Konstruktor nicht direkt aufrufen. Konstruktoren werden von Java automatisch aufgerufen. Das funktioniert so: Wenn Sie new verwenden, um eine neue Klasseninstanz zu erstellen, führt Java drei Aufgaben aus:

Auch wenn für eine Klasse keine speziellen Konstruktoren definiert wurden, erhalten Sie trotzdem ein Objekt, müssen aber seine Instanzvariablen setzen oder andere Methoden aufrufen, die das Objekt zur Initialisierung braucht. Alle Beispiele, die Sie bisher geschrieben haben, verhalten sich so.

Durch Definieren von Konstruktoren in Ihren Klassen können Sie Anfangswerte von Instanzvariablen setzen, Methoden anhand dieser Variablen oder Methoden für andere Objekte aufrufen und die anfänglichen Eigenschaften Ihres Objekts bestimmen. Ferner können Sie Konstruktoren so überladen wie übliche Methoden, um ein Objekt zu erstellen, das die spezifischen Merkmale entsprechend den in new festgelegten Argumenten aufweist.

Basis-Konstruktoren

Konstruktoren sehen wie übliche Methoden aus, unterscheiden sich von diesen aber durch zwei Merkmale:

Listing 7.3 ist ein Beispiel mit einer einfachen Klasse namens Person und einem Konstruktor, der die der Klasse Instanzvariablen anhand der Argumente von new initialisiert. Ferner beinhaltet die Klasse eine Methode für das Objekt, damit es sich selbst vorstellen kann, und eine main()-Methode, um alle Operationen zu testen.

Listing 7.3: Die Person-Klasse

class Person {

String name;
int age;

Person(String n, int a) {
name = n;
age = a;
}
void printPerson() {
System.out.print("Hi, my name is " + name);
System.out.println(". I am " + age + " years old.");
}
public static void main (String args[]) {
Person p;

p = new Person("Laura", 20);
p.printPerson();
System.out.println("- – - – - – - – - -");

p = new Person("Tommy", 3);
p.printPerson();
System.out.println("- – - – - – - – - -");
}
}

Die Ausgabe dieses Beispiels ist wie folgt:

Hi, my name is Laura. I am 20 years old.

- – - – - – - – - -
Hi, my name is Tommy. I am 3 years old.
- – - – - – - – - -

Aufrufen eines anderen Konstruktors

Einige Konstruktoren, die Sie schreiben, können eventuell als übergeordnete Menge eines anderen Konstruktoren in einer Klasse definiert sein. Das heißt, sie könnten das gleiche Verhalten mit ein paar Zusätzen aufweisen. Anstatt ein fast identisches Verhaltensmuster auf mehrere Konstruktor-Methoden einer Klasse zu duplizieren, ist es sinnvoller, lediglich den ersten Konstruktor aus dem Rumpf des zweiten Konstruktors aufzurufen. Java bietet dafür eine spezielle Syntax. Sie verwenden folgende Form, um einen Konstruktor, der in der aktuellen Klasse definiert ist, aufzurufen:

this(arg1, arg2, arg3...);

Die für this() verwendeten Argumente sind selbstverständlich die Argumente des Konstruktors.

Konstruktoren überladen

Wie die üblichen Methoden können auch Konstruktoren überladen werden also verschiedene Anzahl und Typen von Parametern annehmen. Dies gibt Ihnen die Möglichkeit Objekte mit genau den gewünschten Eigenschaften erstellen zu können und Sie sind in der Lage, Eigenschaften aus verschiedenen Eingaben zu berechnen.

Beispielsweise sind die Methoden buildRect(), die Sie heute in der MyRect-Klasse definiert haben, ausgezeichnete Konstruktoren, weil sie die Instanzvariablen eines Objekts auf die entsprechenden Objekte initialisieren. Das bedeutet, daß Sie anstelle der ursprünglich definierten Methode buildRect() (die vier Parameter für die Eckkoordinaten heranzieht) einen Konstruktor erstellen können. In Listing 7.4 wird die neue Klasse MyRect2 aufgeführt, die die gleiche Funktionalität aufweist wie die ursprüngliche Klasse MyRect. Jedoch wurde sie anstelle der Methode buildRect() mit überladenen Konstruktor-Methoden angelegt.

Listing 7.4: Die MyRect2-Klasse (mit Konstruktor-Methoden)

import java.awt.Point;


class MyRect2 {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;

MyRect2(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
MyRect2(Point topLeft, Point bottomRight) {
x1 = topLeft.x;
y1 = topLeft.y;
x2 = bottomRight.x;
y2 = bottomRight.y;
}
MyRect2(Point topLeft, int w, int h) {
x1 = topLeft.x;
y1 = topLeft.y;
x2 = (x1 + w);
y2 = (y1 + h);
}
void printRect() {
System.out.print("MyRect: <" + x1 + ", " + y1);
System.out.println(", " + x2 + ", " + y2 + ">");
}
public static void main (String args[]) {
MyRect2 rect;

System.out.println("Calling MyRect2 with coordinates 25,25 50,50:");
rect = new MyRect2(25, 25, 50,50);
rect.printRect();
System.out.println("- – - – - – - – - -");

System.out.println("Calling buildRect w/points (10,10), (20,20):");
rect= new MyRect2(new Point(10,10), new Point(20,20));
rect.printRect();
System.out.println("- – - – - – - – - -");

System.out.print("Calling buildRect w/1 point (10,10),");
System.out.println(" width (50) and height (50)");
rect = new MyRect2(new Point(10,10), 50, 50);
rect.printRect();
System.out.println("- – - – - – - – - -");
}
}

Nachfolgend sehen Sie die von diesem Beispielprogramm produzierte Ausgabe (sie ist mit der des vorherigen Beispiels identisch, nur der dafür nötige Code wurde geändert):

Calling buildRect with coordinates 25,25 50,50:

MyRect: <25, 25, 50, 50>
- – - – - – - – - -
Calling buildRect w/points (10,10), (20,20):
MyRect: <10, 10, 20, 20>
- – - – - – - – - -
Calling buildRect w/1 point (10,10), width (50) and height (50)
MyRect: <10, 10, 60, 60>
- – - – - – - – - -

Methoden überschreiben

Wenn Sie eine Methode in einem Objekt aufrufen, sucht Java nach der Methodendefinition in der Klasse dieses Objekts. Falls es keine übereinstimmende Signatur findet, wird der Methodenaufruf in der Klassenhierarchie nach oben weitergereicht, bis eine passende Methodendefinition gefunden wird. Durch die in Java implementierte Methodenvererbung können Sie Methoden wiederholt in Subklassen definieren und verwenden, ohne den Code an sich duplizieren zu müssen.

Zuweilen soll ein Objekt aber auf die gleichen Methoden reagieren, jedoch beim Aufrufen der jeweiligen Methode ein anderes Verhalten aufweisen. In diesem Fall können Sie die Methode überschreiben. Durch überschreiben von Methoden definieren Sie eine Methode in einer Subklasse, die die gleiche Signatur hat wie eine Methode in einer Superklasse. Dann wird zum Zeitpunkt des Aufrufs nicht die Methode in der Superklasse, sondern die in der Subklasse ermittelt und ausgeführt.

Erstellen von Methoden, die andere verbergen

Um eine Methode zu überschreiben, erstellen Sie eine Methode in der Subklasse, die die gleiche Signatur (Name, Rückgabetyp und Parameterliste) hat wie eine Methode, die in einer Superklasse der betreffenden Klasse definiert wurde. Da Java die erste Methodendefinition ausführt, die es findet und die mit der Signatur übereinstimmt, wird die ursprüngliche Methodendefinition dadurch »verborgen«. Wir betrachten im folgenden ein einfaches Beispiel. Listing 7.5 zeigt eine einfache Klasse mit der Methode printMe(), die den Namen der Klasse und die Werte ihrer Instanzvariablen ausgibt.

Listing 7.5: Die PrintClass-Klasse

class PrintClass {

int x = 0;
int y = 1;

void printMe() {
System.out.println("X is " + x + ", Y is " + y);
System.out.println("I am an instance of the class " +
this.getClass().getName());
}
}

Listing 7.6 umfaßt eine Klasse namens PrintSubClass, die eine Subklasse von PrintClass (extends) ist. Der einzige Unterschied zwischen PrintClass und PrintSubClass ist, daß letztere die Instanzvariable z hat.

Listing 7.6: Die PrintSubClass-Klasse

class PrintSubClass extends PrintClass {

int z = 3;

public static void main (String args[]) {
PrintSubClass obj = new PrintSubClass();
obj.printMe();
}
}

Im folgenden die Ausgabe von PrintSubClass:

X is 0, Y is 1

I am an instance of the class PrintSubClass

In der Methode main() von PrintSubClass erstellen Sie das Objekt PrintSubClass und rufen die Methode printMe() auf. Beachten Sie, daß PrintSubClass diese Methode nicht definiert, deshalb sucht Java in allen Superklassen von PrintSubClass danach und findet sie in diesem Fall in PrintClass. Leider wird die Instanzvariable z nicht ausgegeben, weil printMe() immer noch in PrintClass definiert ist.

Wir erstellen nun eine dritte Klasse. PrintSubClass2 ist fast mit PrintSubClass identisch, jedoch wird die Methode printMe() überschrieben, um die Variable z einzubinden. Listing 7.7 zeigt diese Klasse.

Listing 7.7: Die PrintSubClass2-Klasse

class PrintSubClass2 extends PrintClass {

int z = 3;

void printMe() {
System.out.println("x is " + x + ", y is " + y +
", z is " + z);
System.out.println("I am an instance of the class " +
this.getClass().getName());
}
public static void main (String args[]) {
PrintSubClass2 obj = new PrintSubClass2();
obj.printMe();
}
}

Wenn Sie diese Klasse jetzt benutzen und die Methode printMe() aufrufen, wird diesmal die Version von printMe(), die Sie für diese Klasse definiert haben, nicht diejenige, die sich in der Superklasse PrintClass befindet, aufgerufen.

Das sehen Sie an folgender Ausgabe:

x is 0, y is 1, z is 3

I am an instance of the class PrintSubClass2

Aufrufen der Originalmethode

Normalerweise gibt es zwei Gründe dafür, warum man eine Methode, die in einer Superklasse bereits implementiert ist, überschreiben will:

Den ersten Grund haben Sie bereits kennengelernt. Durch Überladen einer Methode und Schreiben einer neuen Definition für diese Methode haben Sie die ursprüngliche Definition der Methode verborgen. Zuweilen will man aber auch die ursprüngliche Definition nicht ganz ersetzen, sondern vielmehr um zusätzliche Eigenschaften erweitern. Das ist besonders nützlich, wenn es darauf hinausläuft Verhaltensweisen der Originalmethode in der neuen Definition zu duplizieren. Sie können die Originalmethode im Rumpf der überschriebenen Methode aufrufen und alles hinzufügen, was Sie benötigen.

Um die Originalmethode innerhalb einer Methodendefinition aufzurufen, benutzen Sie das Schlüsselwort super, um den Methodenaufruf in der Hierarchie nach oben weiterzugeben:

void myMethod (String a, String b) {

// Hier irgendwas ausführen
super.myMethod(a, b);
// Eventuell weitere Anweisungen
}

Wie this ist auch das Schlüsselwort super ein Platzhalter – in diesem Fall für die Superklasse dieser Klasse. Sie können es immer verwenden, wenn Sie nicht auf die aktuelle Klasse, sondern die Superklasse verweisen wollen.

In Listing 7.8 sehen Sie die printMe()-Methoden aus dem vorherigen Beispiel.

Listing 7.8: Die printMe-Methoden

// aus PrintClass

void printMe() {
System.out.println("X is " + x + ", Y is " + y);
System.out.println("I am an instance of the class" +
this.getClass().getName());
}

// aus PrintSubClass2
void printMe() {
System.out.println("X is " + x + ", Y is " + y + ", Z is " + z);
System.out.println("I am an instance of the class " +
this.getClass().getName());
}

Anstatt den Großteil des Verhaltens von der Methode der Superklasse in die Subklasse zu duplizieren, können Sie die Methode der Superklasse so umstellen, daß zusätzliche Eigenschaften mühelos hinzugefügt werden können:

// von PrintClass

void printMe() {
System.out.println("I am an instance of the class" +
this.getClass().getName());
System.out.println("X is " + x);
System.out.println("Y is " + y);
}

Beim Überschreiben von printMe können Sie dann in der Superklasse die Originalmethode aufrufen und alles hinzufügen, was Sie benötigen:

// von PrintSubClass2

void printMe() {
super.printMe();
System.out.println("Z is " + z);
}

Die Ausgabe des Aufrufs von printMe() in einer Instanz der Superklasse sieht so aus:

I am an instance of the class PrintSubClass2

X is 0
Y is 1
Z is 3

Konstruktoren überschreiben

Konstruktoren können technisch nicht überschrieben werden. Da sie immer den gleichen Namen haben wie die aktuelle Klasse, werden Konstruktoren nicht vererbt, sondern immer neu erstellt. Das ist in den meisten Fällen sinnvoll, denn wenn ein Konstruktor Ihrer Klasse aufgerufen wird, wird gleichzeitig auch der Konstruktor mit der gleichen Signatur aller Superklassen aktiviert, so daß eventuell alle Teile einer Klasse initialisiert werden.

Andererseits möchten Sie eventuell beim Definieren von Konstruktoren für eine Klasse einiges ändern, z.B. wie ein Objekt initialisiert wird. Eventuell soll es nicht durch Initialisieren der Informationen, die Ihre Klasse zusätzlich einbringt, sondern durch Änderung der bereits vorhandenen Informationen initialisiert werden. Sie erreichen das, indem Sie die Konstruktoren Ihrer Superklasse explizit aufrufen.

Um eine übliche Methode in einer Superklasse aufzurufen, benutzen Sie super.methodname(arguments). Da Sie bei Konstruktoren keinen Methodennamen aufrufen müssen, wenden Sie hier eine andere Form an:

super(arg1, arg2, ...);

Ebenso wie bei der Verwendung von this(...) bewirkt super(...) in Konstruktor-Methoden den Aufruf der Konstruktor-Methode für die unmittelbare Superklasse (die ihrerseits den Konstruktor ihrer Superklasse aufrufen kann usw.).

Das Beispiel in Listing 7.9 zeigt die Klasse NamedPoint, die sich auf die Klasse Point aus dem awt-Paket von Java ableitet. Die Point-Klasse hat nur einen Konstruktor, der anhand der Argumente x und y ein Point-Objekt ausgibt. NamedPoint hat eine zusätzliche Instanzvariable (eine Zeichenkette für den Namen) und definiert einen Konstruktor, um x, y und den Namen zu initialisieren.

Listing 7.9: Die NamedPoint-Klasse

1:   import java.awt.Point;


2: class NamedPoint extends Point {
3: String name;
4:
5: NamedPoint(int x, int y, String name) {
6: super(x,y);
7: this.name = name;
8: }
9: }

Der hier für NamedPoint (Zeilen 6 bis 8) definierte Konstruktor ruft die Konstruktor-Methode von Point auf, um die Instanzvariablen (x und y) von Point zu initialisieren. Obwohl Sie x und y ebenso gut selbst initialisieren könnten, wissen Sie eventuell nicht, ob Point noch andere Operationen ausführt, um sich zu initialisieren. Deshalb ist es immer ratsam, Konstruktor nach oben in der Hierarchie weiterzugeben, um sicherzustellen, daß alles richtig gesetzt wird.

Finalizer-Methoden

Finalizer-Methoden sind in gewissem Sinn das Gegenstück zu Constructor-Methoden. Während eine Constructor-Methode benutzt wird, um ein Objekt zu initialisieren, werden Finalizer-Methoden aufgerufen, kurz bevor das Objekt im Papierkorb landet und sein Speicher zurückgefordert wird.

Um eine Finalizer-Methode zu erstellen, tragen Sie eine Methode mit der folgenden Unterschrift in Ihre Klassendefinition ein:

void finalize() throws Throwable{

super.finalize
}


Der Teil throws Throwable dieser Methodendefinition bezieht sich auf die Fehler, die nach dem Aufruf dieser Methode eventuell auftreten. Fehler werden in Java Exceptions genannt. Im Kapitel des Tages 17, »Exceptions«, lernen Sie mehr darüber. Vorrerst reicht es, daß Sie diese Schlüsselwörter in die Methodendefinition aufnehmen.

Im Körper dieser finalize()-Methode können Sie alle möglichen »Aufräumprozeduren« einbinden, die das Objekt ausführen soll. Sie können auf super.finalize aufrufen, um die Aufräumarbeiten, wenn nötig, an die Superklasse Ihrer Klasse zu deligieren. (Dieses ist im allgemeinen recht sinnvoll, um es allen Beteiligten zu ermöglichen das Objekt zu bearbeiten, wenn dies notwendig sein sollte.)

Sie können die Methode finalize() jederzeit auch selbst aufrufen. Es handelt sich um eine einfache Methode wie alle anderen. Allerdings wird durch den Aufruf von finalize() nicht veranlaßt, daß der Garbage Collector für dieses Objekt aktiv wird. Nur durch Entfernen aller Referenzen auf das Objekt wird das Objekt zum Löschen markiert.

Finalizer-Methoden eignen sich am besten zur Optimierung des Entfernens von Objekten, z.B. durch Löschen aller Referenzen auf andere Objekte, durch das Freigeben aller externen Ressourcen, die verwendet wurden (z.B. externe Dateien), oder für andere Verhaltensweisen, die das Entfernen eines Objekts vereinfachen. In den meisten Fällen benötigen Sie finalize() überhaupt nicht. Mehr zum Thema Garbage Collection und finalize() finden Sie im Kapitel des Tages 21.

Zusammenfassung

Heute haben Sie verschiedene Techniken zum Benutzen, Wiederverwenden, Definieren und Neudefinieren von Methoden kennengelernt. Sie haben gelernt, wie man durch Überladen eines Methodennamens die gleiche Methode mit einem anderen Verhalten auf der Grundlage der Argumente, durch die sie aufgerufen wird, definiert. Sie haben viel über Konstruktor-Methoden gelernt, die benutzt werden, um ein neues Objekt beim Erstellen zu initialisieren. Sie haben mehr über Methodenvererbung erfahren und gelernt, wie Methoden in Subklassen einer Klasse durch überschreiben definiert werden können. Außerdem haben Sie gelernt, daß Sie mit Finalizer-Methoden Ihr Programm »aufräumen« können.

Herzlichen Glückwunsch! Sie haben Ihre erste Woche von Java in 21 Tagen beendet. In der nächsten Woche werden Sie alles, was Sie diese Woche gelernt haben, anwenden, um Java-Applets zu schreiben und mit anspruchsvolleren Konzepten zu arbeiten. Sie werden Java-Programme zusammenstellen und mit der Java-Klassenbibliothek arbeiten.

Fragen und Antworten

F Ich habe zwei Methoden mit folgenden Signaturen geschrieben:

int total(int arg1, int arg2, int arg3) {   }

float total(int arg1, int arg2, int arg3) {...}

A Das Überladen von Methoden funktioniert in Java nur, wenn sich die Parameterlisten unterscheiden, entweder in der Zahl oder im Typ der Argumente. Die Rückgabetypen sind beim Überladen von Methoden nicht relevant. Bei zwei Methoden mit genau der gleichen Parameterliste kann Java nicht wissen, welche aufzurufen ist.

F Kann ich auf Methoden, die bereits überschrieben wurden, überladen (d.h. kann ich Methoden erstellen, die den gleichen Namen wie eine geerbte Methode, jedoch eine andere Parameterliste haben)?

A Sicher! So lange die Parameterliste unterschiedlich ist, spielt es keine Rolle, ob Sie einen neuen Methodennamen oder einen, den Sie aus einer Superklasse geerbt haben, definieren.


(c) 1997 SAMS
Ein Imprint des Markt&Technik Buch- und Software- Verlag GmbH
Elektronische Fassung des Titels: Java in 21 Tagen, ISBN: 3-8272-2009-2

Previous Page Page Top TOC Index Next Page See Page