vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 1

Tag 6


Java: Eine Klassesprache

Wenn Sie von einer anderen Programmiersprache zu Java wechseln, dann werden Sie eventuell mit den Klassen etwas zu kämpfen haben. Der Begriff Klasse scheint zum einen synonym mit dem Begriff Programm zu sein, zum anderen könnten Sie aber unsicher sein, was die Beziehung zwischen den Begriffen anbelangt.

In Java besteht ein Programm aus einer Hauptklasse und beliebig vielen Hilfsklassen, die zur Unterstützung der Hauptklasse benötigt werden. Diese Hilfsklassen beinhalten beliebige Klassen aus der Java-Klassenbibliothek, die Sie eventuell brauchen (wie z.B. String, Math etc.).

Heute werden Sie in bezug darauf, was Sie über dieses Thema wissen, den Gipfel der Klassen erklimmen. Im einzelnen werden Sie über folgendes lesen:

Definieren von Klassen

Da Sie in jedem der vorangegangenen Kapitel bereits Klassen erstellt haben, sollten Sie mit den Grundlagen der Definition von Klassen bereits vertraut sein. Um eine Klasse zu definieren, verwenden Sie das Schlüsselwort class und den Namen der Klasse:

class Ticker {
    // Rumpf der Klasse
}

Standardmäßig werden Klassen von der Klasse Object abgeleitet. Diese ist die Superklasse aller Klassen in der Klassenhierarchie von Java.

Wenn Ihre Klasse eine Subklasse einer anderen Klasse ist, dann wird über das Schlüsselwort extends die Superklasse der neuen Klasse angegeben. Sehen Sie sich hierzu die folgende Subklasse der Klasse Ticker an:

class SportsTicker extends Ticker {
    // Rumpf der Klasse
}

Erstellen von Instanz- und Klassenvariablen

Wenn Sie eine Klasse von einer Superklasse ableiten, dann werden Sie Verhaltensweisen und Eigenschaften hinzufügen wollen, die die neue Klasse von der Klasse, von der sie abgeleitet wurde, unterscheidet.

Diese Verhaltensweisen und Eigenschaften definieren Sie über die Variablen und Methoden der neuen Klasse. In diesem Abschnitt arbeiten Sie mit drei verschiedenen Variablentypen: Klassenvariablen, Instanzvariablen und lokalen Variablen. Der darauffolgende Abschnitt behandelt Methoden.

Definieren von Instanzvariablen

Am 3. Tag haben Sie gelernt, wie lokale Variablen, d.h. Variablen in Methodendefinitionen, deklariert und initialisiert werden. Instanzvariablen werden zum Glück auf genau die gleiche Weise deklariert und definiert. Der wesentliche Unterschied ist ihre Position in der Klassendefinition. Instanzvariablen gelten als solche, wenn sie außerhalb einer Methodendefinition deklariert werden. Üblicherweise werden die meisten Instanzvariablen direkt nach der ersten Zeile der Klassendefinition definiert. Listing 6.1 zeigt als Beispiel eine einfache Definition für eine Klasse namens Jabberwock, die von der Klasse Reptile abgeleitet wird. Diese Klassendefinition enthält vier Instanzvariablen:

Listing 6.1: Die komplette Quelltext von Jabberwock.java

 1: class Jabberwock extends Reptile {
 2:
 3:     String color;
 4:     String sex;
 5:     boolean hungry;
 6:     int age;
 7: }

Diese Klassendefinition umfaßt vier Variablen. Da diese Variablen nicht innerhalb einer Methode definiert sind, handelt es sich um Instanzvariablen. Die folgenden Variablen befinden sich in der Klasse

Konstanten

Variablen sind sehr nützlich, wenn Sie Informationen speichern wollen, die man zur Laufzeit eines Programms ändern können soll. Soll sich der Wert allerdings zur Laufzeit eines Programms nicht ändern, können Sie einen speziellen Variablentyp verwenden: die Konstanten.


Eine Konstante ist eine Variable, deren Wert sich nie ändert (was im Zusammenhang mit dem Wort »Variable« seltsam erscheinen mag).

Konstanten sind sehr nützlich für die Definition von Werten, die allen Methoden eines Objekts zur Verfügung stehen sollen. Mit anderen Worten kann man mit Konstanten unveränderlichen, objektweit genutzten Werten einen aussagekräftigen Namen geben. In Java können Sie mit allen Variablenarten Konstanten erzeugen: Instanzvariablen, Klassenvariablen und lokalen Variablen.


Konstante lokale Variablen waren in Java 1.02 nicht möglich, wurden aber mit Java 1.1 in der Sprache eingeführt. Dies wird wichtig, wenn Sie ein Applet erstellen, das zu Java 1.02 völlig kompatibel sein soll. Über dieses Thema lernen Sie in Woche 2 mehr.

Um eine Konstante zu deklarieren, benutzen Sie das Schlüsselwort final vor der Variablendeklaration und geben für diese Variable einen Anfangswert ein:

final float pi = 3.141592;
final boolean debug = false;
final int numberOfJenny = 8675309;

Konstanten sind auch nützlich zur Benennung verschiedener Zustände eines Objekts, das dann auf diese Zustände getestet werden kann. Nehmen wir beispielsweise an, Sie brauchen einen Schriftzug, der links, rechts oder zentriert ausgerichtet werden kann. Diese Werte können Sie als konstante Ganzzahlen definieren:

final int LEFT = 0;
final int RIGHT = 1;
final int CENTER = 2;

Die Variable alignment (Ausrichtung) wird dann ebenfalls als int deklariert, um darin die aktuelle Ausrichtung zu speichern:

int alignment;

Danach können Sie im Körper einer Methodendefinition eine der Ausrichtungen setzen:

this.alignment = CENTER;

oder auf eine bestimmte Ausrichtung prüfen:

switch (this.alignment) {
case LEFT: // Ausrichtung Links verarbeiten
...
break
case RIGHT: // Ausrichtung Rechts verarbeiten
...
break
case CENTER: // Ausrichtung Zentriert verarbeiten
...
break
}

Konstanten machen es oft leichter, ein Programm zu verstehen. Um diesen Punkt zu verdeutlichen, sollten Sie sich einmal die beiden folgenden Anweisungen ansehen und vergleichen, welche mehr über ihre Funktion aussagt:

this.alignment = CENTER;
this.alignment = 2;

Klassenvariablen

Wie Sie in den vorherigen Lektionen gelernt haben, sind Klassenvariablen global innerhalb einer bestimmten Klasse und für alle Instanzen der jeweiligen Klasse gültig.

Klassenvariablen eignen sich gut zur Kommunikation zwischen verschiedenen Objekten der gleichen Klasse oder zum Verfolgen globaler Zustände in bestimmten Objekten.

Um eine Klassenvariable zu deklarieren, benutzen Sie das Schlüsselwort static in der Klassendeklaration:

static int sum;
static final int maxObjects = 10;

Erstellen von Methoden

Am 4. Tag haben Sie gelernt, daß Methoden das Verhalten eines Objekts bestimmen, d.h. was passiert, wenn das Objekt erstellt wird, und welche Operationen es während seiner Lebenszeit ausführen kann.

In dieser Lektion erhalten Sie eine Grundeinführung in die Methodendefinition und wie Methoden funktionieren. Morgen steigen Sie in mehr Einzelheiten über die Dinge ein, die Sie mit Methoden anstellen können.

Definieren von Methoden

Die Definition von Methoden besteht aus folgenden vier Teilen:

Die ersten drei Teile bilden die sogenannte Signatur der Methode.


Um die heutige Lektion nicht unnötig zu verkomplizieren, habe ich zwei optionale Teile der Definition einer Methode weggelassen: Modifier, z.B. public oder private, und das Schlüsselwort throws, das die Ausnahmen bezeichnet, die eine Methode auswerfen kann. Sie lernen diese Teile der Methodendefinition in Woche 3.

In anderen Sprachen genügt der Name der Methode (bzw. der Funktion, Subroutine oder Prozedur), um sie von anderen im Programm vorhandenen Methoden zu unterscheiden.

In Java sind mehrere Methoden mit dem gleichen Namen möglich, jedoch mit einem anderen Rückgabetyp und einer anderen Argumentenliste. Dieses sogenannte Überladen von Methoden lernen Sie morgen kennen.

Eine einfache Methodendefinition sieht in Java so aus:

Rückgabetyp Methodenname (Typ1 Arg1, Typ2 Arg2, Typ3 Arg3...) {
//Rumpf der Methode
}

Rückgabetyp ist der primitive Typ oder die Klasse des Wertes, den die Methode zurückgibt. Das kann einer der primitiven Typen, ein Klassenname oder void sein, falls die Methode keinen Wert zurückgibt.

Gibt diese Methode ein Array-Objekt zurück, können die Array-Klammern entweder nach dem Rückgabetyp oder nach der Parameterliste eingegeben werden. Da die erste Art wesentlich übersichtlicher ist, wird sie in den heutigen Beispielen (und im gesamten Buch) angewandt:

int[] makeRange (int lower, int upper) {...}

Bei der Parameterliste einer Methode handelt es sich um verschiedene Variablendeklarationen, die durch Kommas getrennt werden und zwischen Klammern stehen. Diese Parameter bilden lokale Variablen im Körper der Methode, deren Werte Objekte oder Werte von Primitivtypen sind, die beim Aufrufen der Methode übergeben werden.

Im Methodenkörper können Anweisungen, Ausdrücke, Methodenaufrufe anderer Objekte, Bedingungen, Schleifen usw. stehen - alles, was Sie in den bisherigen Lektionen gelernt haben.

Hat Ihre Methode einen Rückgabetyp (d.h. der Rückgabetyp wurde nicht mit void deklariert), muß irgendwo im Methodenkörper ein Wert zurückgegeben werden. Sie verwenden hierfür das Schlüsselwort return.

Listing 6.2 zeigt ein Beispiel einer Klasse, die die Methode makeRange() definiert. makeRange() nimmt zwei Ganzzahlen entgegen - eine obere und eine untere Grenze - und erstellt ein Array, das alle zwischen diesen Grenzen liegenden Ganzzahlen (einschließlich der Grenzwerte) enthält.

Listing 6.2: Der gesamte Quelltext von RangeClass.java

 1: class RangeClass {
 2:     int[] makeRange(int lower, int upper) {
 3:         int arr[] = new int[ (upper - lower) + 1 ];
 4:
 5:         for (int i = 0; i < arr.length; i++) {
 6:             arr[i] = lower++;
 7:         }
 8:         return arr;
 9:     }
10:
11:     public static void main(String arguments[]) {
12:         int theArray[];
13:         RangeClass theRange = new RangeClass();
14:
15:         theArray = theRange.makeRange(1, 10);
16:         System.out.print("The array: [ ");
17:         for (int i = 0; i < theArray.length; i++) {
18:             System.out.print(theArray[i] + " ");
19:         }
20:         System.out.println("]");
21:     }
22:
23: }

Die Ausgabe dieses Programms sieht so aus:

The array: [ 1 2 3 4 5 6 7 8 9 10 ]

Die Methode main() in dieser Klasse testet die Methode makeRange() durch Anlegen eines Bereichs, wobei die obere und untere Grenze des Bereichs 1 bzw. 10 ist (siehe Zeile 6). Dann wird eine for-Schleife benutzt, um die Werte des neuen Arrays auszugeben.

Das this-Schlüsselwort

Sicherlich möchten Sie im Körper einer Methodendefinition einmal auf das aktuelle Objekt verweisen, beispielsweise, um auf Instanzvariablen des Objekts zu verweisen oder das aktuelle Objekt als Argument an eine andere Methode weiterzugeben.

Um auf das aktuelle Objekt in diesen Fällen Bezug zu nehmen, können Sie das Schlüsselwort this verwenden.

Sie können es an jeder beliebigen Stelle eingeben, an der das Objekt erscheinen kann, z.B. in einer Punkt-Notation, um auf Instanzvariablen des Objekts zu verweisen, oder als Argument für eine Methode, als Rückgabewert der aktuellen Methode usw. Hier ein paar Beispiele für die Verwendung des Schlüsselwortes this:

t = this.x; // Instanzvariable x für dieses Objekt
this.resetData(this);// Aufruf der in dieser Klasse definierten 
// resetData-Methode, an die das aktuelle Objekt 
// übergeben wird
return this; // Rückgabe des aktuellen Objekts

In vielen Fällen können Sie eventuell das Schlüsselwort this weglassen. Sie können sich auf Instanzvariablen und Methodenaufrufe, die in der aktuellen Klasse definiert sind, einfach auch über den Namen beziehen. this ist in diesen Referenzen implizit vorhanden. Die ersten zwei Beispiele könnten somit auch wie folgt geschrieben werden:

t = x;// Instanzvariable x für dieses Objekt
resetData(this); // Aufruf der in dieser Klasse definierten 
// resetData-Methode


Ob Sie das Schlüsselwort this für Instanzvariablen weglassen können, hängt davon ab, ob es Variablen mit dem gleichen Namen in dem aktuellen Gültigkeitsbereich gibt. Einzelheiten hierzu finden Sie im nächsten Abschnitt.

Da this eine Referenz auf die aktuelle Instanz einer Klasse ist, ist es sinnvoll, das Schlüsselwort nur innerhalb der Definition einer Instanzmethode zu verwenden. Klassenmethoden, d.h. Methoden, die mit dem Schlüsselwort static deklariert sind, können this nicht verwenden.

Gültigkeitsbereich von Variablen und Methodendefinitionen

Was Sie über eine Variable unbedingt wissen müssen, um sie verwenden zu können, ist deren Gültigkeitsbereich.


Der Gültigkeitsbereich einer Variablen legt fest, wo eine Variable verwendet werden kann.

Wenn Sie eine Variable deklarieren, hat diese immer einen eingeschränkten Gültigkeitsbereich. Der Gültigkeitsbereich einer Variablen legt fest, wo diese Variable verwendet werden kann. Variablen mit einem lokalem Gültigkeitsbereich können z.B. nur in dem Block verwendet werden, in dem sie definiert wurden. Der Gültigkeitsbereich von Instanzvariablen bezieht die gesamte Klasse ein, so daß diese von Methoden innerhalb der Klasse verwendet werden können.

Wenn Sie sich auf eine Variable in einer Methodendefinition beziehen, sucht Java zuerst eine Definition dieser Variablen im aktuellen Gültigkeitsbereich (der ein Block sein kann), dann durchsucht es den äußeren Gültigkeitsbereich bis zur Definition der aktuellen Methode. Ist die gesuchte Variable keine lokale Variable, sucht Java nach einer Definition dieser Variablen als Instanzvariable in der aktuellen Klasse und zum Schluß in jeder Superklasse.

Aufgrund der Art, in der Java nach dem Bereich einer bestimmten Variablen sucht, können Sie eine Variable in einem niedrigeren Bereich erstellen, so daß eine Definition der gleichen Variablen den Originalwert der Variablen »verbirgt«. Das kann aber zu Fehlern führen, die schwer zu finden sind.

Betrachten Sie z.B. dieses kleine Java-Programm:

Listing 6.3: Der gesamte Quelltext von ScopeTest.java

 1: class ScopeTest {
 2:     int test = 10;
 3:
 4:     void printTest () {
 5:         int test = 20;
 6:         System.out.println("test = " + test);
 7:     }
 8:
 9:     public static void main(String arguments[]) {
10:         ScopeTest st = new ScopeTest();
11:         st.printTest();
12:     }
13: }

Das Programm erzeugt die folgende Ausgabe:

test = 20

Diese Klasse hat zwei Variablen mit dem gleichen Namen und der gleichen Definition: Die erste, eine Instanzvariable, hat den Namen test und ist auf den Wert 10 initialisiert. Die zweite ist eine lokale Variable mit dem gleichen Namen, jedoch dem Wert 20. Die lokale Variable in test in der Methode printTest() verbirgt die Instanzvariable test. Die Methode printTest() innerhalb der von main() gibt aus diesem Grund test = 20 aus.

Sie können dies Problem umgehen, indem Sie this.test verwenden, um sich spezifisch auf die Instanzvariable zu beziehen, oder nur test, um sich auf die lokale Variable zu beziehen.

Der Konflikt wird also vermieden, indem Sie sich auf die Variable über den Gültigkeitsbereich des Objekts beziehen.

Eine heimtückischere Situation tritt ein, wenn Sie eine Variable in einer Subklasse, die bereits in einer Superklasse vorkommt, neu definieren. Das kann sehr komplizierte Fehler im Code verursachen. Beispielsweise werden Methoden aufgerufen, die den Wert einer Instanzvariablen ändern sollen, nun jedoch die falsche ändern. Ein anderer Fehler kann auftreten, wenn ein Objekt von einer Klasse in eine andere konvertiert wird. Eventuell wird dabei der Wert einer Instanzvariablen auf geheimnisvolle Weise geändert (da sie den Wert von der Superklasse, nicht von der beabsichtigten Klasse entnommen hat).

Die beste Art, dieses Verhalten zu vermeiden, ist, sicherzustellen, daß Sie beim Definieren von Variablen in einer Subklasse die Variablen in allen Superklassen dieser Klasse kennen und nichts duplizieren, was sich bereits dort befindet.

Argumente an Methoden übergeben

Wenn Sie eine Methode mit Objektparametern aufrufen, werden die Variablen, die Sie an den Körper der Methode übergeben, als Referenz übergeben. Das bedeutet, daß sich alles, was Sie mit diesen Objekten in der Methode anstellen, gleichermaßen auf die Originalobjekte auswirkt. Dies beinhaltet Arrays und alle Objekte, die in Arrays enthalten sind. Wenn Sie ein Array an eine Methode übergeben und dann seinen Inhalt ändern, wirkt sich das auch auf das Original-Array aus. (Beachten Sie, daß die Primitivtypen als Wert weitergegeben werden.)

Listing 6.4: Die PassByReference-Klasse

 1: class PassByReference {
 2:     int onetoZero(int arg[]) {
 3:         int count = 0;
 4:
 5:         for (int i = 0; i < arg.length; i++) {
 6:             if (arg[i] == 1) {
 7:                 count++;
 8:                 arg[i] = 0;
 9:             }
10:         }
11:         return count;
12:     }
13:     public static void main(String arguments[]) {
14:         int arr[] = { 1, 3, 4, 5, 1, 1, 7 };
15:         PassByReference test = new PassByReference();
16:         int numOnes;
17:
18:         System.out.print("Values of the array: [ ");
19:         for (int i = 0; i < arr.length; i++) {
20:             System.out.print(arr[i] + " ");
21:         }
22:         System.out.println("]");
23:
24:         numOnes = test.onetoZero(arr);
25:         System.out.println("Number of Ones = " + numOnes);
26:         System.out.print("New values of the array: [ ");
27:         for (int i = 0; i < arr.length; i++) {
28:             System.out.print(arr[i] + " ");
29:         }
30:         System.out.println("]");
31:     }
32: }

Das Programm erzeugt die folgende Ausgabe:

Values of the array: [ 1 3 4 5 1 1 7 ]
Number of Ones = 3
New values of the array: [ 0 3 4 5 0 0 7 ]

Beachten Sie bitte die Definition der Methode onetoZero() in den Zeilen 2 bis 12, die als Argument lediglich ein Array erwartet. Die Methode onetoZero() bewirkt zwei Dinge:

Die main()-Methode in der Klasse PassByReference testet die Methode onetoZero(). Wir wollen nun die Methode main() Zeile für Zeile durchgehen, um zu sehen, was da passiert.

Klassenmethoden

Die Beziehung zwischen Klassen- und Instanzvariablen läßt sich direkt mit der zwischen Klassen- und Instanzmethoden vergleichen.

Klassenmethoden sind für alle Instanzen der Klasse selbst verfügbar und können anderen Klassen zur Verfügung gestellt werden. Außerdem ist bei Klassenmethoden im Gegensatz zu Instanzmethoden keine Instanz der Klasse nötig, damit deren Klassenmethoden aufgerufen werden können.

Die Java-Klassenbibliothek beinhaltet z.B. eine Klasse mit dem Namen Math. Die Klasse Math definiert eine Reihe von mathematischen Operationen, die Sie in jedem beliebigen Programm bzw. auf jeden der Zahlentypen verwenden können, wie das im folgenden der Fall ist:

float root = Math.sqrt(453.0);
System.out.print("The larger of x und y is" + Math.max(x,y));

Um Klassenmethoden zu definieren, benutzen Sie das Schlüsselwort static vor der Methodendefinition, wie beim Erstellen von Klassenvariablen. Die Klassenmethode max könnte beispielsweise folgende Signatur haben:

static int max (int arg1, int arg2) { ... }

Auf ähnliche Weise liefert Java Wrapper-Klassen oder auch Hüllklassen für alle Grundtypen, z.B. die Klassen Integer, Float und Boolean. Anhand der in diesen Klassen definierten Klassenmethoden können Sie Objekte in Grundtypen und umgekehrt konvertieren.

Die Klassenmethode parseInt() z.B. in der Klasse Integer arbeitet mit Strings zusammen. Ein String wird als Argument an die Methode geschickt. Dieser String wird zur Ermittlung eines Rückgabewertes verwendet, der als int zurückgegeben wird:

int count = Integer.parseInt("42") // Ergibt 42

In der obigen Anweisung wird der String "42" von der Methode parseInt() als Integer mit dem Wert 42 zurückgegeben. Dieser Wert wird in der Variablen count gespeichert.

Befindet sich das Schlüsselwort static nicht vor dem Namen einer Methode, so wird diese zur Instanzmethode. Instanzmethoden beziehen sich immer auf ein konkretes Objekt anstatt auf die Klasse selbst. Am 2. Tag haben Sie eine Instanzmethode erstellt, die feedJabberwock() hieß und ein einzelnes Jabberwock-Objekt gefüttert hat.

Die meisten Methoden, die auf ein bestimmtes Objekt anwendbar sind oder sich auf ein Objekt auswirken, sollten als Instanzmethoden definiert werden. Methoden, die eine gewisse allgemeine Nützlichkeit bieten und sich nicht direkt auf eine Instanz einer Klasse auswirken, werden bevorzugt als Klassenmethoden deklariert.

Entwickeln von Java-Applikationen

Sie haben gelernt, Klassen, Objekte, Klassen- und Instanzvariablen sowie Methoden zu erstellen. Alles, was Sie noch lernen müssen, um etwas Lauffähiges zu produzieren, ist das Schreiben einer Java-Applikation.

Anwendungen, um Ihr Gedächtnis aufzufrischen, sind Java-Programme, die eigenständig laufen. Applikationen unterscheiden sich von Applets, für die HotJava oder ein Java-fähiger Browser benötigt wird, um sie ausführen zu können. Ein Großteil dessen, was Sie in den bisherigen Lektionen durchgearbeitet haben, waren Java-Applikationen. Nächste Woche tauchen Sie in die Entwicklung von Applets ein. (Um Applets schreiben zu können, ist mehr Basiswissen erforderlich, denn Applets müssen auch mit dem Browser interagieren und das Grafiksystem zum Zeichnen und Aktualisieren des Ausgegebenen verwenden. Das alles lernen Sie nächste Woche.)

Eine Java-Applikation besteht aus einer oder mehreren Klassen und kann beliebig umfangreich sein. HotJava ist ein Beispiel einer Java-Applikation. Obwohl die Java-Applikationen, die Sie bis jetzt erzeugt haben, nichts anderes tun, als Zeichen auf dem Bildschirm oder in ein Fenster auszugeben, können Sie auch Applikationen erstellen, die Fenster, Grafik und Elemente der Benutzerschnittstelle verwenden, wie das auch bei Applets der Fall ist.

Das einzige, was Sie brauchen, um eine Java-Applikation auszuführen, ist eine Klasse, die als »Sprungbrett« für den Rest Ihres Java-Programms dient. Ist Ihr Programm eher klein, kann eine Klasse unter Umständen genügen.

Die Klasse, die das Sprungbrett für Ihr Java-Programm bildet, muß nur eines haben: eine main()-Methode. Wenn Sie Ihre kompilierte Java-Klasse (mit dem Java-Interpreter) ausführen, ist die Methode main() das erste, was aufgerufen wird. Das dürfte für Sie keine Überraschung mehr sein, da Sie ja in den bisherigen Lektionen mehrmals Java-Applikationen mit einer main()-Methode erstellt haben.

Die Signatur der Methode main() sieht immer so aus:

public static void main (String arg[]) { 
    //Rumpf der Methode
}

Die einzelnen Teile von main() haben folgende Bedeutung:

In den Rumpf der main()-Methode kann jeder beliebige Code eingefügt werden, der benötigt wird, um eine Anwendung zu starten: Variablen oder Instanzen von Klassen, die Sie deklariert haben.

Bei der Ausführung der main()-Methode bleibt zu berücksichtigen, daß es sich um eine Klassenmethode handelt. Deshalb wird die Klasse, die sie beinhaltet, nicht automatisch beim Ablauf des Programms ausgeführt. Soll diese Klasse als Objekt behandelt werden, müssen Sie direkt in der main()-Methode eine Instanz der Klasse erstellen (bei allen bisherigen Beispielen ist das der Fall).

Hilfsklassen

Ihre Java-Applikation kann entweder nur aus einer Klasse, wie das bei den meisten größeren Programmen der Fall ist, oder aus mehreren Klassen bestehen. Dabei werden dann verschiedene Instanzen der einzelnen Klassen erzeugt und verwendet, während das Programm ausgeführt wird. Sie können so viele Klassen erzeugen, wie Sie wollen, und solange sich diese in dem Verzeichnis befinden, auf das die Umgebungsvariable CLASSPATH zeigt, ist Java auch in der Lage, diese zu finden, während Ihr Programm läuft, sofern Sie das JDK verwenden.

Beachten Sie bitte, daß nur in einer Klasse, der Start-Klasse, eine main()-Methode vorhanden sein muß. Denken Sie bitte daran, daß main() nur verwendet wird, um das Programm zu starten und ein Startobjekt zu erzeugen. Danach sind die Methoden in den verschiedenen Klassen und Objekten an der Reihe. Obwohl Sie main()-Methoden in Hilfsklassen implementieren können, werden diese ignoriert, wenn das Programm ausgeführt wird.

Java-Anwendungen und Befehlszeilenargumente

Da Java-Anwendungen in sich geschlossene Programme sind, sollte man in der Lage sein, Argumente oder Optionen an dieses Programm weiterzugeben, um festzulegen, wie das Programm abläuft, oder um ein allgemeines Programm mit verschiedenen Eingabearten zu betreiben. Befehlszeilenargumente können für viele verschiedene Zwecke benutzt werden, z.B. um die Debugging-Eingabe zu aktivieren, den Namen einer Datei zu bezeichnen, die gelesen oder beschrieben werden soll, oder für andere Informationen, die Ihr Java-Programm wissen soll.

Argumente an Java-Programme übergeben

Wie Sie Argumente an eine Java-Applikation übergeben, hängt von der Plattform ab, auf der Sie Java ausführen. Unter Windows und Unix können Sie Argumente über die Kommandozeile übergeben. Auf dem Macintosh stellt Ihnen der Java Runner ein spezielles Fenster zur Verfügung, um diese Argumente einzugeben.

Windows/Solaris

Um Argumente an ein Programm unter Windows und Solaris zu übergeben, geben Sie diese auf Kommandozeilenebene mit dem Aufruf Ihres Java-Programms an:

java Myprogram argumentEins 2 drei

In dem vorigen Beispiel wurden drei Argumente an das Programm übergeben: argument1, die Zahl 2 und drei. Beachten Sie bitte, daß ein Leerzeichen die einzelnen Argumente voneinander trennt.

Um Argumente zu gruppieren, die ihrerseits Leerzeichen enthalten, schließen Sie diese in doppelte Anführungszeichen ein. Das Argument "No Shoes No Shirt No Service" stellt für ein Programm ein einziges Argument dar, da durch die Anführungszeichen verhindert wird, daß die Leerzeichen zur Trennung der einzelnen Argumente verwendet werden. Die Anführungszeichen sind nicht in dem Argument enthalten, wenn dieses an das Programm geschickt und von der main()-Methode verarbeitet wird.

Argumente in einer Java-Applikation verarbeiten

Wie verarbeitet Java Argumente? Java speichert sie in einem String-Array, das an die Methode main() in Ihrer Java-Applikation weitergegeben wird. Sie erinnern sich an die Signatur von main():

public static void main (String arg[]) { ... }

Hier ist arg der Name des String-Arrays, das die Argumentenliste enthält. Sie können dieses Array nach Geschmack benennen.

Innerhalb Ihrer main()-Methode können Sie dann die Argumente, die Ihr Programm erhalten hat, beliebig handhaben, indem Sie das Array entsprechend durchgehen. Das Beispiel in Listing 6.5 ist eine sehr einfache Klasse, die die erhaltenen Argumente zeilenweise ausgibt.

Listing 6.5: Der gesamte Quelltext von EchoArgs.java

 1: class EchoArgs {
 2:     public static void main(String arguments[]) {
 3:         for (int i = 0; i < arguments.length; i++) {
 4:             System.out.println("Argument " + i + ": " + arguments[i]);
 5:         }
 6:     }
 7: }

Im Anschluß sehen Sie ein Beispiel für Argumente, die dieses Programm verarbeitet:

java EchoArgs Wilhelm Niekro Hough 49

Wenn Sie die EchoArgs-Applikation mit den obigen Kommandozeilenargumenten ausführen, wird die folgende Ausgabe erzeugt:

Argument 0: Wilhelm
Argument 1: Niekro
Argument 2: Hough
Argument 3: 49
Hier nun ein weiteres Beipiel 
java EchoArgs "Hoyt Wilhelm" Charlie Hough
Argument 0: Hoyt Wilhelm
Argument 1: Charlie
Argument 2: Hough

Beachten Sie die Gruppierung der Argumente im zweiten Beispiel. Die Anführungszeichen um Hoyt Wilhelm sorgen dafür, daß das Argument als eine Einheit innerhalb des Argumenten-Arrays behandelt wird.

Ein wichtiger Faktor der Argumente, die Sie an ein Java-Programm weitergeben, ist, daß alle Argumente in einem String-Array gespeichert werden. Sollen sie nicht als Strings behandelt werden, müssen Sie sie in den gewünschten Typ umwandeln.


Das Array der Argumente ist in Java nicht mit argv in C und Unix identisch. Insbesondere arg[0] oder arguments[0], das erste Element im Argumenten-Array, ist das erste Argument in der Befehlszeile nach dem Namen der Klasse, es ist nicht der Name des Programms wie in C. Achten Sie darauf, wenn Sie Ihre Java-Programme schreiben.

Nehmen wir beispielsweise an, Sie haben ein sehr einfaches Java-Programm namens SumAverage, das eine beliebige Anzahl an numerischen Argumenten erhält und die Summe sowie den Mittelwert dieser Argumente ausgibt. Eine erste Möglichkeit der Weitergabe an dieses Programm ist in Listing 6.6 aufgeführt. Probieren Sie nicht, diese Version zu kompilieren. Sehen Sie sich einfach den Code an, und versuchen Sie herauszufinden, was dieser tut.

Listing 6.6: Erster Versuch von SumAverage.java

 1: class SumAverage {
 2:     public static void main(String arguments[]) {
 3:         int sum = 0;
 4: 
 5:         for (int i = 0; i < arguments.length; i++) {
 6:             sum += arguments[i];
 7:         }
 8: 
 9:         System.out.println("Sum is: " + sum);
10:         System.out.println("Average is: " +
11:             (float)sum / arguments.length);
12:     }
13: }

Auf den ersten Blick sieht dieses Programm ganz einfach und übersichtlich aus. Eine for-Schleife geht das Argumenten-Array durch, dabei werden die Summe und der Mittelwert ermittelt und als letzter Schritt ausgegeben.

Was passiert aber, wenn Sie versuchen, dieses Programm zu kompilieren? Sie erhalten folgenden Fehler:

SumAverage.java:9:Incompatible type for +=. Can't convert java.lang.String to int.
sum += args[i];

Diese Fehlermeldung erscheint, weil das Argumenten-Array ein String-Array ist. Obwohl Ganzzahlen an das Programm in der Befehlszeile weitergereicht wurden, werden diese Ganzzahlen in Strings konvertiert und dann im Array gespeichert. Um diese Ganzzahlen summieren zu können, müssen sie von Strings zurück in Ganzzahlen konvertiert werden. In der Klasse Integer gibt es die Klassenmethode parseInt(), die genau diesem Zweck dient. Wenn Sie Zeile 6 so abändern, daß hier diese Methode verwendet wird, funktioniert das Programm:

sum += Integer.parseInt(args[i]);

Wenn Sie jetzt das Programm kompilieren, läuft es fehlerfrei ab und gibt die erwarteten Ergebnisse aus. java SumAverage 1 2 3 ergibt beispielsweise folgende Ausgabe:

Sum is: 6
Average is: 2

Zusammenfassung

Nach dem heutigen Tag sollten Sie wissen, warum Java Klasse hat. Alles, was Sie in Java erstellen, bezieht eine Hauptklasse ein, die mit anderen Klassen nach Bedarf interagiert. Dies stellt einen ganz anderen Ansatz dar, als es bei anderen Programmiersprachen der Fall ist.

Heute haben Sie alle Teile, die Sie in den bisherigen Lektionen dieser Woche gelernt haben, vereint, um Java-Klassen zu erstellen und sie in Java-Applikationen zu benutzen. Im einzelnen haben Sie in dieser Lektion folgendes gelernt:

Morgen werden Sie die erste Woche abschließen und dabei einige fortgeschrittene Aspekte der Programmierung mit Methoden lernen.

Bis dahin hat die Klasse frei.

Fragen und Antworten

Frage:
Sie haben erwähnt, daß konstante, lokale Variablen in Applets, die zu Java 1.02 kompatibel sein sollen, nicht erzeugt werden können. Warum sollte ich überhaupt Programme erstellen, die die aktuellen Features der Sprache in Java 1.2 nicht nutzen?

Antwort:
Der wahrscheinlichste Grund ist, daß Sie versuchen, ein Applet zu programmieren, das mit den meisten Browsern zusammenarbeitet. Die volle Unterstützung der Java-Versionen nach 1.02 fehlt noch in Browsern wie dem Netscape Navigator und dem Microsoft Internet Explorer, obwohl JavaSoft an Möglichkeiten arbeitet, dies zu beheben. Die gesamte Situation wird an Tag 8 besprochen.

Frage:
Eine meiner Klassen hat eine Instanzvariable namens origin. Ferner habe ich eine lokale Variable namens origin in einer Methode, die aufgrund des Gültigkeitsbereiches von der lokalen Variablen verborgen wird. Gibt es eine Möglichkeit, den Wert der Instanzvariablen zu erhalten?

Antwort:
Die einfachste Möglichkeit ist, die lokale Variable nicht genauso zu benennen wie die Instanzvariable. Falls Sie unbedingt den gleichen Namen verwenden wollen, können Sie this.origin verwenden, um spezifisch auf die Instanzvariable zu verweisen, während Sie als Referenz auf die lokale Variable origin verwenden.

Frage:
Ich habe ein Programm für vier Argumente geschrieben, wenn ich aber weniger Argumente angebe, stürzt das Programm ab, und ich erhalte einen Laufzeitfehler.

Antwort:
Prüfen Sie Zahl und Typ der Argumente, die Ihr Programm erwartet. Java überprüft das nicht automatisch für Sie. Verlangt Ihr Programm vier Argumente, müssen es tatsächlich vier sein, ansonsten erhalten Sie eine Fehlermeldung.



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