|
|
.JAVA GLOSSAR F-J
F
Membervariablen
mit dem Attribut final dürfen nicht verändert werden,
sind also als Konstanten anzusehen. Methoden
des Typs final dürfen nicht überlagert werden; ebensowenig
dürfen Klassen des Typs
final zur Ableitung neuer Klassen
verwendet werden. Wird das Attribut final dagegen nicht verwendet,
sind Membervariablen veränderbar,
können Methoden überlagert
und Klassen abgeleitet werden.
Falls eine Methode oder Klasse das Attribut
final besitzt, kann der Compiler auf die dynamische Methodensuche
verzichten. final-Methoden können daher performanter
aufgerufen werden als normale Methoden.
Dies ist einer der Gründe dafür, dass die Java-Designer
einige der mitgelieferten Klassen als final deklariert haben.
Es führt aber gleichzeitig dazu, dass die entsprechenden
Klassen nicht mehr erweitert werden können. Ein prominentes
Beispiel aus der Laufzeitbibliothek ist die als final deklarierte
Klasse String.
Seit dem JDK 1.1 kann das final-Attribut
auch auf Parameter von Methoden
und lokale Variablen angewendet
werden. Dadurch stellt der Compiler sicher, dass die Variable
bzw. der Parameter nach der Initialisierung nicht mehr verändert
wird. Die Initialisierung muss
dabei nicht unbedingt bei der Deklaration erfolgen, sondern
kann auch später vorgenommen werden. Wichtig ist, dass
nur genau einmal ein Wert zugewiesen wird.
Im Gegensatz zu C oder C++ gibt es allerdings
bei als final deklarierten Objektparametern keine Möglichkeit,
zwischen dem Objekt insgesamt und seinen einzelnen Elementen
zu unterscheiden. Eine als final deklarierte Objektvariable
wird zwar insgesamt vor Zuweisungen geschützt, der Wert
einzelner Membervariablen kann
jedoch verändert werden. Dies gilt analog für Arrays,
die ja ebenfalls Objekte sind: final bietet keinen Schutz
gegen die unerwünschte Zuweisung eines Werts an ein einzelnes
Element des Arrays.
|
|
Neben Konstruktoren, die während
der Initialisierung eines Objekts
aufgerufen werden, gibt es in Java auch Destruktoren. Sie
werden unmittelbar vor dem Zerstören eines Objekts aufgerufen.
Ein Destruktor wird als geschützte (protected)
parameterlose Methode mit dem Namen finalize definiert.
Da Java über ein automatisches Speichermanagement verfügt,
kommt den Destruktoren hier eine viel geringere Bedeutung
zu als in anderen objektorientierten Sprachen. Anders als
etwa in C++ muss sich der Entwickler ja nicht um die Rückgabe
von belegtem Speicher kümmern; und das ist sicher eine
der Hauptaufgaben von Destruktoren in C++. |
|
Die Methode flush
sorgt dafür, dass die gepufferten Daten tatsächlich
geschrieben werden. flush schreibt die gepufferten Daten physikalisch
auf das Ausgabegerät und leert alle Puffer. |
|
G
Fordert ein Anwender
in seinem Web-Browser eine Seite an, so wird diese Anfrage
vom Browser als GET-Transaktion an den Server geschickt. Um
beispielsweise die Seite http://www.xyz.com/index.php?fs=truel zu
laden, wird folgendes Kommando an den Server www.xyz.com gesendet:
GET /index.php?fs=truel
Der erste Teil gibt den Kommandonamen an, dann folgt die gewünschte
Datei. Die Zeile muss mit einer CRLF-Sequenz abgeschlossen
werden, ein einfaches '\n' reicht nicht aus. Der Server versucht
nun die angegebene Datei zu laden und überträgt
sie an den Client. Ist der Client ein Web-Browser, wird er
den darin befindlichen HTML-Code interpretieren und auf dem
Bildschirm anzeigen. Befinden sich in der Seite Verweise auf
Images, Applets
oder Frames, so fordert der Browser die fehlenden Seiten in
weiteren GET-Transaktionen von deren Servern ab.
Die Struktur des GET-Kommandos wurde mit
der Einführung von HTTP 1.0 etwas erweitert. Zusätzlich
werden nun am Ende der Zeile eine Versionskennung und wahlweise
in den darauffolgenden Zeilen weitere Headerzeilen mit Zusatzinformationen
mitgeschickt. Nachdem die letzte Headerzeile gesendet wurde,
folgt eine leere Zeile (also ein alleinstehendes CRLF), um
das Kommandoende anzuzeigen. HTTP 1.0 ist weit verbreitet,
und das obige Kommando würde von den meisten Browsern
in folgender Form gesendet werden (jede der beiden Zeilen
muss mit CRLF abgeschlossen werden):
GET /index.php?fs=truel HTTP/1.0
Nachdem der Request gelesen wurde, wird in createResponse
die Antwort erzeugt. Zunächst prüft die Methode,
ob es sich um ein GET-Kommando handelt (HTTP kennt noch andere
Kommandos). Ist das nicht der Fall, wird durch Aufruf von
httpError eine Fehlerseite an den Browser gesendet. Andernfalls
fährt die Methode mit der Bestimmung des Dateityps fort.
Der Dateityp wird mit Hilfe der Arraykonstante mimetypes anhand
der Dateierweiterung bestimmt und in einen passenden MIME-Typ
konvertiert, der im Antwortheader an den Browser übertragen
wird. Der Browser entscheidet anhand dieser Information, was
mit der nachfolgend übertragenen Datei zu tun ist (Anzeige
als Text, Anzeige als Grafik, Speichern in einer Datei usw.).
Wird eine Datei angefordert, deren Erweiterung nicht bekannt
ist, sendet der Server sie als application/octet-stream an
den Browser, damit dieser dem Anwender die Möglichkeit
geben kann, die Datei auf der Festplatte zu speichern.
Mit getType kann der Typ der Membervariable
bestimmt werden. Das zurückgegebene Klassenobjekt
beschreibt ihn in derselben Weise wie beispielsweise das Parameterobjekt
von getMethod. Mit get kann auf den Wert zugegriffen werden,
den die Membervariable in dem
als Argument übergebenen Objekt hat. Handelt es sich
um einen primitiven Typ, wird dieser automatisch in die passende
Wrapper-Klasse verpackt und als
Objekt zurückgegeben. Referenztypen werden unverändert
zurückgegeben. Mit Hilfe der Methode set kann der Wert
einer Membervariable verändert
werden. Das erste Argument repräsentiert das zu veränderende
Objekt und das zweite den neuen Wert der Membervariable.
Soll ein primitiver Typ verändert werden, muß er
vor der Übergabe in die passende Wrapper-Klasse
verpackt werden.
|
|
Methoden
definieren das Verhalten von Objekten. Sie werden innerhalb
einer Klassendefinition angelegt und haben Zugriff auf alle
Variablen des Objekts. Methoden
sind das Pendant zu den Funktionen anderer Programmiersprachen,
arbeiten aber immer mit den Variablen
des aktuellen Objekts. Globale Funktionen, die vollkommen
unabhängig von einem Objekt oder einer Klasse
existieren, gibt es in Java ebenso wenig wie globale Variablen.
Wir werden später allerdings Klassenvariablen
und -methoden kennen lernen, die nicht an eine konkrete Instanz
gebunden sind. |
|
H
Hashtable |
Die Klasse Hashtable und Hash-Funktion |
Die Klasse Hashtable
ist eine Konkretisierung der abstrakten Klasse Dictionary.
Diese stellt einen assoziativen Speicher dar, der Schlüssel
auf Werte abbildet und über den Schlüsselbegriff
einen effizienten Zugriff auf den Wert ermöglicht. Ein
Dictionary speichert also immer zusammengehörige Paare
von Daten, bei denen der Schlüssel als Name des zugehörigen
Wertes angesehen werden kann. Über den Schlüssel
kann später der Wert leicht wiedergefunden werden.
Da ein Dictionary auf unterschiedliche Weise
implementiert werden kann, haben die Java-Designer entschieden,
dessen abstrakte Eigenschaften in einer Basisklasse zusammenzufassen.
Die Implementierung Hashtable benutzt das Verfahren der Schlüsseltransformation,
also die Verwendung einer Transformationsfunktion (auch Hash-Funktion
genannt), zur Abbildung von Schlüsseln auf Indexpositionen
eines Arrays. Weitere Konkretisierungen der Klasse Dictionary,
etwa auf der Basis binärer Bäume, gibt es in Java
derzeit nicht.
|
|
I
if / else
|
Schleifen - Anweisungen
|
Die if-Anweisung
wertet zunächst den Ausdruck ausdruck aus. Danach führt
sie die Anweisung anweisung genau dann aus, wenn das Ergebnis
des Ausdrucks true ist. Ist ausdruck
hingegen false, so wird die Anweisung nicht ausgeführt,
sondern mit der ersten Anweisung nach der if-Anweisung fortgefahren.
Mit der if-else-Anweisung gibt es eine weitere
Verzweigung in Java. Falls ausdruck wahr ist, wird anweisung1
ausgeführt, andernfalls anweisung2. Eine der beiden Anweisungen
wird also in jedem Fall ausgeführt. Anstelle einer einzelnen
Anweisung kann jeweils auch eine Folge von Anweisungen angegeben
werden, wenn sie innerhalb eines Blocks steht. Dieser wird
als Einheit betrachtet und komplett ausgeführt, wenn
die entsprechende Bedingung zutrifft.
Zu beachten ist, dass der Testausdruck in
der Schleife vom Typ boolean
sein muss. Anders als in C ist es in Java nicht erlaubt, einen
numerischen Ausdruck an seiner Stelle zu verwenden.
|
|
Durch das bloße
Definieren eines Interfaces wird
die gewünschte Funktionalität aber noch nicht zur
Verfügung gestellt, sondern lediglich beschrieben. Soll
diese von einer Klasse tatsächlich realisiert werden,
muss sie das Interface implementieren
. Dazu erweitert sie die class-Anweisung
um eine implements-Klausel, hinter der der Name des zu implementierenden
Interfaces angegeben wird. Der
Compiler sorgt dafür, dass alle im Interface geforderten
Methoden definitionsgemäß
implementiert werden. Zusätzlich "verleiht"
er der Klasse einen neuen Datentyp, der - wie wir noch sehen
werden - ähnliche Eigenschaften wie eine echte Klasse
hat. |
|
Am Anfang des Programms
werden die gewünschten Klassen
mit Hilfe einer import-Anweisung eingebunden, um die Klassen
des angegebenen Pakets bekannt
zu machen. Ohne diese Anweisung würden Anweisungen vom
Compiler nicht gefunden und es gäbe eine entsprechende
Fehlermeldung. |
|
Eine Applikation
wird gestartet, indem vom Java-Interpreter die Klassenmethode
main aufgerufen wird. Das Starten
eines Applets wird dadurch erreicht,
dass der Web-Browser die Applet-Klasse instanziert und danach
die Methoden init und start aufruft.Die
Methode init wird aufgerufen, um dem Applet
die Möglichkeit zu geben, Initialisierungen vorzunehmen. |
|
Insbesondere bei
den Erweiterungen für die Programmierung grafischer Oberflächen,
die mit dem JDK 1.1 eingeführt wurden, entstand der Wunsch
nach einem flexibleren Mechanismus. Durch das neue Ereignismodell
müssen seit dem JDK 1.1 sehr viel häufiger kleine
Programmteile geschrieben werden, die nur in einem eng begrenzten
Kontext eine Bedeutung haben. Die Lösung für dieses
Problem wurde mit der Einführung von lokalen und anonymen
Klassen geschaffen (im JDK werden sie als Inner Classes
bezeichnet). Dabei wird innerhalb einer bestehenden Klasse
X eine neue Klasse Y definiert, die nur innerhalb von X sichtbar
ist. Objektinstanzen von Y können damit auch nur innerhalb
von X erzeugt werden. Anders herum kann Y auf die Membervariablen
von X zugreifen.
Lokale und anonyme
Klassen sind ein mächtiges - und manchmal leicht
verwirrendes - Feature von Java. Darüber hinaus gibt
es seltener genutzte Varianten, die hauptsächlich durch
trickreiche Anwendung von Modifiern auf die lokale
Klasse oder ihrer Member entstehen.
|
|
instanceof
|
Der instanceof-Operator
|
Der instanceof-Operator
kann verwendet werden, um herauszufinden, zu welcher Klasse
ein bestimmtes Objekt gehört. Der Ausdruck a instanceof
b liefert genau dann true, wenn
a und b Referenztypen sind und a eine Instanz der Klasse
b oder einer ihrer Unterklassen ist. Falls das Ergebnis des
instanceof-Operators nicht bereits zur Compile-Zeit ermittelt
werden kann, generiert der Java-Compiler Code, um den entsprechenden
Check zur Laufzeit durchführen zu können. |
|
In objektorientierten
Programmiersprachen wird eine Klasse durch die Zusammenfassung
einer Menge von Daten und darauf operierender Funktionen (die
nun Methoden genannt werden)
definiert. Die Daten werden durch einen Satz Variablen
repräsentiert, der für jedes instanziierte Objekt
neu angelegt wird (diese werden als Attribute, Membervariablen,
Instanzvariablen oder Instanzmerkmalebezeichnet). Die Methoden
sind im ausführbaren Programmcode nur einmal vorhanden,
operieren aber bei jedem Aufruf auf den Daten eines ganz bestimmten
Objekts (das Laufzeitsystem übergibt bei jedem Aufruf
einer Methode einen Verweis auf den Satz Instanzvariablen,
mit dem die Methode gerade arbeiten soll).
Die Instanzvariablen repräsentieren
den Zustand eines Objekts. Sie können bei jeder Instanz
einer Klasse unterschiedlich sein und sich während seiner
Lebensdauer verändern. Die Methoden
repräsentieren das Verhalten des Objekts. Sie sind -
von gewollten Ausnahmen abgesehen, bei denen Variablen
bewusst von außen zugänglich gemacht werden - die
einzige Möglichkeit, mit dem Objekt zu kommunizieren
und so Informationen über seinen Zustand zu gewinnen
oder diesen zu verändern.
|
|
interface
|
Schnittstellen (Interfaces)
|
Es wurde bereits
erwähnt, dass es in Java keine Mehrfachvererbung
von Klassen gibt. Die möglichen Schwierigkeiten beim
Umgang mit mehrfacher Vererbung
und die Einsicht, dass das Erben nichttrivialer Methoden
aus mehr als einer Klasse in
der Praxis selten zu realisieren ist, haben die Designer dazu
veranlasst, dieses Feature nicht zu implementieren. Andererseits
sah man es als wünschenswert an, dass Klassen eine oder
mehrere Schnittstellendefinitionen erben können, und
hat mit den Interfaces ein Ersatzkonstrukt geschaffen, das
dieses Feature bietet.
Ein Interface ist eine besondere Form einer
Klasse, die ausschließlich abstrakte Methoden und Konstanten
enthält. Anstelle des Schlüsselwortes class
wird ein Interface mit dem Bezeichner
interface deklariert. Alle Methoden
eines Interfaces sind implizit abstrakt und öffentlich.
Neben Methoden kann ein Interface
auch Konstanten enthalten, die Definition von Konstruktoren
ist allerdings nicht erlaubt.
Durch das bloße Definieren eines Interfaces
wird die gewünschte Funktionalität aber noch nicht
zur Verfügung gestellt, sondern lediglich beschrieben.
Soll diese von einer Klasse tatsächlich realisiert werden,
muss sie das Interface implementieren . Dazu erweitert sie
die class-Anweisung um eine implements-Klausel,
hinter der der Name des zu implementierenden Interfaces
angegeben wird.
Die Art der Realisierung der vereinbarten
Methoden spielt für das
Implementieren eines Interfaces
keine Rolle. Tatsächlich kommt es ausgesprochen häufig
vor, daß Interfaces von sehr unterschiedlichen Klassen
implementiert und die erforderlichen Methoden
auf sehr unterschiedliche Weise realisiert werden.
Eine Klasse kann ein Interface auch dann
implementieren, wenn sie nicht alle seine Methoden
implementiert. In diesem Fall ist die Klasse allerdings als
abstract zu deklarieren und kann
nicht dazu verwendet werden, Objekte zu instanzieren.
Nützlich ist ein Interface immer dann,
wenn Eigenschaften einer Klasse
beschrieben werden sollen, die nicht direkt in seiner normalen
Vererbungshierarchie abgebildet
werden können. Hätten wir beispielsweise Groesse
als abstrakte Klasse definiert, ergäbe sich eine sehr
unnatürliche Ableitungshierarchie, wenn Autos, Fußballplätze
und Papierblätter daraus abgeleitet wären. Durch
Implementieren des Groesse-Interfaces können sie die
Verfügbarkeit der drei Methoden laenge, hoehe und breite
dagegen unabhängig von ihrer eigenen Vererbungslinie
garantieren.
|
|
J
jar ist ein Archivierungsprogramm,
das Dateien und komplette Unterverzeichnisse komprimieren
und in eine gemeinsame Archivdatei packen kann. Es verwendet
ein Kompressionsformat, das den diversen zip-/unzip-Programmen
ähnelt, und wird analog dem UNIX-Tool tar bedient. Ein
Vorteil von jar ist seine Portabilität, die sowohl für
das erzeugte Dateiformat als auch für das (in Java geschriebene)
Programm selbst gilt.
Wichtigster Einsatzzweck von jar ist es,
alle zu einem Applet gehörenden
Dateien (.class-, Image-, Sound-Dateien
usw.) in einer einzigen Datei zusammenzufassen. Dadurch müssen
Web-Browser nicht für jede einzelne Datei, die in einem
Applet benötigt wird, eine
eigene GET-Transaktion absetzen,
sondern können alle erforderlichen Files in einem Schritt
laden. Die Ladezeit von Applets
wird dadurch drastisch verringert, insbesondere, wenn viele
kleine Dateien benötigt werden.
Leider unterstützen noch nicht alle
Browser das jar-Format, so dass seine Verwendung zum heutigen
Zeitpunkt überlegt sein will. Für die nahe Zukunft
ist es aber ein wichtiger Schritt zur Verbesserung der Ladezeiten
von Applets.
|
|
Dieses Paket
wurde von den Entwicklern der Sprache als so wichtig angesehen,
dass es bei jedem Compilerlauf automatisch importiert wird.
Man kann sich das so vorstellen, als wenn am Anfang jeder
Quelldatei implizit die folgende Anweisung stehen würde:
import java.lang.*;
Ein expliziter Import von java.lang ist daher niemals nötig.
Alle anderen Pakete müssen
jedoch vor ihrer Verwendung importiert werden, wenn auf die
Anwendung voll qualifizierter Klassennamen verzichtet werden
soll.
|
|
Der Compiler javac
übersetzt Sourcecode in Bytecode. Zu jeder Klasse, die
innerhalb einer .java-Datei definiert wurde, wird eine eigene
. class-Datei erzeugt. Der Compiler
wacht automatisch über die Abhängigkeiten zwischen
den Quelldateien. Wird beispielsweise in einer Klasse X in
der Datei X.java eine Klasse Y, die in Y.java liegt, verwendet,
so wird Y.java automatisch mit übersetzt, wenn es erforderlich
ist. Anstelle der Liste von Dateinamen kann nach einem @ auch
eine Textdatei angegeben werden, in der die zu übersetzenden
Dateien durch Whitespaces getrennt angegeben werden. |
|
javadoc
|
javadoc [ options ] { package
| sourcefile }
|
javadoc ist ein Programm,
das aus Java-Quelltexten Dokumentationen im HTML-Format erstellt.
Dazu verwendet es die öffentlichen Klassen-,
Interface- und Methodendeklarationen
und fügt zusätzliche Informationen aus eventuell
vorhandenen Dokumentationskommentaren hinzu. Zu jeder Klassendatei
xyz.java wird eine HTML-Seite xyz.php?fs=truel generiert, die über
verschiedene Querverweise mit den anderen Seiten desselben
Projekts in Verbindung steht. Zusätzlich generiert javadoc
diverse Index- und Hilfsdateien, die das Navigieren in den
Dokumentationsdateien erleichtern. |
|
javaw
|
javaw [ options ] classname [{ args
}]
|
Der Interpreter java
dient dazu, kompilierte Java-Programme auszuführen, die
als Bytecode in . class-Dateien
vorliegen. javaw erfüllt denselben Zweck, erzeugt aber
kein Terminalfenster beim Start des Programms und erlaubt
nicht die Verwendung der Standard-Streams System.in, System.out
und System.err. Beim Aufruf beider Programme wird der Name
einer Klassendatei erwartet (ohne die Erweiterung . class).
Damit sie ausgeführt werden kann, muss sie eine Klassenmethode
main mit folgender Signatur
enthalten. |
|
Die RMI-Registry
bietet lediglich eine sehr einfache Abbildung von Namen auf
Remote-Objekte. Hierarchische Namensräume, dynamische
Objektsuche, Lastverteilung oder ähnliche Eigenschaften
fehlen ihr dagegen. Möglicherweise ist es besser, einen
anderen Namens-Service zu verwenden. Mit JNDI (Java Naming
and Directory Interface) steht
dabei im JDK 1.3 bereits eine mögliche Alternative standardmäßig
zur Verfügung. |
|
Die beiden anderen
Methoden, die eine Ausnahme des
Typs InterruptedException auslösen können, sind
join der Klasse Thread und wait
der Klasse Object. Auch sie setzen
beim Auftreten der Ausnahme das Abbruchflag zurück und
müssen daher in ähnlicher Weise behandelt werden. |
|
Mit dem JDK wird
auch die Laufzeitumgebung JRE (Java Runtime Environment) installiert.
Sie besitzt einen eigenen Deinstallationseintrag und befindet
sich im Verzeichnis c:\programme\javasoft\jre\1.3. In der
Installationsroutine des JDK 1.2 hatte das JRE einen separaten
Lizenztext und konnte wahlweise in ein anderes Verzeichnis
installiert werden. Seit dem JDK 1.3 gibt es diese zusätzlichen
Schritte nicht mehr. Für Arbeitsplätze, die nur
das JRE benötigen (auf denen Java-Programme lediglich
ausgeführt, nicht aber entwickelt werden sollen), kann
das JRE auch alleine installiert werden. |
|
Quelle: Java - Glossary zusammengestellt aus „Go To Java 2“,
Zweite Auflage, Addison Wesley, Version 2.0 © 2000 Guido Krüger
|
|