Das dritte Kapitel erklärt Besonderheiten der Sprache anhand von Praxisbeispielen. Es wurde versucht, möglichst viele Spracheigenschaften auf engstem Raum zu verdeutlichen, daher sind die Beispiele teilweise sehr komplex und sollen nur als Hilfe beim selbständigen Programmieren dienen.
Dieses Programm dient nur der Einführung und schreibt etwas an die Standardausgabe.
hallo.java
Bei den ersten 6 Zeilen handelt es sich um (besondere) Kommentare.
Genaueres erfahren Sie dazu beim dritten Beispiel
bzw. im Kapitel 2.3.
Danach beginnt ein neuer Block, die öffentliche Klasse "hallo".
In dieser Klasse wird nun die öffentliche Funktion main definiert,
welche beim Starten der Klasse mittels "java" automatisch
aufgerufen wird. Auf die Parameter, die der Funktion übergeben
werden (das argv-Feld), wird später eingegangen.
System.out ist ein PrintStream, der
automatisch mit der Standardausgabe (Konsole) verbunden ist. Ein
PrintStream kennt die Methode println (siehe API), die als Parameter
in diesem Fall eine Zeichenkette (String) erhält. Diese wird
ausgegeben. In der nächsten Zeile wird eine Zeichenkette
und eine Zahl (Rechenergebnis) auf den Bildschirm geschrieben.
Danach wird das Programm verlassen.
Geben Sie das Programm mit einem Editor
ein und speichern Sie es unter dem Namen "hallo.java".
Eine Quelldatei sollte immer den gleichen Namen haben, wie die
darin definierte Klasse, in den meisten Fällen ist dies auch
unumgänglich.
Starten Sie jetzt mit "javac hallo.java"
den Compilerlauf. Wenn sich keine Tipfehler eingeschlichen haben,
sollten Sie sich bald darauf wieder in der Kommandozeile befinden,
wo sie das übersetzte Programm ("hallo.class")
durch Eingabe von "java hallo" starten können.
Achten Sie auf Groß- und Kleinschreibung!
Experimentieren Sie jetzt etwas mit
dem Programm, indem Sie z.B. die Zeichenkette durch eine Rechenaufgabe
ersetzen, z.B.: System.out.println(3+5). Ebenfalls durch den Plus-Operator
lassen sich auch mehrere Zeichenketten verbinden, was dasselbe
bewirkt, wie mehrere print-Befehle mit je einem Argument.
Sie können dem Objekt System.out
natürlich auch andere Aufträge (Methoden) geben, die
ein PrintStream versteht (siehe java.io.PrintStream).
Dieses kleine Programm zeigt Ihnen, was Sie bei Vergleichen mit Strings beachten müssen. Benutzen Sie immer die "equals"-Methode, da der "=="-Operator die Objekte und nicht deren Inhalt vergleicht.
equal.java
Anhand dieses Programmes sollen Besonderheiten von Java, wie z.B. DocComments, Inner classes und Interfaces erklärt werden.
ls.java
Das Programm beginnt mit einem Import-Statement,
welches alle Klassen unter java.io einbindet. Import ist eine
aus der Programmiersprache Objective-C (NeXTSTEP) entnommene Erweiterung
der #include-Directive von C++, die automatisch darauf achtet,
daß keine Klasse mehrfach eingebunden wird, was "?
already defined"-Meldungen vorbeugt.
Die folgenden Zeilen enthalten eine
besondere Art des Kommentars, nämlich den in der Sprachdefinition
von Java enthaltenen DocComment. Wie normale Kommentare (// und
/* */) wird auch er vom Compiler ignoriert (bis auf den @deprecated-Tag,
bei dem der Compiler eine Warnung ausgibt, siehe dazu die Tool-Dokumentation),
aber mit dem in JDK enthaltenen Tool javadoc kann man sich auf
diese Weise schnell eine API-Dokumentation basteln (lassen), denn
javadoc sucht speziell nach Kommentaren in /** */ und erzeugt
aus diesen HTML-Dokumente.
Als nächstes wird die Klasse ls
definiert und in ihr die Variable ext. Die Definition von ext
ist mit dem Modifier static versehen, was bedeutet, daß
es sich um keine Instanz- sondern um eine Klassenvariable handelt,
d.h. es gibt sie nicht einmal pro Instanz sondern nur einmal pro
Klasse.
Bei der Programmausführung wird
nun zuerst wie bei C nach der Methode main gesucht, der in dem
Zeichenkettenfeld argv alle Kommandozeilenparameter übergeben
werden. Hierbei ist neben den Modifiern "public static"
zu beachten, daß der erste Parameter im Gegensatz zu C den
Index 0 hat und nicht 1. "void" ist der Rückgabetyp
der Methode.
Die Feldvariable "length"
enthält die Anzahl der Elemente in "argv". Wurden
keine Parameter übergeben, werden alle Dateien angezeigt,
bei einem Parameter werden nur Dateien angezeigt, die mit diesem
Text enden und bei mehr als einem Parameter wird eine Information
zur Benutzung ausgegeben und dann das Programm beendet.
System.out ist ein PrintStream (siehe
java.io.PrintStream), der standardmäßig mit der Konsole
(Bildschirmausgabe) verbunden ist. Über seine println-Methode
kann man leicht Zeichenketten, Zahlen und anderes ausgeben. Verschiedene
Argumente können mit dem Plus-Operator verbunden werden.
Mit "typ name=new typ-Konstruktor(parameter)"
legt man eine Instanz einer Klasse an. In diesem Fall wird ein
neues File-Objekt mit dem Namen find erzeugt. Der Konstruktor
ist "public File(String path)", als Pfad wird ".",
also der aktuelle Pfad übergeben. Danach wird das neue Feld
files angelegt, daß später die Einträge im Directory
aufnehmen soll.
Die nächsten Zeilen sorgen sicher
für etwas Verwirrung. Es gibt aber keine andere Möglichkeit,
als daß die aktuelle Klasse eine Instanz von sich selbst
erzeugt, um die innere Klasse evalExt (weiter vorn im Quellcode)
instantiieren zu können. Wenn es sich bei der aufrufenden
Methode nicht um eine static-Funktion handelt, geht es auch ein
bißchen einfacher. Die erzeugte Instanz der Klasse evalExt
wird nun der Methode list unserer Fileinstanz find übergeben,
welche nun alle Dateien im aktuellen Pfad sucht und bei jeder
den Filenamenfilter in evalExt fragt, ob die Datei aufgenommen
werden soll.
Nun noch etwas genauer zur evalExt-Klasse.
Hinter der Klassendefinition befindet sich noch die Erweiterung
implements und dahinter der Name eines Interfaces (in diesem Fall
java.io.FilenameFilter). Interfaces sind eine ebenfalls aus Objective-C
übernommene Art der Mehrfachvererbung. Sie enthalten Vorgaben,
die eine umsetzende Klasse erfüllen muß. So enthält
z.B. FilenameFilter eine abstrakte Methode mit dem Namen accept.
Da es zu dieser unvollständigen Methode keine Implementation
gibt, muß die umsetzende (implementierende) Klasse eine
liefern, was evalExt auch tut. Wenn der ext-String leer ist, wird
jede Datei akzeptiert, ansonsten nur Dateinamen, die mit dem Text
in ext enden.
Nun weiter im Hauptprogramm. Werden
keine Einträge zurückgeliefert, bricht das Programm
mit einer diesbezüglichen Meldung ab, ansonsten werden alle
Dateinamen mit ihrer Dateilänge ausgegeben.
wc.java
Das kleine Programm erfordert als Parameter
eine beliebige Textdatei, deren Wort- und Zeilenanzahl es dann
ausgibt. Für das Lesen der Datei wird erst einmal das Package
java.io eingebunden. Der Compiler findet selbst heraus, welche
Klassen des Paketes benötigt werden. Für die Zerlegung
der Zeilen in Wörter wird der StringTokenizer aus java.util
benötigt.
Zuerst wird jetzt eine neue Zeichenkette
mit dem Namen srcName angelegt und die Variablen Lines (Zeilenanzahl)
und Words (Wörter) werden mit 0 initialisiert. Das ist eigentlich
nicht nötig, da der Compiler Integer-Variablen automatisch
den Wert 0 zuweist.
Danach wird die Kommandozeile im Feld
argv analysiert (siehe ls-Beispiel). Nur genau ein Parameter,
nämlich der Name der Textdatei wird akzeptiert, alles andere
führt zu einem Programmabbruch, vorher wird noch eine Beschreibung
ausgegeben.
Das try-Statement leitet jetzt einen
neuen Block ein, der mit einem oder mehreren catch-Statements
endet. Wird innerhalb des Blockes eine Exception (Ausnahme) ausgelöst,
so werden die Befehle im catch-Block ausgeführt. So kann
man flexibel auf Situationen wie Lesefehler, nicht gefundene Dateien,
o.ä. reagieren. Der finally-Block wird immer ausgeführt,
auch wenn das Programm an irgend einer Stelle vorher schon lange
beendet wurde.
Im try-Block wird ein neuer Eingabestrom
namens inp erzeugt. Das sieht komplizierter aus als es ist. BufferedReader
verlangt in seinem Konstruktor einen FileReader-Typ als Argument,
welcher wiederum einen Dateinamen (String) als Argument erwartet.
So muß man die Erzeugung des Objektes etwas verschachteln.
Danach wird ein String erzeugt, der
die aktuelle Zeile aufnehmen soll. Nun wird die while-Schleife
solange abgearbeitet, wie die readLine-Methode von inp einen nichtleeren
String liefert. Gleichzeitig wird das Ergebnis (die gelesene Zeile)
in line gespeichert. Diesen "Nebenwirkungseffekt" hat
Java von C geerbt.
In der Schleife wird die Anzahl der
Zeilen mit jeder gelesenen Zeile erhöht und ein StringTokenizer
mit dem Namen st angelegt, der als Argument die aktuelle Zeile
erhält. Nun wird in einer neuen while-Schleife solange die
Wortanzahl erhöht, wie es mehr Token (durch Delimiter wie
z.B. das Leerzeichen von einander getrennte Wörter) gibt.
Wurde das Dateiende erreicht, wird das
Ergebnis ausgegeben und das Programm wird nach Abarbeitung des
finally-Blockes beendet.
Hier finden Sie ein klassisches Beispiel für objektorientierte Programmierung. Die Klasse "Liste" verwaltet eine Liste, über die nur über entsprechende Methoden zugegriffen werden kann.
list.java
Die Listenklasse kann Elemente hinzufügen, entfernen, auslesen und die Anzahl der Elemente bestimmen. Die "evaluate"-Methode dient lediglich zur Vereinfachung der Bildschirmausgabe. Im Hauptprogramm wird eine Instanz dieser Klasse erzeugt und dann wird die Funktionalität der Klasse etwas getestet. Das erste "remove" führt zu einem Fehler, da die Liste noch keine Elemente enthält, die man entfernen könnte. Dann werden 6 Zufallszahlen zwischen 0 und 210 hinzugefügt. Das letzte wird wieder entfernt, die Anzahl der Elemente wird ausgegeben und diese aufgelistet.
lohn.java
Die Klasse Lohn ist das Hauptprogramm,
übersetzen sie also das gesamte Programm mit "javac
lohn.java" und starten Sie es dann mit "java lohn".
Die benötigten Klassen werden mitübersetzt, auch wenn
sie sich in anderen Quelldateien mit entsprechendem Namen befinden.
Dann müssen sie allerdings als public deklariert werden.
Das Programm enthält eine abstrakte
Klasse "SuperLohn". Diese unvollständige Klasse
enthält Funktionen, die alle Lohnarten benötigen und
als Subklassen von ihr erben. Die Superklasse selbst kann nicht
instantiiert werden.
Alle Eingaben werden über die Klasse
Eingabe abgewickelt. Die input-Methode in SuperLohn ist eine für
den speziellen Zweck angepaßte Eingabefunktion, die im Fehlerfall
einen Vorgabewert zurückliefert. Die Klassen sind online
dokumentiert, so daß sich mit javadoc eine API-Dokumentation
erstellen läßt. Dazu müssen allerdings alle Klassen
public deklariert werden und sich in jeweils eigenen Quelldateien
befinden.
hi.html
Achtung!
Dieses Applet benutzt JDK1.1-spezifischen Code und benötigt einen
entsprechenden Browser. Starten Sie diese HTML-Datei mit dem appletviewer
aus dem JDK, mit HotJava oder mit java als Application.
Obenstehende HTML-Datei soll nicht weiter erläutert werden. Sie dient dazu, hi.class als Applet zu starten. Wenn sie mit dem appletviewer geladen wird, kommt ohnehin nur der im 2. Kapitel besprochene Applet-Tag zum Tragen.
hi.java
Obenstehendes Programm kann sowohl als
Applet als auch als Application ausgeführt werden. Die dazu
verwendete Technik mag etwas verwirren (die Klasse erzeugt eine
Instanz von sich selbst), aber es ist der einzig mögliche Weg.
"hi.java" ist das einzige
Beispielprogramm welches sich ein wenig mit dem "Abstract
Window Toolkit" (AWT), der Grafikschnittstelle der Java-Plattform,
beschäftigt. Besonderheiten des Programmes sind weiterhin
die Verwendung einer "inner class" (EvtHandler) und
des neuen Event-Modells im Java-Sprachstandard 1.1.
Copyright für Texte, Programme und Design 1997 by Dirk Schönfuß
WWW: http://rcswww.urz.tu-dresden.de/~schoenfu
e-mail: schoenfu@rcs.urz.tu-dresden.de