HRZ Einführungspraktikum Java

Werbung
Begleitmaterial zum
Einführungspraktikum Java
- November 2001 -
Universität Essen
Schützenbahn 70
45127 Essen
Dozent:
Dipl.-Wirt. Inform. Frank Lützenkirchen
[email protected]
2
HRZ Einführungspraktikum Java
2
3
Themenübersicht
I.
-
II.
-
Einführung und erste Schritte mit Java
Entstehung von Java, Java heute, Eigenschaften von Java
Realisierung der Plattformunabhängigkeit mit der Java Virtual Machine
Verwendung des JDK, Applets und Applikationen
Literatur, Software und Informationsquellen im Internet
Grundlegende Sprachelemente
Kommentare und Anweisungen, Variablen, Datentypen und Literale
Operatoren, Arrays, Fallunterscheidungen und Schleifen
Methoden schreiben, Arbeiten mit Zeichen und Zeichenketten
III . Objektorientierte Programmierung mit Java
-
Klassen, Objekte, ihre Verwendung und ihr Lebenszyklus
Klassen und Konstruktoren, Zugriffsschutz durch Modifier
Klassen- und Instanzvariablen, Klassen- und Instanzmethoden
Polymorphismus und Overloading, Vererbung und Overriding
Abstrakte Klassen, Interfaces und Packages nutzen
IV. Nützliches und Wissenswertes
-
V.
-
Die Klasse Objekt und Wrapper-Klassen, Casting und Konvertierung von Datentypen
Datums- und Zeitwerte, Mathematische und Zufallsfunktionen
Laufzeitfehler erzeugen und abfangen mit Exceptions
Aus der Werkzeugsammlung: StringTokenizer, Vector, Stack und Hashtable
Die Klassen System, Runtime und Process
Applets, Grafik- und Soundausgabe, Ereignisse
Applets schreiben und einsetzen, Appletmethoden
Zeichnen mit der Klasse Graphics, Bilder, Farben und Zeichensätze einsetzen
AudioClips abspielen und MediaTracker einsetzen
Das Delegation Event Modell am Beispiel von Maus- und Tastaturereignissen
VI. Graphische Benutzeroberflächen mit dem AWT
-
Das Abstract Windowing Toolkit und seine Funktionsweise
Bausteine graphischer Oberflächen: Container, Komponenten und Layout-Manager
Fenster und Menüs
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
-
Arbeiten mit Ein- und Ausgabeströmen, Zugriff auf Dateien und Verzeichnisse
Netzwerkfunktionalität von Java
Einblicke in fortgeschrittene Techniken:
Datenbankzugriffe mit JDBC, Grafische Oberflächen mit Swing, Java Servlets
HRZ Einführungspraktikum Java
3
4
HRZ Einführungspraktikum Java
4
5
I.
Einführung
und erste Schritte
mit Java
HRZ Einführungspraktikum Java
5
I. Einführung und erste Schritte mit Java
6
1. Entstehung von Java
 1991 Gründung des "Green Project" bei Sun Microsystem: Schaffung einer einfachen,
objektorientierten Programmiersprache für Steuerungselektronik im Consumerbereich.
Plattformunabhängigkeit und Stabilität spielen eine große Rolle.
 Das Resultat heißt "Oak". Sun gründet 1992 First Person, Inc. zur Vermarktung. Es
entsteht ein tragbares Gerät mit dem Namen "*7" (Star seven), das über einen animierten
"Assistenten" mit dem Namen "Duke" verfügt und eine Art Universalfernbedienung für
Haushaltselektronik realisiert.
 Viele Verhandlungen, z. B. im Bereich Set-Top-Boxen, scheitern. Oak findet noch keinen
Markt. Im Frühjahr 1994 wird First Person, Inc. aufgelöst.
 Im Juni 1993 wird die erste brauchbare Version eines Browsers für das World Wide Web
mit dem Namen Mosaic bekannt. Das WWW verbreitet sich von nun an rasant.
 Ende 1994 kommt bei Sun die Idee auf, Oak als freie Programmiersprache für das World
Wide Web umzuarbeiten. Ein einfacher Browser namens "WebRunner" kann im Herbst
1994 bereits kleine Oak-Applets ausführen.
 Anfang 1995 wird der Name "Java" gewählt, nach einer im Silicon Valley auch unter den
Sun-Programmierern beliebte starke Bohnenkaffee-Sorte. Es wird viel Arbeit in die
Bereiche Netzwerkfähigkeit und Sicherheit von Java gesteckt: Aus Oak wurde Java.
 Im März 1995 entdeckt Netscape-Gründer Marc Andreessen das Java-Projekt. Im
Dezember 1995 ist die Netscape-Version 2.0 mit integrierter Java-Unterstützung
verfügbar. Java Applets werden als erste Möglichkeit zur Realisierung dynamischer WebSeiten schnell populär.
 Im Frühjahr 1996 ist die erste Beta-Version des Java Development Kit (JDK) 1.0 im
Internet frei erhältlich. Die kostenlose Java-Entwicklungsumgebung trägt erheblich zur
schnellen Verbreitung der Programmiersprache bei.
2. Java heute
 Inzwischen ist Java als ernstzunehmende objektorientierte Programmiersprache etabliert
und für nahezu alle gängigen Plattformen in aktuellen Versionen verfügbar.
 Auf der Client-Seite (Java Applets) hat Java in letzter Zeit deutlich an Bedeutung
verloren. Wesentlicher Grund hierfür ist die mangelnde Browser-Unterstützung im
Netscape Navigator und Internet-Explorer, die beide die aktuellsten Java-Versionen nur
mit einem separat zu installierenden Java Plug-in von Sun unterstützen.
 Auf der Server-Seite hat sich Java deutlich stärker etabliert. Java Servlets und Java
Server Pages lösen CGI-Anwendungen ab. Mächtige Klassenbibliotheken unterstützen
aktuelle Standards, insbesondere Datenbankzugriffe mit JDBC, XML, LDAP, IMAP /
POP3.
 Mit der Java 2 Micro Edition kehrt Java zu den ursprünglichen Anwendungsgebieten
von Oak zurück. Es gibt Java-Umgebungen für Palm-Handhelds und ein erstes Javafähiges Handy von Motorola. Java verbreitet sich ebenfalls stark als System zur
Programmierung von Chip-Karten (JavaCard).
HRZ Einführungspraktikum Java
6
I. Einführung und erste Schritte mit Java
7
3. Die Plattformunabhängigkeit von Java
 Java-Quellcode besteht aus Dateien mit der Endung "*.java". Dieser Quellcode wird
durch einen Compiler übersetzt.
 Es entsteht kein ausführbares Programm, sondern Java Bytecode mit der Endung
"*.class". Der Bytecode stellt eine plattformunabhängige, vorkompilierte Form des
Java-Codes dar.
 Er besteht aus einfachen, mit Maschinensprache vergleichbaren Anweisungen für einen
virtuellen Computer, der Java Virtual Machine. Die Funktionsweise der Java Virtual
Machine und der Bytecode-Anweisungen, die sie zu verarbeiten hat, ist genau definiert.
Anbieter, die ihr System Java-fähig machen wollen, müssen eine entsprechende Virtual
Machine für die jeweilige Plattform implementieren.
 Java Bytecode wird durch die Java Virtual Machine ausgeführt. Diese kann als
eigenständiges Programm ausgelegt sein (z. B. java im JDK), Bestandteil eines WebBrowsers sein (z. B. integriert im Netscape Navigator) oder in Zukunft als Hardware in
Form eines Prozessors z. B. in einer Waschmaschine existieren.
 Die Virtual Machine ist nicht nur ein virtueller Prozessor, sondern bietet auch eine
virtuelle Betriebssystem-Umgebung nach, z. B. um Zugriffe auf Dateien und
Verzeichnisse, das Fenstersystem der Plattform oder das Netzwerk zu ermöglichen. Die
Virtual Machine kontrolliert die Zugriffe auf diese Ressourcen, was differenzierte
Sicherheitsmechanismen ermöglicht.
 Der Sprachumfang des Java Bytecodes ist sehr gering. Er wird ergänzt durch eine
Sammlung von Java-Klassenbibliotheken (Standard-Packages), die wiederum größtenteils
in Java geschrieben sind und auf dem jeweiligen Laufzeitsystem der Virtual Machine
vorausgesetzt werden können.
Java-Quellcode *.java
Compiler
Java-Bytecode *.class
Java
Runtime
Environment
(java)
Java
Virtual
Machine
HRZ Einführungspraktikum Java
Javaenabled
Web-Browser
( Netscape, IE )
Java
Virtual
Machine
7
I. Einführung und erste Schritte mit Java
8
4. Wichtige Eigenschaften von Java
 Java ist streng genommen eine interpretierte Sprache. Übersetzte Java-Programme
werden von einem Interpreter, der Java Virtual Machine, ausgeführt. Neuere JVMs
verbessern allerdings inzwischen mit integriertem Just-in-Time-Compiler und dem HotSpot-Konzept die Performance gegenüber reinen Java-Interpretern erheblich.
 Java ist plattformunabhängig. Java-Anwendungen, die in 100 % reinem Java
geschrieben sind, laufen ohne jegliche Veränderung auf allen Systemen, für die eine JavaLaufzeitumgebung zur Verfügung steht.
 Java ist durchgehend objektorientiert. Java-Code besteht aus Klassen, in denen
Variablen und Methoden definiert sind. Objektorientierte Konzepte wie Vererbung,
Overloading und Overriding werden unterstützt.
 Java ist relativ einfach zu erlernen. Java lehnt sich stark an C++ an, besitzt jedoch keine
Zeiger und keine Mehrfachvererbung. Java ist recht übersichtlich strukturiert und hat eine
einfache Syntax, daher weniger schwerverständlicher Code als z.B. in Perl oder C. Da
Java neu entworfen wurde, gibt es weniger Altlasten als z. B.in C++.
 Java arbeitet in einer virtuellen Betriebssystemumgebung. Plattformunabhängige JavaAnwendungen laufen in einer plattformabhängigen Java Virtual Machine, die die Aufrufe
des Java-Programms auf Aufrufe des jeweiligen Systems abbildet, z .B. den Zugriff auf
Dateien.
 Java bietet integrierte Sicherheitsmechanismen. Die Java Virtual Machine überwacht
zur Laufzeit den Zugriff auf das System und verhindert z. B., daß aus dem Netz geladene
Java-Applets lokale Daten lesen können.
 Java ist robust. Laufzeitfehler können hierarchisch auf verschiedenen Ebenen vom
Programmierer abgefangen, weitergeleitet oder selbst erzeugt werden.
 Java ist streng typisiert. Die Verwendung der Datentypen wird zur Übersetzungszeit
genau überprüft. Der Wertebereich von Datentypen ist plattformübergreifend einheitlich
definiert.
 Java ist multithreadingfähig. Java bietet Konstrukte, um in einer Anwendung
verschiedene Teile parallel ausführen zu können.
 Java besitzt keine Mechanismen, um direkt auf Hardware, z. B. eine bestimmte
Speicheradresse, zuzugreifen.
 Java verwaltet eigenständig den Arbeitsspeicher. Eine Garbage Collection wird von
Java regelmäßig automatisch angestoßen, um den Speicher von nicht mehr benutzten
Objekten zu säubern. Der Programmierer muß seine Objekte nicht mehr explizit
freigeben.
 Java bietet eine integrierte Netzwerkunterstützung mit Klassen für Datenströme, URLs,
Sockets etc zur Kommunikation auf der Basis der TCP/IP und UDP-Protokollfamilie.
 Java-Anwendungen sind klein. Das Java-Laufzeitsystem belegt nur einige hundert
KByte. Da die Java-Bibliotheken auf dem Client vorausgesetzt werden können, müssen
sie nicht zum übersetzten Programm dazugebunden werden. Die übertragene Datenmenge
für ein einfaches Java-Applet ist daher vergleichsweise gering.
 Das Java 2 Software Development Kit und inzwischen auch integrierte graphische
Entwicklungsumgebungen sind frei verfügbar, jedoch liegen das Copyright und alle
Rechte an Java bei Sun Microsystems. Java ist also kein offener Standard, sondern ein
herstellerabhängiges Produkt!
HRZ Einführungspraktikum Java
8
I. Einführung und erste Schritte mit Java
9
5. Literatur und Software zu Java
5.1 Empfehlenswerte Literatur für Einsteiger
 Guido Krüger: Go To Java 2,
Handbuch der Java-Programmierung
Addison-Wesley, ISBN: 382731710X, DM 99,90
Gebundene Ausgabe - 1207 Seiten
 Bruce Eckel: Thinking in Java,
Prentice Hall; ISBN: 0130273635, ca. DM 100,-,
Taschenbuch kartoniert - 1128 Seiten
5.2 Literatur online und zum Download als HTML oder PDF
 Sun: The Java Tutorial - A practical guide for programmers:
http://www.javasoft.com/docs/books/tutorial/
 Gosling, James; Joy, Bill; Stelle, Guy: The Java Language Specification:
http://www.javasoft.com/docs/books/jls/index.html
 Eckel, Bruce: Thinking in Java:
http://www.bruceeckel.com/
 Krüger, Guido: Go To Java 2:
http://www.javabuch.de/
5.3 Java-Entwicklungsumgebungen
 http://www.javasoft.com/j2se/
Das Java 2 Software Development Kit, Standard Edition, Version 1.3.1 ist eine reine
Kommandozeilen-Umgebung zum Compilieren und Ausführen von Java-Anwendungen
und wird von Sun zum freien Download für Windows, Linux und Solaris angeboten.
 http://www.jcreator.com/
JCreator ist eine graphische Entwicklungsumgebung (IDE) für Java, von der es auch eine
kostenlose Freeware-Version (JCreator LE 2.0) gibt. Der Funktionsumfang beschränkt
sich auf das Wesentliche, dafür ist das Programm aber auch schneller als Forte und
JBuilder.
 http://www.borland.com/jbuilder/personal/
Die graphische Java-Entwicklungsumgebung Borland JBuilder 5.0 steht in der Personal
Edition für Windows, Solaris und Linux frei zur Verfügung.
 http://www.sun.com/forte/ffj/
Die Java-IDE Forte for Java 3.0 ist eine weitere Alternative, die direkt von Sun
angeboten wird. Die freie Version heisst hier Community Edition und steht ebensfalls
für Windows, Solaris, Linux und als reine Java-Implementierung zur Verfügung.
HRZ Einführungspraktikum Java
9
I. Einführung und erste Schritte mit Java
10
6. Das Java 2 SDK und Java-Versionen
6.1 JDK (Java Development Kit) bzw. SDK (Software Development Kit)
 Frei verfügbares Entwicklungssystem für Java, beinhaltet den Java-Compiler javac, den
Java-Interpreter java zum Ausführen von Java-Applikationen, den appletviewer
zum Ausführen von Java-Applets und weitere Tools
 Beinhaltet die Standard-Klassenbibliothek von Java inkl. Dokumentation und Quellcode
 Keine graphische Entwickler-Oberfläche, nur Kommandozeilen-Tools
 Windows-, Solaris- und Linux-Versionen werden von Sun entwickelt, weitere Versionen
durch Drittanbieter portiert, z. B. von Apple für Mac, von IBM für AIX usw.
 Funktion eines Referenzsystems für den aktuellen Sprachumfang
6.2 Java-Versionen und Editionen
 Der aktuelle Sprachumfang von Java wird durch die Versionen des Java Development
Kit (JDK/SDK) festgelegt. Die dritte Stelle der Versionsnummern dokumentiert den Stand
von Bugfixes etc., aber keine Erweiterungen des Standard-Sprachumfangs:
 Java 1 und JDK 1.0.2: Wird von allen Java-fähigen Web-Browsern und Plattformen
unterstützt, aus praktischer Sicht derzeit oft noch die wichtigste Java-Version für die
Entwicklung von Java-Applets, die auf möglichst allen Browsern laufen sollen.
 Java 1.1 und JDK 1.1.8: Wird in vollem Umfang nur von den neuesten Browsern
unterstützt, z .B. Netscape Communicator 4.7. Wesentliche Verbesserungen in
Funktionalität (z. B. JDBC), Geschwindigkeit und Stabilität.
 Umbenennung des JDK nach der Version 1.1.8 in "Java 2 Software Development Kit"
(Java 2 SDK). Der aktuelle Sprachumfang wird auf der Browser-Seite leider kaum
unterstützt, auf der Server-Seite sind aktuelle Java-Versionen verfügbar. Netscape 6 ist
derzeit der einzige Browser, der von der Installation an eine Java 2 Umgebung bieten
kann. Andere Browser erfordern die separate Installation des Java Plug-in und spezielle
HTML-Seiten zum Starten eines Applets mit diesem Plug-in.
 Aktuellste Versionen: Java 2 SDK 1.2.2 und 1.3.1. Version 1.4 befindet sich derzeit im
Beta-Stadium.
 Alle aktuellen Java-Entwicklungsumgebungen und Standard-Bibliotheken sind Teil der
"Java 2 Platform". In dieser werden nun verschiedene Editionen unterschieden:
 Java 2 Standard Edition:
Entwicklung von Applets und Applikationen für Desktop-Clients / PC
Gegenstand dieses Kurses
 Java 2 Enterprise Edition:
Erweiterung der Standard Edition um zusätzliche Bibliotheken und standardisierte
Schnittstellen, z. B. XML, Servlets/JSP, EMail, Verzeichnisdienste, Enterprise Java Beans
Einsatz in Application Servern
 Java 2 Micro Edition:
Eingeschränkter Sprachumfang, spezielle Entwicklungsumgebungen
Spezialisierung auf Kleingeräte wie PDAs (Palm), Handys etc.
HRZ Einführungspraktikum Java
10
I. Einführung und erste Schritte mit Java
11
7. Erste Schritte mit dem JDK bzw. SDK
 Welche Java-Version ist installiert?
java –version
 Wie compiliert man eine Quellcode-Datei?
javac HelloWorld.java
Es entsteht eine Datei HelloWorld.class.
 Wie führt man eine Java Application aus?
java HelloWorld
 Wie führt man ein Java Applet aus?
... durch Laden der HTML-Seite im Browser, die das Java Applet einbindet und aufruft!
 Die Umgebungsvariable CLASSPATH enthält eine Liste von Verzeichnissen, in denen die
Java Laufzeitumgebung nach Class-Dateien sucht. Werden class-Dateien nicht gefunden,
überprüfen Sie diese Variable und erweitern Sie sie gegebenenfalls, z. B. für Unix
export CLASSPATH=.:~hrz120/myprojects/classes:$CLASSPATH
 Zusammengehörende Java-Class-Dateien einer Klassenbibliothek sind oft in einer JarDatei (Java Archive) zusammengefasst. Java Laufzeitumgebungen können Jar- und ZipDateien wie Verzeichnisse nach Class-Dateien durchsuchen. Jar- und Zip-Dateien werden
wie Verzeichnisse im CLASSPATH eingetragen:
export CLASSPATH=$CLASSPATH:/x/y/swingall.jar:/x/y/other.jar
 Jar-Dateien können mit dem Kommandozeilen-Tool jar bearbeitet werden, dessen
Aufrufsyntax vom tar-Kommando übernommen ist:
jar –vtf demo.jar
zeigt den Inhalt einer Jar-Datei
jar –xvf demo.jar
packt den Inhalt einer Jar-Datei aus.
jar –cvf demo.jar *
erzeugt eine Jar-Datei mit allen Class-Dateien aus dem aktuellen Verzeichnis.
HRZ Einführungspraktikum Java
11
I. Einführung und erste Schritte mit Java
12
8. Applets und Applications
 Java-Programme können in zwei verschiedenen Formen auftreten:
 Applications sind Java-Anwendungen, die wie gewöhnliche Anwendungen (d. h.
ohne einen WWW-Browser) gestartet werden. Dazu benötigt man ein JavaLaufzeitsystem, das die Java-Applikation dann ausführt.
 Applets sind Java-Anwendungen, die in eine HTML-Seite eingebunden sind und mit
dieser aus dem WWW heruntergeladen werden. Java-fähige Webbrowser führen dann
das Applet aus und stellen es als Teil der WWW-Seite dar, sobald alle Bestandteile
heruntergeladen wurden.
 Java Beans und Java Servlets sind weitere Erscheinungsformen von Java-Anwendungen.
8.1 Eine einfache Java-Application: HelloWorld.java
public class HelloWorld
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
Beachte:
 Java ist durchgehend objektorientiert, d. h. in Java gibt es auf der obersten Ebene nur
Klassen. Auch eine Java-Anwendung besteht also mindestens aus einer Klasse. Mehr zu
Klassen und Objektorientierung später.
 Der Dateiname muß exakt mit dem Klassennamen übereinstimmen (Hier also
"HelloWorld.java" ).
 Jede (public-) Java-Klasse muß in einer eigenen Datei angegeben werden.
 Java-Applikationen müssen eine Methode main besitzen, die automatisch vom
Laufzeitsystem aufgerufen wird, wenn man ihm diese Java-Klasse zur Ausführung
übergibt. Mehr zu Methoden später.
 Die Methode main muß public und static deklariert sein
 String[] args ist ein Feld (Array) aus Zeichenketten, das eventuell mit dem Aufruf
übergebenen Parameter aus der Kommandozeile aufnimmt.
 System.out ist ein Objekt, das den Standard-Ausgabestrom des Systems darstellt (also
z. B. den Bildschirm oder die Java Console im Netscape Navigator)
 System.out besitzt eine Methode println, mit der man Zeichenketten auf dem
Bildschirm ausgeben kann. Hier wird also die Zeichenkette "Hello World!"
ausgegeben.
 Groß- und Kleinschreibung werden in Java genauestens unterschieden!
 Leerzeichen, Tabulatoren, Leerzeilen usw. werden von Java wie einfache Leerzeichen
behandelt und können zur Strukturierung des Codes verwendet werden.
HRZ Einführungspraktikum Java
12
I. Einführung und erste Schritte mit Java
13
8.2 Ein einfaches Java-Applet: HelloWorldApplet.java
import java.applet.Applet;
import java.awt.Graphics;
public class HelloWorldApplet
extends Applet
{
public void paint( Graphics g )
{
g.drawString( "Hello World!", 20, 25 );
}
}
Hinweise:
 Der Dateiname dieses Quellcodes muß "HelloWorldApplet.java" lauten
 Mit der Anweisung import werden dem Java-System Sprachbestandteile
bekanntgemacht, die nicht standardmäßig geladen sind. Hier werden die Klassen Applet
und Graphics aus den Paketen java.applet und java.awt geladen.
Standardmäßig sind nur die Klassen aus dem Paket java.lang bekannt. Mehr zu
Packages später!
 extends Applet teilt Java mit, daß diese Klasse von der Klasse Applet abgeleitet
ist, daß es sich also um ein Applet handelt. Mehr zu Vererbung später!
 Wenn Java-Applets, die in eine Webseite eingebunden wurden, geladen sind, ruft der
Browser automatisch die Methode paint auf, um den Bereich des Applets auf dieser
Seite zu "bemalen".
 Das System übergibt der Methode paint ein Objekt vom Typ Graphics, das die
"Malfläche" repräsentiert.
 Das Objekt Graphics besitzt eine Methode drawString, um an den angegebenen
Koordinaten eine Zeichenkette auszugeben.
HRZ Einführungspraktikum Java
13
I. Einführung und erste Schritte mit Java
14
8.3 Aufruf eines Applets
 Java-Applets werden in eine HTML-Seite eingebunden und dann automatisch als Teil der
Seite durch einen Java-fähigen Browser gestartet und angezeigt:
Datei applet.html:
<HTML>
<HEAD>
<TITLE> Ein einfaches Beispiel </TITLE>
</HEAD>
<BODY>
<H1>
Auf dieser Seite sehen Sie das Applet HelloWorld
</H1>
Etwas Text.<P>
<APPLET CODE
= "HelloWorldApplet.class"
WIDTH = 100
HEIGHT = 50
>
</APPLET>
Noch etwas Text.<P>
</BODY>
</HTML>
Beachte:
 Der Name der HTML-Seite ist unabhängig vom Namen des Applets.
 Eine HTML-Seite kann mehrere Applets gleichzeitig beinhalten.
 Das Applet wird durch das HTML-Tag <APPLET> aufgerufen und erscheint dann an
dieser Stelle auf der Seite. Mehr dazu später!
 Die CODE-Anweisung teilt dem Webbrowser mit, welche Klassendatei er aus dem Netz
laden und ausführen muß. Beachte, daß auch hier Groß- und Kleinschreibung relevant ist!
 Die Angaben WIDTH und HEIGHT geben den Platz an, der dem Applet auf der HTMLSeite eingeräumt wird.
HRZ Einführungspraktikum Java
14
15
II.
Grundlegende
Sprachelemente
HRZ Einführungspraktikum Java
15
II. Grundlegende Sprachelemente
16
1. Anweisungen und Kommentare
1.1 Anweisungen und Anweisungsblöcke
 Anweisungen enden immer mit einem Semikolon!
 Anweisungsblöcke werden mit geschweiften Klammern gebildet.
 Anweisungsblöcke können dort verwendet werden, wo sonst nur eine einzelne Anweisung
von Java erwartet würde.
1.2 Kommentare
 Nach "//" wird der Rest der Zeile als Kommentar betrachtet
 Kommentarblöcke können durch "/* ... */" gebildet werden
 Javadoc-Kommentare sind durch "/** .. */" gekennzeichnet. Javadoc ist ein
System, das aus einem derart kommentierten Quellcode automatisch eine QuelltextDokumentation im HTML-Format erzeugen kann und ist Bestandteil des JDK von Sun.
Beispiel:
a = b + c; // Hier wird was gerechnet
/*
Das Leben ist eher kurz als lang
und wir stehen alle mittenmang.
*/
if ( a < 10 )
{
d = a * 2;
e = b + 1;
}
Beachte:
 Vorsicht beim Schachteln von Kommentaren!
/*
Das Leben ist eher kurz als lang
/*
Zeit ist ohnehin relativ,
wie Einstein schon festgestellt hat.
*/
// An dieser Stelle haben wir jetzt ein Problem!
und wir stehen alle mittenmang.
*/
HRZ Einführungspraktikum Java
16
II. Grundlegende Sprachelemente
17
2. Variablen und primitive Datentypen
2.1 Variablennamen
 Variablennamen dürfen mit einem Buchstaben, Unterstrich "_" oder Dollarzeichen "$"
beginnen.
 Groß- und Kleinschreibung wird wie überall in Java auch bei Variablennamen
unterschieden.
 Variablennamen dürfen sehr lang werden.
 Konvention ist, den ersten Buchstaben immer klein zu schreiben und folgende Worte mit
einem Großbuchstaben zu beginnen, ohne "$" und "_" zu verwenden:
boolean dieseVariableSpeichertObDiePersonVerheiratetIst;
2.2 Primitive Datentypen
Datentyp
boolean
byte
short
int
long
float
double
char
Wertebereich
true oder false
-128 bis 127
-32768 bis 32767
-231 bis +231
-263 bis +263 –1
32 Bit Gleitpunktzahl
64 Bit Gleitpunktzahl
Ein einzelnes Zeichen
Beachte:




boolean ist ein eigener Datentyp mit den Literalen true und false!
Die Wertebereiche sind auch auf verschiedenen Plattformen bei Java immer identisch!
Zeichenketten (Strings) sind in Java Objekte, kein primitiver Datentyp!
Eigene Datentypen können nicht definiert werden, jedoch eigene Objekte!
2.3 Variablen deklarieren
int
float
boolean
long
schuhgroesse;
meineGroesse;
maennlich;
meinWunschGehalt, deinWunschGehalt;
Beachte:
 Variablendeklarationen können an beliebiger Stelle innerhalb einer Methode stehen,
solange sie vor ihrer ersten Verwendung deklariert werden.
 Java kennt keine globalen Variablen.
 Java unterscheidet Klassen-, Instanz- und lokale Variablen (mehr dazu später).
HRZ Einführungspraktikum Java
17
II. Grundlegende Sprachelemente
18
2.4 Variablen initialisieren:
int
schuhgroesse = 43;
float
meineGroesse = 1.76;
boolean maennlich
= true;
int x, y, z = 5;
int x = 5, y = 5, z = 5;
// x und y nicht initialisiert!
// so ist's recht!
Beachte:
 Instanz- und Klassenvariablen bekommen default-Initialisierungen (0, false, null, '\0' ).
 Lokale Variablen sollten immer initialisiert werden.
2.5 Werte an Variablen zuweisen
int
int
y =
y =
x =
x = 5;
y;
6;
x + 3;
y = 10;
Beachte:
 Eine Zuweisung ist auch ein Ausdruck, dessen Wert der zugewiesenen Wert ist (siehe
letzte Anweisung oben)! Dies ist eine potentielle Fehlerquelle, manchmal aber auch
nützlich.
2.6 Variablen ausgeben (Beispiel)
public class Test
{
public static void main( String[] args )
{
int x = 5;
double d = 10.357;
System.out.println( x );
System.out.println( "x = " + x + " und d = " + d );
}
}
HRZ Einführungspraktikum Java
18
II. Grundlegende Sprachelemente
19
3. Literale
int
long
int
int
x
y
z
a
=
=
=
=
4;
4L;
0xC000; // hexadezimale Angabe mit 0x
0777;
// oktale Angabe mit führender Null
double d = 1.23;
float f = 1.23F;
double e = 1E-4; // 0.0001
boolean wahr
= true;
boolean falsch = false;
char c = 'c';
char newline = '\n';
Zeichenliteral
\n
\t
\b
\r
\f
\\
\'
\"
\777
\xC000
\u1234
Beschreibung
newline
tab
backspace
return
formfeed
\
'
"
Oktale Angabe
Hexadezimale Angabe
Unicode-Zeichensatz
String undefinierterString = null;
String einTitel
= "Programmieren mit Java";
String leererString = "";
String text
=
"In M\u00fnchen sagt man \"O’zapft is!\"";
\\ In München sagt man "O’zapft is!"
Beachte:
 Zeichen und Zeichenketten werden in Java im 16-Bit-Unicode-Format verarbeitet und
gespeichert. Das bedeutet, daß Sie z. B. auch hebräische oder andere Schriftzeichen bei
der Ein- und Ausgabe von Datenströmen verwenden können.
 Die Verwendung von Unicode-Zeichen erfolgt mit \u (siehe oben), gefolgt vom
Zahlencode des entsprechenden Zeichens.
 Ob die korrekte Ausgabe aller Unicode-Zeichen jedoch möglich ist, hängt vom
Laufzeitsystem und den dort verfügbaren Zeichensätzen ab.
Umlaut
Unicode
Ä
\u00c4
ä
\u00e4
HRZ Einführungspraktikum Java
Ö
\u00d6
ö
\u00f6
Ü
\u00dc
ü
\u00fc
ß
\00df
19
II. Grundlegende Sprachelemente
20
4. Operatoren
4.1 Arithmetische Operatoren
x
y
z
i
=
=
=
=
5 + 2;
3 – 2;
4 * 8 / 2;
47 % 11
// Modulo-Rest der Division: i = 3
4.2 Inkrementieren und Dekrementieren
x = 1;
x++;
y = x++;
// x = 1
// x = 2
// y = 2, x = 3
Postfix-Notation
x = 1;
y = ++x;
// x = 1
// y = 2, x = 2
Prefix-Notation
 Analog arbeitet der Operator --.
4.3 Bitweise Operatoren
&
|
^
~
<<
>>
>>>
AND
OR
XOR
Komplementbildung
Linksschieben
Rechtsschieben
Rechtsschieben, mit Null füllen
4.4 Zuweisungsoperatoren
a = b = c = d = 5;
a
b
c
d
e
+=
-=
*=
/=
%=
2;
3;
4;
5;
2;
//
//
//
//
//
a
b
c
d
e
=
=
=
=
=
a
b
c
d
e
// a = ( b = ( c = ( d = 5 ) ) );
+
–
*
/
%
2;
3;
4;
5;
2;
 Analog arbeiten die Operatoren <<=, >>=, &=, |=, ^=
HRZ Einführungspraktikum Java
20
II. Grundlegende Sprachelemente
21
4.5 Logische Operatoren
&
|
^
!
&&
||
AND
OR
XOR
NOT
Beachte:
 Bei Verwendung der Form
if ( AusdruckA & AusdruckB )
werden beide Ausdrücke ausgewertet und dann das Ergebnis gebildet.
 Bei Verwendung der Form
if ( AusdruckA && AusdruckB )
wird zunächst AusdruckA ausgewertet. Wenn daraus allein schon das Endergebnis
feststeht, wird AusdruckB nicht weiter beachtet.
4.6 Vergleichsoperatoren
==
!=
<
>
<=
>=
gleich
ungleich
kleiner als
größer als
kleiner oder gleich
größer oder gleich
Beachte:
 Zuweisungen mit =, Vergleiche mit ==
 Häufiger Fehler, da Zuweisung auch als Wert interpretiert wird:
boolean result = false;
if( result = true ) ...
// ist immer wahr
-> result wird true zugewiesen, dann erst Vergleich! Abhilfe:
if( true == result ) ... (Compiler würde meckern) oder if( result )...
 Bei Vergleich zwischen Objekten wird auf Identität geprüft, nicht auf inhaltliche
Gleichheit:
GregorianCalendar a = new GregorianCalendar( 2001, 5, 17 );
GregorianCalendar b = new GregorianCalendar( 2001, 5, 17 );
GregorianCalendar c = a;
if ( a == b ) ...
// false
if ( a.equals( b ) )... // true ( Inhaltlicher Vergleich )
if ( a == c ) ...
// true ( Identität )
HRZ Einführungspraktikum Java
21
II. Grundlegende Sprachelemente
22
5. Arrays





Ein Feld (Array) speichert eine Liste von Werten
Die Werte müssen alle vom gleichen Typ sein
Der Typ ist ein beliebiger Objekttyp oder einfacher Datentyp
Auf die Elemente kann über die Nummer (Index) des Elementes zugegriffen werden
Die Größe des Arrays ist nicht variabel.
5.1 Deklarieren von Arrays
int[] preise;
String[] artikelNamen;
5.2 Erzeugen von Arrays
preise = new int[ 10 ];
String[] artikelNamen = new String[ 10 ];
Beachte:
 Der Wert in den eckigen Klammern gibt die Anzahl der Elemente, nicht den höchsten
Indexwert an!
5.3 Initialisieren von Arrays:
String[] namen = { "Claudia", "Simone", "Eva" };
Hinweis:
 Array-Elemente werden default mit ( 0, false, '\0', null ) initialisiert.
5.4 Zugriff auf Array-Elemente:
String[] namen = { "Claudia", "Simone", "Eva" };
namen[ 2 ] = "Marlene";
System.out.println( namen[ 0 ] ); // gibt "Claudia" aus
Beachte:
 Das erste Element hat den Index Null!
5.5 Größe von Arrays feststellen:
 Die Größe eines Arrays läßt sich mit length prüfen:
String[] namen = { "Claudia", "Simone", "Eva" };
int drei = namen.length;
HRZ Einführungspraktikum Java
22
II. Grundlegende Sprachelemente
23
Beachte:
 Häufiger Schreibfehler: length ist keine Methode!
String
String[]
int i1 =
int i2 =
a1 = "The quick brown fox jumps over the lazy dog.";
a2 = { "Claudia", "Simone", "Eva" };
a1.length();
a2.length;
// !!!
5.6 Mehrdimensionale Arrays
 In Java gibt es keine mehrdimensionalen Arrays, aber Arrays aus Arrays sind möglich:
int[]
werte1 = new int[ 2, 3 ]
// geht nicht!
int[][] werte2 = new int[ 2 ][ 3 ] // geht!
werte[ 2 ][ 1 ] = 4711;
5.7 Arrays kopieren
 Arrays lassen sich mit der Methode arraycopy aus dem Paket System kopieren:
System.arraycopy( Quelle, QStart, Ziel, ZStart, Anzahl );
Beispiel:
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[ 5 ];
b[ 0 ] = 9;
b[ 1 ] = 10;
System.arraycopy( a, 1, b, 2, 3 );
// b = { 9, 10, 2, 3, 4 }
Beachte:
 In Java können Methoden auch beliebige Arrays von Objekten übergeben werden oder sie
können solche erzeugen: public String[] getNames() { ... }
 Die Klasse Vector aus dem Paket java.util ermöglicht Arrays variabler Größe, bei
denen die Elemente auch verschiedenen Typs sein können.
 Arrays werden wie Objekte als Referenz übergeben! Dies ist unbedingt zu beachten, wenn
man z. B. ein Array bei einem Methodenaufruf übergibt: Manipulationen des Arrays
innerhalb der Methode wirken sich dann auch auf die aufrufende Umgebung aus!
HRZ Einführungspraktikum Java
23
II. Grundlegende Sprachelemente
24
6. Fallunterscheidungen
6.1 if-Anweisung
if( Bedingung )
AnweisungA;
else
AnweisungB;
if(Bedingung )
{
AnweisungenA
}
else
{
AnweisungenB
}
 Wenn die Bedingung erfüllt ist, wird der erste Anweisungsblock ausgeführt, sonst der
zweite.
 Für Bedingung kann ein Vergleich, eine boolesche Variable oder ein Methodenaufruf
verwendet werden, der einen boolean-Wert zurückgibt.
Beachte:
 Auch wenn der if-Teil nur aus einer Anweisung besteht, kommt vor dem else-Teil ein
Semikolon!
Beispiel:
if ( x < 5 ) System.out.println( "X ist kleiner als fünf" );
if ( y > 4 )
{
a = y * 3 + 7;
b = y + 2 - a;
} else b = y + 1;
Hinweis:
Betrachte folgenden Fall:
if ( x < 5 )
if ( x > 2 )
System.out.println( "2 < x < 5" );
else
System.out.println( "x <= 2" );
Dieser Fall wird in der Literatur als "Dangling Else" bezeichnet. Java ordnet hier ein else
immer dem letzten if zu. Ein abweichendes Verhalten läßt sich durch entsprechende
Klammerung erreichen:
if ( x < 5 )
{ if ( x > 2 ) System.out.println( "2 < x < 5" ); }
else
System.out.println( "x >= 5" );
HRZ Einführungspraktikum Java
24
II. Grundlegende Sprachelemente
25
6.2 Bedingungsoperator
( Bedingung ? WertA : WertB )
 Wenn die Bedingung erfüllt ist, hat dieser Ausdruck den WertA, sonst den WertB.
Beispiel:
int x = 5;
int y = 8;
int maximum = ( x > y ? x : y );
// maximum ist jetzt 8
Tip für später:
 Dieser Operator kann z. B. eine "NullPointerException" (Laufzeitfehler) verhindern:
System.out.println( ( name == null ? "" : name ).length() );
6.3 switch-Anweisung
switch ( Ausdruck )
{
case Wert1:
Anweisung1;
break;
case Wert2:
Anweisung2;
break;
default:
Anweisung3;
}
if ( Ausdruck == Wert1 )
Anweisung1;
else if ( Ausdruck == Wert2 )
Anweisung2;
else
Anweisung3;
 Die switch-Anweisung verhindert "else-if-Orgien" und das Wiederholen des
Ausdrucks
 Der default-Teil wird ausgeführt, wenn keine der case-Fälle zutrifft. Er kann auch
wegfallen.
Beachte:
 Ausdruck darf nur ein primitiver Datentyp sein, dessen Casting nach int möglich ist, also
z. B. long, int, char etc., nicht aber ein String!
 Ohne die Anweisung break; werden die folgenden Blöcke ebenfalls ausgeführt, bis zum
nächsten break; (Potentielle Fehlerquelle).
HRZ Einführungspraktikum Java
25
II. Grundlegende Sprachelemente
26
Beispiel:
public class Test
{
public static void main( String[] args )
{
char x = args[ 0 ].charAt( 0 );
// ersten Buschstaben des ersten Parameters ermitteln
switch ( x )
{
case 'a':
case 'b':
System.out.println("Das Zeichen ist ein a oder b");
break;
case 'c':
System.out.println("Das Zeichen ist ein c");
case 'd':
System.out.println("Das Zeichen ist ein c oder d");
break;
default:
System.out.println("Kein a, b, c oder d");
}
}
}
Aufruf:
java Test c
Ausgabe:
Das Zeichen ist ein c
Das Zeichen ist ein c oder d
HRZ Einführungspraktikum Java
26
II. Grundlegende Sprachelemente
27
7. Schleifen
7.1 for-Schleifen
for( Initialisierung; Bedingung; Inkrement )
{
Anweisungen
}
 Die Anweisung Initialisierung wird vor dem ersten Eintritt in den Schleifenblock
ausgeführt.
 Die Anweisung Inkrement wird nach jedem Durchlauf des Schleifenblock ausgeführt.
 Vor jedem Durchlauf wird die Bedingung geprüft und, falls diese erfüllt ist, ein
nochmaliger Durchlauf gestartet.
Beispiel:
for( int i = 0; i < 3; i++ )
{
System.out.println( "Die Variable i hat den Wert " + i );
}
Hinweis:
 In der Anweisung Initialisierung deklarierte Variablen sind nur lokal im Schleifenblock
bekannt.
 Der Schleifenblock kann bei allen Schleifenarten auch nur aus einer einzelnen Anweisung
ohne geschweifte Klammern bestehen
 Alle Elemente der Schleife können leer sein, wenn man sie nicht benötigt, also z. B.
for( ; Bedingung; )
{
Anweisungen
}
for( Initialisierung; Bedingung; Inkrement );
Beachte:
 Ein häufiger Fehler ist ein versehentliches Semikolon hinter der Klammer:
for ( i = 0; i < 10; i++ );
System.out.println( "Oh, oh, bin nicht in der Schleife!" );
HRZ Einführungspraktikum Java
27
II. Grundlegende Sprachelemente
28
7.2 while-Schleifen
while( Bedingung )
{
Anweisungen
}
 Vor jedem Schleifendurchlauf wird die Bedingung geprüft, auch vor dem ersten Eintritt in
die Schleife
Beispiel:
int x = 20, y = 30;
while ( Math.abs( x - y ) < 100 ) // Solange Differenz < 100
{
System.out.println( "x=" + x + ", y=" + y );
x -= 10;
y += 5;
}
7.3 do-while-Schleifen
do
{
Anweisungen
}
while( Bedingung );
 Die Schleife wird mindestens einmal durchlaufen.
 Nach jedem Durchlauf wird die Bedingung geprüft und ggf. die Schleife verlassen.
Beispiel:
int x = 0;
do
{
x = x * 2 + 1;
System.out.println( x );
}
while( x < 100 );
HRZ Einführungspraktikum Java
28
II. Grundlegende Sprachelemente
29
7.4 Schleifen unterbrechen
 Die Anweisung break; verläßt die gesamte Schleife und setzt die Programmausführung
hinter der Schleife fort ( bei verschachtelten Schleifen wird also die nächsthöhere Ebene
angesprungen)
 Die Anweisung continue; beendet nur den aktuellen Schleifendurchlauf und setzt die
Schleife mit einem neuen Durchlauf fort.
Beispiel:
for( int i = 1; i < 100; i++ )
{
if( i % 3 == 0 ) continue;
System.out.println( "i ist:
" + i
);
System.out.println( "i zum Quadrat ist:" + i * i );
}
7.5 Schleifen benennen
 Schleifen können durch ein Label gefolgt von einem Doppelpunkt benannt werden:
raushier:
for( int i = 1; i < 10; i++ )
{
while( irgendwasIstWahr )
{
tuWas();
if ( etwasSchrecklichesIstPassiert ) break raushier;
}
}
Beachte:
 Wo wir gerade bei Labeln sind: goto ist in Java ein reserviertes Schlüsselwort, wird aber
nicht verwendet!
Übung:
 Schreiben Sie ein Java-Programm, das mit Hilfe von zwei verschachtelten Schleifen alle
Zahlenpaare größer als Null ausgibt, deren Summe kleiner als fünf ist.
HRZ Einführungspraktikum Java
29
II. Grundlegende Sprachelemente
30
8. Methoden
 Methoden entsprechen den Prozeduren und Funktionen in anderen Programmiersprachen.
8.1 Methoden aufrufen
 Methoden werden über ihren Namen aufgerufen.
 Methoden gehören in der Regel zu einem Objekt. Der Name des Objektes wird dem
Namen der Methode vorangestellt, gefolgt von einem Punkt.
 Beim Aufruf kann Ihnen eine Liste von Parametern mitgegeben werden, die aus Variablen
oder Objekten besteht.
 Methoden können einen Variablenwert, ein Array, ein Objekt oder gar nichts
zurückgeben.
Beispiele:
System.out.println( "Hallo Welt!" );
...
String name = "Willi Winzig";
int anzahlZeichen = name.length();
System.out.println( name.toUpperCase() );
System.out.println( "John Doe".length() ); // Ausgabe = 8
8.2 Methoden definieren
Beispiele:
public class MethodenTest
{
public static void sagHallo()
{ System.out.println( "Hallo Welt!" ); }
public static void gruss( String name )
{ System.out.println( "Hallo " + name + "!" ); }
public static double mittelwert( double x, double y )
{
double mw = ( x + y ) / 2;
return mw;
}
public static void main( String[] args )
{
sagHallo();
gruss( "Peter" );
double x = 7.8;
double y = mittelwert( 3.5, x );
System.out.println( mittelwert( 10.2, 9.45 ) );
}
}
HRZ Einführungspraktikum Java
30
II. Grundlegende Sprachelemente
31
Allgemeine Syntax einer Methodendeklaration:
Modifier Rückgabetyp Methodenname( Parameterliste )
{
Anweisungen
}
 Rückgabetyp legt den Datentyp fest, der nach Beendigung der Methode von dieser
zurückgegeben wird. Methoden, die nichts zurückgeben, bekommen den Datentyp void.
 Methoden können auch Arrays oder Objekte zurückgeben
 Methoden ohne Rückgabe (void) heißen in anderen Programmiersprachen oft
"Prozeduren".
 Methoden mit Rückgabe heißen in anderen Programmiersprachen oft "Funktionen".
 Parameterliste ist die Liste der Parameter, die der Methode mit übergeben werden,
jeweils mit der Angabe des Datentyps und einem Variablennamen, getrennt durch
Kommata.
 Die Parameterliste kann leer sein, die Klammern sind unbedingt anzugeben!
 Mit der Anweisung return wird die Methode verlassen und ein Wert zurückgegeben.
 Bei void-Methoden wird die return-Anweisung weggelassen.
 Methoden können in Java 1.0 nur innerhalb einer Klasse und außerhalb jeder anderen
Methode deklariert werden. Ab Java 1.1 ist es mit "Inner Classes" möglich, in gewisser
Weise Klassen und Methoden innerhalb anderer Klassen und Methoden zu deklarieren
(mehr dazu später).
8.3 Parameterübergabe an Methoden, Rückgabe von Werten
 Bei einfachen Datentypen (int, double, boolean usw.) wird stets nur der Wert,
nicht die Variable an sich übergeben (call by value).
 Bei Objekten und Arrays wird eine Referenz auf das Objekt, also an sich das Objekt selbst
unter einem neuen Namen, übergeben (call by reference).
 Gleiches gilt für einen eventuell von der Methode zurückgegebenen return-Wert.
Beispiel:
public class Verdoppeln
{
public static int doppelt( int zahl )
{
zahl = zahl * 2; // zahl ist hier eine lokale Variable!
return zahl;
}
public static void main( String[] args )
{
int zahl = 10;
System.out.println( zahl );
System.out.println( doppelt( zahl ) );
System.out.println( zahl );
}
// 10
// 20
// 10
}
HRZ Einführungspraktikum Java
31
II. Grundlegende Sprachelemente
32
9. Arbeiten mit Zeichen und Zeichenketten
9.1 Die Klasse String
Strings erzeugen
String
String
char[]
String
// ...
a =
s =
c =
b =
und
new String();
"Mein Name ist Hase.";
{ 'T', 'i', 'n', 'a' };
new String( c );
weitere Konstruktoren
Länge eines Strings
String s = "Mein Name ist Hase.";
int l = s.length(); // l = 19
Suchen in Strings
String s = "Mein Name ist in Namibia bekannt.";
int i = s.indexOf( "Nam" );
// i = 5
int j = s.indexOf( "Hund" );
// i = -1
int k = s.lastIndexOf( "Nam" ); // k = 17
int k = s.indexOf( "Nam", 10 ) // k = 17, ab 10. Zeichen
Teile von Strings
String
char
String
String
s
c
w
y
=
=
=
=
"Mein Name ist in Namibia
s.charAt( 0 );
// c
s.substring( 5, 9 ); // w
s.substring( 17 );
// w
bekannt.";
= 'M'
= "Name", Zeichen 5 – 8
= "Namibia bekannt."
Veränderte Ausgabe von Strings
String s = "Drei Chinesen mit dem Kontrabaß";
String t =
s.replace('e','i').replace('o','i').replace('a','i');
// t = "Drii Chinisin mit dim Kintribiß"
String c = "Monica loves Bill";
String d = c.toUpperCase(); // "MONICA LOVES BILL"
String u = c.toLowerCase(); // "monica loves bill"
Beachte:
 Instanzen von String sind nicht veränderlich, d. h. obige Methoden geben einen
entsprechenden neuen String zurück, statt den alten zu verändern (Strings sind Objekte,
nicht vergessen)!
HRZ Einführungspraktikum Java
32
II. Grundlegende Sprachelemente
33
Vergleichen von Strings
String a = "Inflationsgefahr";
String b = "Inflation"+a.charAt(9)+"Gefahr".toLowerCase();
String c = "infLATionsGefaHr";
if
if
if
if
if
(
(
(
(
(
a == b ) ...
//
a.equals( b ) ) ...
//
a.equalsIgnoreCase( c ) ) ...
//
a.startsWith( "Inflation" ) ) ... //
a.endsWith( "Ende" ) ) ...
//
false !!!
true
true
true
false
String x = "Verona Feldbusch";
String y = "Morgens Aronal, abends Elmex" // Werbeeinnahmen!
boolean b = x.regionMatches( 2, y, 9, 4 ); // "rona" -> true
boolean ignoreCase = true;
b = x.regionMatches( ignoreCase, 2, "ARONAL", 1, 4 ); // true
String a1 = "Ameisenbär";
String a2 = "Braunbär";
int c = a1.compareTo( a2 );
// c < 0
// = 0 falls a1.equals( a2 )
// < 0 falls a1 lexikographisch vor a2
// > 0 falls a1 lexikographisch nach a2
Einfaches Verketten von Strings
String
String
String
String
s
t
u
v
=
=
=
=
"Eins";
"Zwei";
s + t;
s.concat( t );
Beachte:
 Viele Zeichenketten sollten besser mit Hilfe der Klasse StringBuffer verkettet
werden!!
 length() liefert die Anzahl Zeichen, nicht die letzte Indexposition im String!
 substring( von, bis ) liefert den Teilstring bis vor dem Zeichen an der Position bis!
 replace() kann nur komplett alle Vorkommen eines Zeichens ersetzen, aber keine
Teilstrings durch andere ersetzen!
 indexOf() etc. liefern bei erfolgloser Suche den Wert -1
Hinweis:
 Die Klasse String ist für statische Zeichenketten gedacht.
 StringBuffer realisieren dynamische, änderbare Zeichenketten.
HRZ Einführungspraktikum Java
33
II. Grundlegende Sprachelemente
34
9.2 Die Klasse StringBuffer
StringBuffer erzeugen
StringBuffer st = new StringBuffer();
StringBuffer st = new StringBuffer( "Ein Text" );
Variablenwerte an den StringBuffer anhängen
st.append( Variable );
 Die Methode append existiert in Varianten für boolean, char, double,
float, int, long und String
Variablenwerte in den StringBuffer einfügen
st.insert( Position, Variable );
 Die Methode insert existiert in Varianten für boolean, char, double,
float, int, long und String und fügt den Wert an der Stelle Position in
den StringBuffer ein.
Länge eines StringBuffers
StringBuffer st = new StringBuffer( "Ein kurzer Text" );
int len = st.length();
// len = 15
st.setLength( len – 10 ); // st = "Ein k"
Auf einzelne Zeichen zugreifen
StringBuffer st = new StringBuffer( "Ein kurzer Text" );
char c = st.charAt( 1 );
// c = 'i'
st.setCharAt( 13, 's' );
// "Ein kurzer Test"
StringBuffer-Inhalt umdrehen:
StringBuffer st = new StringBuffer( "Frank" );
st.reverse()
System.out.println( st.toString() ); // Ausgabe "knarF"
StringBuffer in String umwandeln
String s = st.toString();
HRZ Einführungspraktikum Java
34
II. Grundlegende Sprachelemente
35
9.3 Die Klasse Character
 Die Klasse Character ist eine sogenannte Wrapper-Klasse für den einfachen Datentyp
char (mehr zu Wrapper-Klassen später).
 Sie besitzt einige nützliche Methoden, um mit einzelnen Zeichen (Datentyp char) zu
arbeiten.
Zeichentyp bestimmen
char c = 'a';
boolean b1 = Character.isDigit( c );
// true, falls c eine Ziffer ist
boolean b2 = Character.isLetter( c );
// true, falls c ein Buchstabe ist
boolean b3 = Character.isLetterOrDigit( c );
// ...
boolean b4 = Character.isSpace( c );
// true, falls c Leerzeichen, \t, \n, \f, \r
boolean b5 = Character.isJavaLetter( c );
// true, falls isLetter( c ) oder '$' oder '_'
boolean b6 = Character.isJavaLetterOrDigit( c );
// ...
boolean b7 = Character.isLowerCase( c );
// true, falls c ein Kleinbuchstabe ist
boolean b8 = Character.isUpperCase( c );
// true, falls c ein Großbuchstabe ist
Zeichen umwandeln
char c
char d
char e
char f
String s
=
=
=
=
=
'a';
'B';
Character.toLowerCase( d ); // e = 'b'
Character.toUpperCase( c ); // f = 'A'
Character.toString( c );
// s = "a"
HRZ Einführungspraktikum Java
35
II. Grundlegende Sprachelemente
36
HRZ Einführungspraktikum Java
36
37
III.
Objektorientierte
Programmierung
mit Java
HRZ Einführungspraktikum Java
37
III. Objektorientierte Programmierung mit Java
38
1. Objekte und Klassen
Objekt
 besitzt Variablen (Attribute), die den Zustand des Objektes beschreiben.
 besitzt Methoden, über die auf das Objekt zugegriffen wird, die mit den Attributen
arbeiten und die das Verhalten des Objektes festlegen.
 dadurch Verbindung der Daten und der Prozeduren, die mit diesen Daten arbeiten.
Klasse
 Menge von gleichartigen Objekten
 Definition der Attribute und Methoden aller Objekte dieser Klasse
Instanz (engl. instance, besser übersetzt als "Exemplar")
 Zur Laufzeit gebildetes konkretes Objekt aus einer Klasse
Beispiele:
Klasse:
Attribute:
Methoden:
Instanz:
Konto
Kontostand, Kontoinhaber, Kontonummer
einzahlen, abheben, überweisen
Das Konto mit der Kontonr. 1234243
Klasse:
Attribute:
Methoden:
Instanz:
Point aus dem Paket java.awt
x, y
move, translate, ...
Der Punkt ( 10, 45 )
Beachte:
 Jedes Java-Programm besteht aus einer Sammlung von Klassen, in denen Variablen und
Methoden definiert werden
 Zur Laufzeit werden entsprechend den Anweisungen Instanzen von Objekten der Klassen
erzeugt, die gegenseitig ihre Methoden aufrufen und ihre Variablen verwenden.
Wichtige Ziele objektorientierter Programmierung:
 Anwendungssysteme als Abbildung der Objekte der realen Welt modellieren:
Objekte Produkt, Kunde, Lieferant, Rechnung, Auftrag, ...
Modellierung soll einfacher und korrekter werden
 Wiederverwendung von Code ermöglichen: Probleme nur einmal lösen!
(Objekte in verschiedenen Anwendungen nutzen, durch Vererbung spezialisieren...)
 Auswirkungen von Änderungen lokal halten, auf Objekt beschränken
(Pflegbarkeit des Codes erhöhen, Fehleranfälligkeit minimieren)
HRZ Einführungspraktikum Java
38
III. Objektorientierte Programmierung mit Java
39
2. Lebenszyklus und Verwendung von Objekten
2.1 Objekte erzeugen
 Objekte werden durch Aufruf eines Konstruktors erzeugt. Dies geschieht durch
Verwendung des Schlüsselwortes new.
GregorianCalendar heute = new GregorianCalendar();
//parameterloser “Standardkonstruktor“
GregorianCalendar damals = new GregorianCalendar(1971,3,22);
Point hier = new Point( 10, 45 );
 Konstruktoren dienen dem Erzeugen von Objekten und legen dessen Anfangszustand fest.
 Konstruktoren werden durch new Klassenname( Parameter ) aufgerufen und
geben ein Objekt dieser Klasse zurück.
2.2 Objekte verwenden
 Auf Variablen und Methoden eines Objektes wird durch Voranstellen des Objektnamens,
gefolgt von einem Punkt, zugegriffen:
import java.awt.Point;
...
Point hier = new Point( 10, 45 );
hier.translate( 2, 0 ); // verschieben um 2 nach rechts
System.out.println( "x = " + hier.x );
System.out.println( "y = " + hier.y );
hier.x = 8;
hier.y = 20;
// hier.move( 8, 20 ); täte dasselbe
System.out.println( "x = " + hier.x );
System.out.println( "y = " + hier.y );
 Objekte können als Parameter bei Methodenaufrufen übergeben werden und von
Methoden als Rückgabewert zurückgegeben werden. Dabei wird nicht eine Kopie,
sondern eine Referenz auf das Objekt übergeben, also quasi das Objekt selbst.
2.3 Objekte zerstören
 In Sprachen wie C++ ist es nötig, den von einem Objekt belegten Hauptspeicher wieder
freizugeben, wenn das Objekt nicht mehr verwendet wird.
 Java entfernt selbständig Objekte aus dem Speicher, auf die keine Referenz mehr existiert
(Garbage Collection).
 Dies geschieht verzögert in regelmäßigen Abständen, bei Speicherknappheit oder kann
manuell durch Aufruf von System.gc(); angestoßen werden.
HRZ Einführungspraktikum Java
39
III. Objektorientierte Programmierung mit Java
40
2.4 Packages verwenden
 Java-Klassen können zu Packages (Klassenbibliotheken) geordnet zusammengefaßt
werden. Die wichtigsten Standard-Packages ab JDK 1.1 lauten:
java.lang
Klassen für grundlegende Sprachbestandteile
java.math
Klassen und Arithmetik für sehr große Zahlen
java.net
Netzwerkfunktionalität: URLs, Sockets, Datagramme
java.io
Ein-/Ausgabe über Datenströme und Dateien
java.sql
Datenbankzugriffe mit Java Database Connectivity (JDBC)
java.text
Internationalisierte, formatierte Datums- und Zahlenwerte
java.applet
Basis- und Hilfsklassen für Java Applets
java.awt
Abstract Windowing Toolkit: Fenster, Schaltflächen, ...
java.awt.datatransfer
Clipboard-Funktionen des AWT
java.awt.event
Ereignisverarbeitung
java.rmi
Remote Method Invocation (RMI)
java.util
Hilfsklassen und Utilities
java.util.zip
Klassen für ZIP / GZIP Datenströme
 Klassen aus dem Paket java.lang sind ohne import-Anweisung sofort verfügbar.
Andere Klassen müssen im Kopf einer Klassendeklaration erst importiert werden:
import java.awt.Graphics;
import java.awt.*;
// Einzelne Klasse, oder aber:
// Alle Klassen aus java.awt
public class HelloWorldApplet ...
 Die import-Anweisung macht lediglich dem System die Klassennamen des Paketes
bekannt. Es werden aber nur die Klassen importiert, die zur Laufzeit auch wirklich
verwendet werden, nicht automatisch alle Klassen des Paketes!
 Unterpakete müssen einzeln importiert werden, z. B.
import java.awt.*; import java.awt.event.*;
 Alternativ kann der Name des Packages bei jeder Benutzung vorangestellt werden, z. B.:
public void paint( java.awt.Graphics g )
{ g.drawString( "Hello World", 20, 25 ); }
Beachte:
 Mit dieser Form des Klassenaufrufs kann man das Problem umgehen, das entsteht, wenn
man zwei Klassen mit dem gleichen Namen aus verschiedenen Paketen verwenden will.
 Es lassen sich eigene Packages erstellen (mehr dazu später).
 Es existiert eine Namenskonvention, die Konflikte bei Paketnamen vermeiden soll:
 Standardpakete aus dem Java-Sprachumfang beginnen mit java
 Java-Erweiterungen beginnen mit javax
 Pakete von Drittanbietern beginnen mit der Umkehrung des Domainnamens:
www.ibm.com -> Paketnamen beginnen mit com.ibm
HRZ Einführungspraktikum Java
40
III. Objektorientierte Programmierung mit Java
41
3. Eigene Klassen erstellen
3.1 Variablen, Konstruktoren und Methoden der Klasse deklarieren
 Jede (öffentliche) Klasse wird in einer eigenen Datei deklariert. Dateinamen und
Klassennamen müssen sich entsprechen (class Konto in der Datei Konto.java).
 Die Reihenfolge der Deklarationen in der Klasse spielt keine Rolle:
public class Klassenname
{
Variablendeklarationen ...
Konstruktorendeklarationen...
Methodendeklarationen ... in beliebiger Reihenfolge!
}
Beispiel:
public class Konto
{
// Attribute:
// Welche Werte beschreiben den Zustand dieses Kontos?
public String kontoInhaber;
public int
kontoStand;
public int
kontoNr;
// Konstruktor: wird aufgerufen bei "new Konto(...)"
// Was geschieht beim Erzeugen eines neuen Kontos?
public Konto( String derKontoInhaber, int dieKontoNr )
{
kontoStand
= 0;
kontoInhaber = derKontoInhaber;
kontoNr
= dieKontoNr;
}
// Methoden:
// Was kann ich mit einem Konto tun?
public void einzahlen( int betrag )
{ kontoStand += betrag; }
public void abheben( int betrag )
{ kontoStand -= betrag; }
}
 Konstruktoren sind spezielle Methoden eines Objektes, die keinen Rückgabedatentyp
und als Methodenname den Namen der Klasse besitzen. Sie werden aufgerufen, wenn
man mit dem Schlüsselwort new eine neues Objekt erzeugt und dienen dazu, den
Anfangszustand des neuen Objektes herzustellen.
HRZ Einführungspraktikum Java
41
III. Objektorientierte Programmierung mit Java
42
3.2 Eigene Klassen verwenden:
public class Bank
{
public static void main( String[] args )
{
Konto meins = new Konto( "Willi Winzig", 1234823 );
Konto anderes;
anderes = new Konto( "John Doe", 1234824 );
meins .einzahlen(
anderes.einzahlen(
meins .abheben (
meins .einzahlen(
anderes.abheben (
16500
23400
11200
13400
22300
); // 165 DM
);
);
);
);
System.out.println( meins .kontoStand );
System.out.println( anderes.kontoStand );
}
}
3.3 Das Schlüsselwort this
 Ein Objekt kann auf seine eigenen Variablen und Methoden durch Voranstellen von this
zugreifen. Insbesondere bei Namensgleichheit von Variablen des Objektes und lokalen
Variablen der Methode ist dies sehr nützlich.
 Ein Objekt kann this auch verwenden, um eine Referenz auf sich selbst zu übergeben,
z. B. mit return( this ); als Rückgabewert oder als Parameter in einem
Methodenaufruf.
Beispiel:
Variante A:
public Konto( String derKontoInhaber, int dieKontoNr )
{
kontoStand
= 0;
kontoInhaber = derKontoInhaber;
kontoNr
= dieKontoNr;
}
Variante B (Verwendung von this):
public Konto( String kontoInhaber, int kontoNr )
{
this.kontoStand
= 0;
this.kontoInhaber = kontoInhaber;
this.kontoNr
= kontoNr;
}
HRZ Einführungspraktikum Java
42
III. Objektorientierte Programmierung mit Java
43
4. Zugriffsrechte steuern: Modifier public und private
Das Problem:
Konto meins = new Konto( "Willi Winzig", 1234823 );
meins.einzahlen ( 34500 );
meins.abheben
( 12000 );
meins.kontoStand = 100000;
Mit Hilfe der Schlüsselwörter public und private kann man derartige Probleme
vermeiden:
 public kennzeichnet, daß aus jeder beliebigen Klasse auf die so gekennzeichnete
Variable oder Methode zugegriffen werden darf.
 private kennzeichnet, daß nur innerhalb der jeweiligen Klasse selbst auf die so
gekennzeichnete Variable oder Methode zugegriffen werden darf.
...
private int kontoStand;
...
public void einzahlen( int betrag )
{
if( betrag < 0 )
throw new IllegalArgumentException( "betrag < 0" );
kontoStand += betrag;
}
public void abheben( int betrag )
{
if( ( betrag > kontoStand ) || ( betrag < 0 ) )
throw new IllegalArgumentException
( "betrag < 0 oder keine ausreichende Deckung" );
kontoStand -= betrag;
}
public int gibKontoStand()
{ return kontoStand; }
Beachte:
 In den meisten Fällen sollten die Variablen eines Objektes aus oben aufgezeigten Gründen
private deklariert werden und nur mit Zugriffsmethoden wie einzahlen() und
abheben() kontrolliert veränderbar sein!
 Durch "Datenkapselung" und "Information Hiding" die Integrität und Fehlersicherheit
der Objekte schützen!
 Das Objekt kann z. B. auch private-Methoden oder -Konstruktoren besitzen, die nur
innerhalb des Objektes benutzt werden können und sollen.
HRZ Einführungspraktikum Java
43
III. Objektorientierte Programmierung mit Java
44
5. Klassenvariablen, Klassenmethoden und Konstanten
5.1 Instanz- und Klassenvariablen
 Die bisher betrachteten Objektvariablen waren Instanzvariablen, d. h. jede Instanz der
Klasse (also jedes Objekt) besitzt z. B. seine eigene Variable kontoStand.
 Durch Voranstellen des Schlüsselwortes static werden Klassenvariablen definiert.
 Klassenvariablen existieren nur einmal je Klasse. Alle Objekte dieser Klasse können auf
deren Klassenvariablen zugreifen. Wird eine Klassenvariable geändert, "sehen" alle
Objekte automatisch den geänderten Wert.
Beispiel:
public class Konto
{
public static int letzteKontoNr = 0;
...
public Konto( String kontoInhaber )
{
this.kontoStand
= 0;
this.kontoInhaber = kontoInhaber;
this.kontoNr
= ++letzteKontoNr;
}
public int gibKontoNr()
{ return kontoNr; }
...
}




Die Klassenvariable letzteKontoNr verwaltet die letzte vergebene Kontonummer.
Der Konstruktor der Klasse erhöht jeweils diese Klassenvariable um eins.
Die Klassenvariable muß sinnvollerweise initialisiert werden.
Auf Klassenvariablen kann über den Namen der Klasse oder den Namen eines Objektes
der Klasse zugegriffen werden:
Konto meinKonto = new Konto( "Willi Winzig" );
System.out.println( meinKonto.letzteKontoNr );
System.out.println( Konto
.letzteKontoNr );
 Sinnvollerweise sollte obige Klassenvariable aber besser private deklariert sein!
Beachte:
 Klassenvariablen sind nicht an die Existenz einer Instanz der Klasse gebunden, d. h. sie
sind auch dann zugreifbar, wenn derzeit keine Instanz der Klasse existiert!
HRZ Einführungspraktikum Java
44
III. Objektorientierte Programmierung mit Java
45
5.2 Konstanten deklarieren und verwenden
 Mit den Schlüsselwörtern final und static werden Konstanten deklariert, d.h.
unveränderbare Variablen.
Beispiel:
public class Konto
{
public final static float EURO_DM_KURS = 1.95583F;
...
}
Verwendung in der Klasse Bank:
public class Bank
{
public static void main( String[] args )
{
int dm
= 50;
int euro = Math.round( dm / Konto.EURO_DM_KURS );
System.out.println( euro );
}
}
HRZ Einführungspraktikum Java
45
III. Objektorientierte Programmierung mit Java
46
5.3 Instanz- und Klassenmethoden
 Analog zu Klassenvariablen werden mit static Klassenmethoden definiert.
 Klassenmethoden sind nicht an die Existenz eines Objektes der Klasse gebunden, d. h. sie
lassen sich auch dann aufrufen, wenn (noch) keine Instanz der Klasse existiert.
 Klassenmethoden dürfen daher nur auf Klassenvariablen oder andere Klassenmethoden
der Klasse zugreifen, nicht auf Instanzvariablen oder -methoden.
 Klassenmethoden lassen sich durch Voranstellen des Klassennamens oder des Namens
eines Objektes der Klasse aufrufen.
Beispiel:
public class Konto
{
public final static float EURO_DM_KURS = 1.95583F;
public static int EUROnachDM( int betrag )
{ return Math.round( EURO_DM_KURS * betrag ); }
...
}
Verwendung in der Klasse Bank:
public class Bank
{
public static void main( String[] args )
{
int euro = 30;
int dm
= Konto.EUROnachDM( euro );
System.out.println( dm );
}
}
Hinweise:
 Es können Klassen definiert werden, die nur aus Klassenvariablen und –methoden
bestehen, d. h. es existieren keine Konstruktoren und keine Instanzen der Klasse.
 Mit Klassenvariablen und –methoden werden oft Hilfsklassen realisiert, z. B. die Klasse
Math mit den (konstanten) Klassenvariablen PI und E und mathematischen Funktionen.
 Die Methode main einer Java-Anwendung ist eine Klassenmethode, da von der Klasse
dieser Anwendung keine Instanz erzeugt wird, wenn die Anwendung gestartet wird.
Übung:

Erweitern Sie die Klasse um eine statische Methode zur Umrechnung von DM nach Euro.
HRZ Einführungspraktikum Java
46
III. Objektorientierte Programmierung mit Java
47
6. Klasse Konto (Übersicht)
public class Konto
{
public final static float EURO_DM_KURS = 1.95583F;
public static int EUROnachDM( int betrag )
{ return Math.round( EURO_DM_KURS * betrag ); }
public static int DMnachEURO( int betrag )
{ return Math.round( betrag / EURO_DM_KURS ); }
private String kontoInhaber;
private int
kontoStand;
private int
kontoNr;
public String gibKontoInhaber(){ return kontoInhaber; }
public int
gibKontoStand() { return kontoStand;
}
public int
gibKontoNr()
{ return kontoNr;
}
private static int letzteKontoNr = 0;
public Konto( String kontoInhaber )
{
this.kontoStand
= 0;
this.kontoInhaber = kontoInhaber;
this.kontoNr
= ++letzteKontoNr;
}
public void einzahlen( int betrag )
{
if( betrag < 0 )
throw new IllegalArgumentException( "betrag < 0" );
kontoStand += betrag;
}
public void abheben( int betrag )
{
if( ( betrag > kontoStand ) || ( betrag < 0 ) )
throw new IllegalArgumentException
( "betrag < 0 oder keine ausreichende Deckung" );
kontoStand -= betrag;
}
}
HRZ Einführungspraktikum Java
47
III. Objektorientierte Programmierung mit Java
48
7. Polymorphismus und Überladen
7.1 Methoden überladen
 In Java lassen sich Methoden definieren, die den gleichen Namen, aber eine
unterschiedliche Parameterliste besitzen.
 Das Java-System unterscheidet beim Aufruf der Methode anhand der Datentypen der
Parameterliste, welche der angegebenen Methoden auszuführen ist.
 Diese Eigenschaft objektorientierter Sprachen nennt man auch Überladen (Overloading)
oder statischer Polymorphismus.
 Vergleiche auch z. B. die Definition der Methoden in der Klasse Math für verschiedene
Datentypen int, long, float und double als Parameter!
Beispiel:
 Zwei Varianten der Methode gibKontoStand():
public class Konto
{
...
public int gibKontoStand()
{ return kontoStand; }
public int gibKontoStand( boolean inEuro )
{
if( inEuro )
return DMnachEURO( kontoStand );
else
return kontoStand;
}
...
}
...
Konto k = new Konto( "Meier" );
k.einzahlen( 10000 );
int dm, euro;
dm
= k. gibKontoStand();
euro = k. gibKontoStand( true );
dm
= k. gibKontoStand( false );
Beachte:
 In einigen Programmiersprachen ist das Überladen vordefinierter Operatoren ( z. B. "+")
möglich. Dies ist in Java nicht möglich.
 Es ist nicht möglich, Methoden mit gleicher Parameterliste, aber verschiedenem
Rückgabewert zu definieren!
HRZ Einführungspraktikum Java
48
III. Objektorientierte Programmierung mit Java
49
Objektorientierte Denkweise:
 Wenn zwei Methoden das gleiche tun, sollten Sie auch gleich heißen.
 Vereinfache die Benutzung und ermögliche Wiederverwendung durch Flexibilität.
 Lasse nicht den Programmierer, sondern den Compiler oder das System zur Laufzeit
entscheiden, welche Aktion die richtige ist, wenn bestimmte Parameter oder Objekte
verwendet werden.
7.2 Konstruktoren überladen
 Oft werden auch Konstruktoren überladen. Die Klasse Konto kann z. B. alternative
Konstruktoren anbieten:
Beispiel:
public class Konto
{
...
public Konto( String kontoInhaber )
{
this.kontoStand
= 0;
this.kontoInhaber = kontoInhaber;
this.kontoNr
= ++letzteKontoNr;
}
public Konto( String kontoInhaber, int betrag )
{
this.kontoStand
= betrag;
this.kontoInhaber = kontoInhaber;
this.kontoNr
= ++letzteKontoNr;
}
...
}
 Überladene Konstruktoren flexibilisieren die Verwendung der Klasse:
Konto k1 = new Konto( "Meier" );
k1.einzahlen( 1000 );
Konto k2 = new Konto( "Schulze", 2000 );
HRZ Einführungspraktikum Java
49
III. Objektorientierte Programmierung mit Java
50
7.3 Überladene Konstruktoren aufrufen

Mit this( Parameterliste ) kann ein überladener Konstruktor einen anderen
Konstruktor der gleichen Klasse aufrufen.
 Die this()-Anweisung muß die erste Anweisung in diesem Konstruktor sein!
 Dieser Mechanismus wird oft verwendet, wenn ein Konstruktor einem bereits definierten
entspricht, aber zusätzlich z. B. noch weitere Variablen setzt oder weitere Methoden
aufruft.
 Objektorientierung: Greife auf Bestehendes zurück, löse ein Problem nur einmal.
Beispiel:
public class Konto
{
...
public Konto( String kontoInhaber )
{ this( kontoInhaber, 0 ); }
public Konto( String kontoInhaber, int betrag )
{
this.kontoStand
= betrag;
this.kontoInhaber = kontoInhaber;
this.kontoNr
= ++letzteKontoNr;
}
...
}
Hinweis zu Konstruktoren:
 Ein parameterloser Konstruktor wird Standardkonstruktor genannt. Er soll in der Regel
eine Instanz erzeugen, bei der die Attribute auf bestimmte Standardwerte gesetzt werden.
Andere Konstruktoren bieten dann die Möglichkeit, von den Standardvorgaben
abzuweichen.
 Wird in einer Klasse kein Konstruktor deklariert, erzeugt das System automatisch einen
Standardkonstruktor, der nichts tut (außer eine neue Instanz zurückzugeben). Will man
dies verhindern, muß man mindestens einen Konstruktor deklarieren. Will man aber
verhindern, daß überhaupt Instanzen der Klasse direkt erzeugt werden können, sollte man
einen parameterlosen Standardkonstruktor deklarieren, der private ist.
HRZ Einführungspraktikum Java
50
III. Objektorientierte Programmierung mit Java
51
8. Subklassen und Vererbung von Eigenschaften
 Objekte bzw. ihre Definition in Klassen können in einer Vererbungsbeziehung stehen,
indem man eine neue Klasse von einer bereits existierenden Klasse ableitet.
 Eine Klasse bzw. ein Objekt erbt automatisch alle Eigenschaften (Variablen und
Methoden) der Klasse, von der sie abgeleitet wird. Dies kann über mehrere Ebenen
rekursiv erfolgen.
 Die erbende Klasse nennt man Subklasse, die vererbende Klasse Superklasse.
 Durch Vererbung müssen nur die Teile der Klasse neu angegeben werden, in denen sie
sich von ihrer Superklasse unterscheidet.
Beispiel:
Superklasse: Konto
Attribute:
kontoStand, kontoNr, ...
Methoden:
einzahlen(), abheben(), ...
Subklasse:
Attribute:
Methoden:
Girokonto
kontoStand, kontoNr, ... (geerbt),
limit (neu)
einzahlen(), abheben(), ... (geerbt),
setzeLimit(), gibLimit() (neu)
 Durch das Schlüsselwort extends wird angezeigt, daß diese Klasse von einer anderen
Klasse abgeleitet ist (d. h. von ihr erbt).
 In der Subklasse stehen automatisch alle Methoden und Variablen zur Verfügung, die in
der Superklasse definiert wurden.
Code-Beispiel (noch nicht vollständig!):
public class Girokonto extends Konto
{
private int limit;
public void setzeLimit( int limit )
{ this.limit = limit; }
public int gibLimit()
{ return limit; }
}
Objektorientierte Denkweise:
 Löse ein Problem möglichst generell und nur einmal in einer möglichst
wiederverwendbaren Superklasse. Erweitere die Funktionalität durch Spezialisierung in
Subklassen: Ein Girokonto ist eine besondere Art von Konto.
Übung:
 Erzeugen Sie eine neue Klasse Girokonto, die von der Klasse Konto abgeleitet ist.
HRZ Einführungspraktikum Java
51
III. Objektorientierte Programmierung mit Java
52
8.1 Konstruktoren und Vererbung
 Da Konstruktoren als Methodennamen den Namen ihrer Klasse tragen, können sie im
obigen Sinne nicht vererbt werden. Konstruktoren werden für jede Klasse neu definiert
und nicht wie andere Methoden vererbt.
 Ein Konstruktor der Subklasse kann (und sollte) jedoch einen Konstruktor der Superklasse
über das Schlüsselwort super aufrufen, anstatt dessen Code in der Subklasse nochmals
anzugeben.
 Fehlt die Angabe von super() in einem Konstruktor, wird beim Aufruf eines Konstruktors
der Subklasse automatisch der sog. Standardkonstruktor (derjenige Konstruktor ohne
Parameterliste: "super();" ) der Superklasse aufgerufen, falls er existiert.
Beispiel:
public class Girokonto extends Konto
{
...
public Girokonto( String kontoInhaber,
int
betrag,
int
limit )
{
super( kontoInhaber, betrag );
setzeLimit( limit );
}
...
}
Übung:
 Ergänzen Sie die Klasse Girokonto um einen Konstruktor und schreiben Sie eine JavaAnwendung, die mit Konten und Girokonten arbeitet und Methoden dieser Klassen
aufruft.
Hinweis:
 In vielen objektorientierten Sprachen gibt es die Möglichkeit, Klassen zu erstellen, die
von mehreren Klassen abgeleitet sind und die Eigenschaften aller dieser Klassen besitzen.
Dies nennt man Mehrfachvererbung. Mehrfachvererbung ist in Java nicht möglich, da
damit einige konzeptionelle Schwächen verbunden sind. Viele Probleme, bei denen man
in anderen Sprachen Mehrfachvererbung verwenden würde, lassen sich in Java mit Hilfe
von Interfaces lösen (mehr dazu später).
 Instanzen von Subklassen lassen sich wie Instanzen der Superklasse verwenden, z. B. bei
der Übergabe als Parameter an eine Methode, die eine Instanz der Superklasse erwartet:
 Da ein Girokonto ein Konto ist, kann man eine Instanz von Girokonto überall dort
verwenden, wo ein Konto erwartet wird:
Konto irgendeins = new Girokonto( "Willi", 50000 );
HRZ Einführungspraktikum Java
52
III. Objektorientierte Programmierung mit Java
53
9. Überschreiben von Methoden und Konstruktoren
9.1 Variablenzugriffe und Methodenaufrufe bei Vererbung
 Hat man eine Instanz der Subklasse, kann auf alle Variablen zugegriffen und alle
Methoden aufgerufen werden, die ihre Superklasse besitzt.
 Bei Vererbung über mehrere Ebenen wird der Aufruf einer Methode von unten nach oben
so weit zur jeweiligen Superklasse durchgereicht, bis eine passende Methode in einer der
Superklassen gefunden wird.
9.2 Überschreiben von Methoden
 Bei einem Methodenaufruf sucht Java zunächst in der jeweiligen Klasse nach einer
Definition der Methode. Ist die Methode dort nicht definiert, wird die Anfrage nach oben
in der Klassenhierarchie weitergereicht und die Superklasse dieser Klasse durchsucht. Auf
diese Weise wird die Vererbung realisiert.
 Oft möchte man jedoch eine Methode, die bereits definiert war, neu definieren, um sie mit
einer erweiterten Funktionalität zu versehen. Dies nennt man Überschreiben
(Overriding). Die Methode muß dazu mit der gleichen Parameterliste wie in der
Superklasse neu angegeben werden.
Beispiel:
 Bei Girokonten darf das Konto bis zum Limit überzogen werden, daher muß die Methode
abheben() überschrieben werden:
public class Girokonto extends Konto
{
...
public void abheben( int betrag )
{
if( betrag <= 0 )
throw new IllegalArgumentException
( "Betrag darf nicht <= 0 sein" );
if( betrag > kontoStand + limit )
throw new IllegalArgumentException
( "Sie sind leider zu arm" );
kontoStand -= betrag;
}
...
}
Übung:
 Warum läßt sich das Beispiel mit der bisherigen Klasse Konto noch nicht übersetzen?
HRZ Einführungspraktikum Java
53
III. Objektorientierte Programmierung mit Java
54
9.3 Die Zugriffsebene Protected
 Eine Subklasse kann nicht auf Methoden oder Variablen ihrer Superklasse zugreifen, die
als private deklariert wurden, jedoch wie jede andere Klasse auf die public –Teile
zugreifen.
 Methoden und Variablen, die (statt public oder private) als protected deklariert
wurden, verhalten sich bezüglich ihrer Subklassen wie public, bezüglich aller anderen
Klassen wie private deklariert.
Beispiel:
 Damit die Methode abheben() in Girokonto direkt auf die Variable kontoStand der Klasse
Konto zugreifen kann, muss diese als protected statt als private deklariert sein:
public class Konto
{
protected String kontoInhaber;
protected int
kontoStand;
protected int
kontoNr;
...
}
9.4 Überschriebene Methoden wieder aufrufen
 Innerhalb einer überschreibenden Methode kann über das Schlüsselwort "super." auf
die Originalmethode zugegriffen werden:
Beispiel:
public class X
{
public void doSomething()
{ System.out.println( "Greetings from X" ); }
}
public class Y extends X
{
public void doSomething()
{
super.doSomething(); // Gibt "Greetings from X" aus
System.out.println( "Greetings from Y" );
}
}
HRZ Einführungspraktikum Java
54
III. Objektorientierte Programmierung mit Java
55
9.5 Final-Methoden
 Methoden, die als final deklariert werden, können nicht von einer Subklasse
überschrieben werden.
 Da der Compiler weiß, daß sich die Methode nicht mehr ändert, kann er ihren Code
optimieren, so daß final-Methoden schneller ausgeführt werden. Aus diesem Grund
sind viele Methoden der Java-Standardpakete final, was aber ihre Veränderung in
eigenen Subklassen verhindert.
Beispiel:
 Einige besonders zeitkritische Methoden der Klasse java.util.Vector sind final,
damit sie schneller ausgeführt werden können.
9.6 Final-Klassen
 Klassen, die als final deklariert sind, dürfen nicht abgeleitet werden, d. h. von ihnen
kann keine Unterklasse gebildet werden: public final class Name...
 Der Java-Compiler kann die Implementierung solcher Klassen optimieren, da er weiß, daß
die Klasse nicht mehr verändert bzw. erweitert wird. Aus diesem Grunde sind einige JavaKlassen final.
Beispiel:
 Die Klasse String ist leider final, da Zeichenkettenverarbeitung zeitaufwendig ist
und die Java-Schöpfer durch die final-Deklaration die schnelle Implementierung von
String durch die Laufzeitsysteme ermöglichen wollten.
 Man kann demnach nicht einfach eine Subklasse von String erstellen, die die
Funktionalität erweitert, z. B. um eine Methode, die Teile von Strings durch andere
ersetzen kann.
HRZ Einführungspraktikum Java
55
III. Objektorientierte Programmierung mit Java
56
10. Abstrakte Klassen und Schnittstellen
10.1 Abstrakte Klassen
 Von Klassen, die als abstract deklariert werden, können keine Instanzen gebildet
werden. Sie dienen lediglich als Vorlage für daraus abzuleitende Subklassen, die dann die
in ihrer abstrakten Superklasse definierten Methoden und Variablen verwenden können.
 Abstrakte Klassen dürfen Methoden enthalten, die als abstract deklariert werden und
von denen nur die Methodenunterschrift (d. h. Datentyp, Name, Parameterliste)
angegeben wird. Nicht-abstrakte Subklassen dieser Klasse sind dann verpflichtet, diese
Methoden zu implementieren.
 Subklassen abstrakter Klassen können wiederum abstrakt sein.
 Mit Hilfe abstrakter Klassen kann der Entwickler dafür sorgen, daß alle Unterklassen
dieser Klasse gewisse Methoden zur Verfügung stellen müssen. Außerdem besitzen diese
Subklassen damit eine gemeinsame Superklasse (die abstrakte Klasse). Obwohl diese
abstrakt ist, läßt sich dieser Sachverhalt dann z. B. so ausnutzen, daß Objekte dieser
abstrakten Klasse als Objekttypen in anderen Methoden anderer Klassen verwendet
werden können. Da jede Subklasse auch dort verwendet werden kann, wo ein Objekt der
Superklasse erwartet wird und sichergestellt ist, daß alle Subklassen die abstract
definierten Methoden implementieren müssen, können so Methoden geschrieben werden,
die automatisch mit allen Subklassen der abstrakten Klasse umgehen können.
Beispiel aus der Java Klassenbibliothek:
Vgl. die Definition der Klasse Number aus dem Paket java.lang, der abstrakten Superklasse
der Wrapper-Klassen Integer, Long, Float und Double.
Beispiel:
public abstract class Konto // Abstrakte Klasse
{
...
// Abstrakte Methode
public abstract int verfuegbarerBetrag();
public void abheben( int betrag )
{
if( betrag < 0 )
throw new IllegalArgumentException( "Betrag < 0" );
if( betrag > verfuegbarerBetrag() )
throw new IllegalArgumentException( "Sorry, zu arm!" );
kontoStand -= betrag;
}
}
(Fortsetzung folgende Seite)
HRZ Einführungspraktikum Java
56
III. Objektorientierte Programmierung mit Java
57
 Unterklassen von Konto implementieren die abstrakte Methode:
public class Girokonto extends Konto
{
...
// Implementierung der abstrakten Methode:
public int verfuegbarerBetrag()
{ return kontoStand + limit; }
}
public class Sparbuch extends Konto
{
...
// Implementierung der abstrakten Methode:
public int verfuegbarerBetrag()
{ return kontoStand; }
}
 Andere Klassen können nur Instanzen der nicht abstrakten Unterklassen bilden, können
aber alle Methoden der Klasse Konto, auch auf die abstrakten, aufrufen:
public class Bank
{
public static void main( String[] args )
{
Sparbuch sb = new Sparbuch ( "Meier" );
Girokonto gk = new Girokonto( "Müller", 10000 );
bearbeiten( sb );
bearbeiten( gk );
}
public static void bearbeiten( Konto k )
{
int verfuegbar = k.verfuegbarerBetrag();
System.out.println( "Betrag: " + verfuegbar );
}
}
HRZ Einführungspraktikum Java
57
III. Objektorientierte Programmierung mit Java
58
10.2 Schnittstellen
 Oft ist die konkrete Klasse eines Objektes eigentlich unwichtig, wichtig ist nur, daß sie ein
bestimmtes Verhalten zeigt, d. h. eine bestimmte Methode anbietet. Beim Sortieren eines
Arrays ist es beispielsweise eigentlich egal, was in dem Array steht (Strings, Konten,
Kunden, ...), solange zwei Array-Elemente sich vergleichen lassen, um die Sortierung
durchführen zu können.
 Eine mögliche Lösung wäre, alle sortierbaren Klassen von einer abstrakten Superklasse
Sortierbar abzuleiten, die eine Methode zum Vergleichen anbietet. Es wird so für alle
Subklassen garantiert, daß sie eine Vergleichsmethode anbieten. Das ist jedoch keine gute
Lösung: Kunde könnte z. B. eigentlich besser eine Subklasse von PersonenRolle sein, und
Mehrfachvererbung ist in Java nicht erlaubt. Kunden und Konten sind auch nicht
besonders ähnlich, die gemeinsame Superklasse erscheint sehr gekünstelt.
 Schnittstellen lösen dieses Problem. Eine Schnittstelle definiert eine Menge von
Methoden, ohne deren Implementierung vorzugeben, ähnlich wie bei einer abstrakten
Klasse. Beliebige Klassen können nun die Schnittstelle 'implementieren' und müssen dann
die entsprechenden Methoden zur Verfügung stellen. Die Klassen und Schnittstellen
müssen dann nicht mehr in einer Vererbungsbeziehung stehen.
 Man kann nun Programmcode schreiben, der mit beliebigen Klassen arbeitet, die eine
bestimmte Schnittstelle implementieren, die Art der Klasse ist nun irrelevant. Das macht
z. B. die Sortier-Funktion wiederverwendbar und sehr flexibel.
 Schnittstellen werden durch das Schlüsselwort interface (statt class) eingeleitet. Sie
legen die Methoden fest, die alle Klassen anbieten müssen, die die Schnittstelle
'implementieren'.
Beispiel:
 Die Schnittstelle Bewertbar definiert das Verhalten bewertbarer Objekte:
public interface Bewertbar
{
public int gibWert();
}
 Beliebige Klassen implementieren die Schnittstelle:
public abstract class Konto implements Bewertbar
{
...
public int gibWert()
{ return kontoStand; }
}
public class Auto implements Bewertbar
{
...
public int gibWert()
{ return kaufpreis * ( 20 – alterInJahren ) / 20; }
}
HRZ Einführungspraktikum Java
58
III. Objektorientierte Programmierung mit Java
59
 Andere Klassen können gegen die Schnittstelle programmieren, ohne wissen zu müssen,
welche konkreten Klassen zur Laufzeit diese Schnittstelle implementieren (vgl. unten die
Methode berechneGesamtwert):
public class Vermoegensverwaltung
{
public static void main( String[] args )
{
Sparbuch sb = new Sparbuch( "Meier" );
sb.einzahlen( 30000 );
Auto porsche = new Auto();
Bewertbar[] dinge = new Bewertbar[ 2 ];
dinge[ 0 ] = sb;
dinge[ 1 ] = porsche;
int summe = berechneGesamtwert( dinge );
System.out.println( summe );
}
public static int berechneGesamtwert( Bewertbar[] sachen )
{
int summe = 0;
for( int i = 0; i < sachen.length; i++ )
summe += sachen[ i ].gibWert();
return summe;
}
}
HRZ Einführungspraktikum Java
59
III. Objektorientierte Programmierung mit Java
60
10.3 Beispiel: Sortieren eines Arrays: wiederverwendbare Implementierung
Das Beispiel zeigt eine wiederverwendbare Implementierung einer Sortierfunktion für Arrays.
Es sollen beliebige Arrays von Objekten beliebiger Klassen sortiert werden können.
Vorausgesetzt wird nur, daß die Objekte eine Methode vergleiche() zur Verfügung
stellen, anhand derer zwei Objekte miteinander verglichen werden können, um die korrekte
Reihenfolge zu bestimmen. Die Methode vergleiche() soll je nachdem, welches Objekt
als 'größer' betrachtet wird, eine Zahl größer, kleiner oder gleich null zurückgeben (vgl. die
Methode compareTo() in der Klasse String, die analog arbeitet):
Seien x und y zwei Instanzen der gleichen Klasse, dann soll der Aufruf x.vergleiche(y)
einen int-Wert wie folgt zurückgeben:
x.vergleiche( y )
x.vergleiche( y )
x.vergleiche( y )
ergibt einen Wert < 0 falls x < y
ergibt einen Wert > 0 falls x > y
ergibt 0
falls x = y
 Erstellen der Schnittstellendefinition in der Datei Vergleichbar.java:
public interface Vergleichbar
{
public int vergleiche( Vergleichbar v );
}
 Die Klasse Konto implementiert die Schnittstelle Vergleichbar, d. h. sie stellt eine
konkrete Implementierung für die in der Schnittstelle geforderte(n) Methode(n) zur
Verfügung. Hier sollen Konto-Instanzen anhand ihres Kontostandes aufsteigend sortiert
werden:
public class Konto implements Vergleichbar
{
...
public int vergleiche( Vergleichbar v )
{
Konto other = (Konto)v;
return ( this.kontoStand - other.kontoStand );
}
}
 Instanzen der Klasse Kunde sollen ebenfalls miteinander vergleichbar werden. Die
Reihenfolge der Kunden soll anhand ihres Namens bestimmt werden (lexikographische
Sortierung):
HRZ Einführungspraktikum Java
60
III. Objektorientierte Programmierung mit Java
61
public class Kunde implements Vergleichbar
{
protected String name; // Der Name des Kunden
public Kunde( String name )
{ this.name = name; }
public int vergleiche( Vergleichbar v )
{
Kunde other = (Kunde)v;
return ( this.name.compareTo( other.name ) );
}
}
 Anwendungen können nun zu Sortierzwecken Kunden und Konten paarweise vergleichen
und dabei einen einheitlichen Aufruf (die Methode der Schnittstelle) verwenden:
public class Test
{
public static void main( String[] args )
{
Konto ko1 = new Sparbuch( "Schmidt" );
Konto ko2 = new Sparbuch( "Kling"
);
ko1.einzahlen( 20000 );
ko2.einzahlen( 30000 );
int vgl = ko1.vergleiche( ko2 );
System.out.println( vgl );
Vergleichbar ku1 = new Kunde( "Meier" );
Vergleichbar ku2 = new Kunde( "Müller" );
int vgl = ku1.vergleiche( ku2 );
System.out.println( vgl );
}
}
HRZ Einführungspraktikum Java
61
III. Objektorientierte Programmierung mit Java
62
 Eine Klasse Sortierer, die Arrays von vergleichbaren Objekten sortiert, benutzt nur die
Schnittstelle Vergleichbar, ohne etwas über die konkreten Klassen zu wissen, die diese
Schnittstelle auf verschiedene Weise implementieren. Sie ist damit völlig unabhängig von
einer bestimmten Klasse und wiederverwendbar. Die Klasse bietet eine Methode
sortiere(), die ein Array von Instanzen einer die Schnittstelle Vergleichbar
implementierenden Klasse mittels QuickSort-Algorithmus sortiert:
public class Sortierer
{
public static void sortiere( Vergleichbar[] werte )
{ quicksort( werte, 0, werte.length - 1 ); }
protected static void quicksort( Vergleichbar[] werte,
int lo0, int hi0 )
{
if( hi0 > lo0 )
{
int lo = lo0; int hi = hi0;
int mid = ( lo0 + hi0 ) / 2;
while( lo <= hi
{
while( ( lo <
( werte[ lo
lo++;
while( ( hi >
( werte[ hi
hi--;
)
hi0 ) &&
].vergleiche( werte[ mid ] ) < 0 ) )
lo0 ) &&
].vergleiche( werte[ mid ] ) > 0 ) )
if( lo <= hi )
{
Vergleichbar temp = werte[ lo ];
werte[ lo ] = werte[ hi ];
werte[ hi ] = temp;
lo++; hi--;
}
if( lo0 < hi ) quicksort( werte, lo0, hi );
if( lo < hi0 ) quicksort( werte, lo, hi0 );
}
}
}
}
 Eine beliebige Anwendung kann nun Arrays von Kunden oder Konten sortieren:
Kunde[] kunden = new Kunde[ 10 ];
Konto[] konten = new Konto[ 20 ];
... // Arrays mit Kunden- und Konto-Instanzen füllen...
Sortierer.sortiere( kunden );
Sortierer.sortiere( konten );
HRZ Einführungspraktikum Java
62
III. Objektorientierte Programmierung mit Java
63
Hinweise:
 Neue Klassen können später problemlos dem System hinzugefügt werden. Damit auch sie
sortierbar sind, müssen sie nur ebenfalls das Interface Vergleichbar implementieren...
 Die Plattformunabhängigkeit von Java gründet sich an einigen Stellen auf Schnittstellen,
insbes. im AWT (graphische Benutzeroberflächen in Java).
 Vgl. auch die Schnittstelle Enumeration aus dem Paket java.util und die
Schnittstelle Runnable aus dem Paket java.lang!
10.4 Mehrfachvererbung und Implementierung mehrerer Schnittstellen
 Da Schnittstellen-Definitionen keine konkreten Implementierungen beinhalten, existieren
hier keine Probleme bei Mehrfachvererbung, daher ist Mehrfachvererbung bei
Schnittstellen erlaubt.
public interface XundYundZ extends X, Y
{
public void doZ();
}
 Eine Klasse kann zwar nur eine Oberklasse besitzen, kann aber beliebig viele
Schnittstellen implementieren:
public class Girokonto extends Konto
implements Bewertbar, Vergleichbar
{
...
}
10.5 Schnittstellen als Konstantensammlungen
 Schnittstellen werden auch oft verwendet, um so etwas wie 'globale Konstanten' zu
definieren. Definiert man in einer Schnittstelle eine Konstante, so ist diese automatisch in
jeder Klasse bekannt, die die Schnittstelle implementiert
public interface FinanzKonstanten
{
public final static float EURO_DM_KURS = 1.95583F;
}
public class Konto implements FinanzKonstanten
{
public static int EUROnachDM( int betrag )
{ return Math.round( EURO_DM_KURS * betrag ); }
public static int DMnachEURO( int betrag )
{ return Math.round( betrag / EURO_DM_KURS ); }
...
}
HRZ Einführungspraktikum Java
63
III. Objektorientierte Programmierung mit Java
64
11. Eigene Klassen zu Packages zusammenfassen
11.1 Packages definieren
 Mit Hilfe des Schlüsselwortes package kann man die Zugehörigkeit einer Klasse zu
einem Package definieren. Damit lassen sich Klassen zu Bibliotheken zusammenfassen
und übersichtlich verwalten und weitergeben.
 Namen von Packages werden per Konvention klein geschrieben. Die packageAnweisung muß die erste Anweisung im Quellcode sein:
package finanzen;
// hier kommen ggf. import-Anweisungen hin...
public class Konto{ ... }
package finanzen.wertpapiere;
public class Aktie{ ... }
 Die Klassendateien und Quellcodedateien müssen sich dann in einem Unterverzeichnis
befinden, das dem Namen des Package entspricht:
Konto.java
Aktie.java
in
in
.\finanzen\Konto.java
.\finanzen\wertpapiere\Aktie.java
 Die Packages lassen sich dann benutzen wie andere Packages auch:
import finanzen.*;
import finanzen.wertpapiere.*;
public class Bank{ ... }
 Klassen die sich innerhalb des gleichen Paketes befinden, 'kennen' sich automatisch, es ist
dann kein import nötig. Fehlt die Angabe einer Zugehörigkeit zu einem Package, wird das
unbenannte 'Standardpaket' angenommen, das dem aktuellen Verzeichnis entspricht.
Auch dann ist kein import nötig.
HRZ Einführungspraktikum Java
64
III. Objektorientierte Programmierung mit Java
65
11.2 Zugriffsebenen und Packages
 Neben den Modifiern public, protected und private existiert noch eine vierte
Zugriffsebene, die die Sichtbarkeit einer Methode oder Variable auf alle Klassen des
gleichen Paketes beschränkt. Dazu wird jedoch nicht 'package' vor den Methodenoder Variablennamen geschrieben, sondern der Modifier weggelassen:
public class xy
{
int gruppenschluessel = 4711;
// kann nur aus Klassen dieses Packages benutzt werden
void tuEtwasKritisches();
// darf nur aus Klassen dieses Packages aufgerufen werden
}
 Auch den Zugriff auf ganze Klassen kann man entweder allen anderen Klassen erlauben
public class x { ... }
oder auf Klassen des gleichen Paketes beschränken. Nur diese können die Klasse dann
benutzen:
class y { ... }
 Klassen, die nicht public sind, müssen nicht in einer eigenen Quellcodedatei untergebracht
sein, sie können sich eine Quellcodedatei mit anderen Klassen teilen.
 Nichtöffentliche Klassen mit Package-Zugriff ermöglichen es, die Komplexität einer
Anwendung zu verbergen. Die import-Anweisung importiert nur public-Klassen, andere
Klassen bleiben ihr verborgen.
HRZ Einführungspraktikum Java
65
IV. Nützliches und Wissenswertes
66
HRZ Einführungspraktikum Java
66
IV. Nützliches und Wissenswertes
67
IV.
Nützliches
und
Wissenswertes
HRZ Einführungspraktikum Java
67
IV. Nützliches und Wissenswertes
68
1. Mathematische Funktionen
 Mathematische Funktionen werden durch die Klasse java.lang.Math abgedeckt.
 Da sie Teil des Paketes java.lang ist, ist sie standardmäßig bereits importiert.
1.1 Konstanten
Klassenvariable
Math.PI
Math.E
Wert
 als double ( 3.14159...)
e als double (2.71828...)
1.2 Trigonometrische Funktionen
Klassenmethode
double Math.sin( double Radiant )
double Math.cos( double Radiant )
double Math.tan( double Radiant )
double Math.asin( double Radiant )
double Math.acos( double Radiant )
double Math.atan( double Radiant )
Funktion
sinus
cosinus
tangens
arcsinus
arccosinus
arctangens
Beachte:
 Angabe als Radiant! Bei Angabe als Winkel diesen mit PI/180 multiplizieren!
1.3 Vergleiche
Klassenmethode
Math.max( Zahl1, Zahl2 )
Math.min( Zahl1, Zahl2 )
Funktion
Max für int, long, float, double
Min für int, long, float, double
1.4 Rundungsfunktionen
Klassenmethode
Math.round( Zahl )
double Math.rint( double Zahl )
double Math.floor( double Zahl )
double Math.ceil( double Zahl )
Math.abs( Zahl )
Math.IEEEremainder( Z1, Z2 )
HRZ Einführungspraktikum Java
Funktion
Auf- / Abrundung für float, double
Ergebnis int bzw. long
Auf- / Abrundung
Nächstkleinere ganze Zahl
Nächstgrößere ganze Zahl
Absolutwert für int, long, float, double
Rest der Division als double
68
IV. Nützliches und Wissenswertes
69
1.5 Exponentialfunktionen und Potenzen
Klassenmethode
double Math.pow( double d1, double d2)
double Math.sqrt( double z )
double Math.exp( double z )
double Math.log( double z )
Funktion
Potenz d1 hoch d2
Zweite Wurzel von z
Potenz e hoch z
Logarithmus naturalis von z
1.6 Zufallszahlen
Klassenmethode
double Math.random()
Funktion
Zufallszahl zwischen 0 und 1
Beachte:
 Zur Erzeugung von Zufallszahlenfolgen gibt es eine eigene Klasse Random im Paket
java.util:
import java.util.Random;
...
Random r = new Random();
...
int
i = r.nextInt();
// Nächste Zufallszahl
long
l = r.nextLong();
float f = r.nextFloat();
double d = r.nextDouble();
...
Random r1 = new Random();
// Systemzeit als Seed
Random r2 = new Random( seed ); // seed ist vom Typ long
...
r2.setSeed( seed );
// seed ist vom Typ long
Beachte:
 Bei Verwendung identischer Seeds wird die gleiche Folge von Pseudo-Zufallszahlen
erzeugt!
1.7 Große Zahlen
 Zum Arbeiten mit beliebig großen Zahlen stehen ab JDK 1.1 die Klassen BigDecimal
und BigInteger aus dem Paket java.math zur Verfügung.
 Die Klassen bieten Methoden zum Rechnen mit solchen Zahlen an, die analog zu den
mathematischen Standard-Operatoren der Sprache Java sind und diese für große Werte
ersetzen. Außerdem sind alle relevanten Methoden aus der Klasse Math analog verfügbar.
 Weitere Details zu diesen Klassen finden sich in der API-Dokumentation!
HRZ Einführungspraktikum Java
69
IV. Nützliches und Wissenswertes
70
2. Datums- und Zeitwerte
2.1 Einfache Zeitstempel
 Über die Funktion
long jetzt = System.currentTimeMillis();
erhält man die seit Mitternacht am 1. Januar 1970, UTC vergangenen Millisekunden
 Darüber hinaus existieren die Klassen Date, Calendar und
GregorianCalendar im Paket java.util, um mit Datumswerten zu arbeiten:
2.2 Die Klassen Date und Calendar
 Im JDK 1.0 diente die Klasse Date neben der Darstellung eines bestimmten Zeitpunktes
auch dazu, diesen Zeitpunkt als ein bestimmtes Kalenderdatum in Tag / Monat / Jahr usw.
zu interpretieren und zu verarbeiten. Diese Kalenderfunktionen waren nicht sehr gut auf
internationale Anforderungen ausgelegt.
 Ab JDK 1.1 übernimmt die Klasse Calendar die Aufgabe, ein Datum innerhalb eines
Kalendersystems darzustellen. Calendar ist eine abstrakte Klasse, derzeit einzig
mitgelieferte konkrete Implementierung ist die Klasse GregorianCalendar.
 Jede Instanz von Calendar besitzt intern zwei Darstellungen eines Zeitpunktes: zum einen
als Datum in Tag, Monat, Jahr usw. aufgeteilt und zum anderen als long-Wert (Anzahl
Millisekunden seit 1.1.1970). Diese beiden Darstellungen sind auch getrennt
manipulierbar und müssen synchron gehalten werden.
2.3 Datumswerte mit GregorianCalendar anlegen
GregorianCalendar c;
c
c
c
c
=
=
=
=
new
new
new
new
GregorianCalendar();
GregorianCalendar(1998,11,31 );
GregorianCalendar(1998,11,31,17,32);
GregorianCalendar(1998,11,31,17,32,15);
//
//
//
//
heute
31.12.1998
um 17:32 h
und 15 Sek
Beachte:
 Der Monat wird ab 0 gezählt ( Dezember = 11 )!
 Weitere Konstruktoren legen noch die Zeitzone, Sommer-/Winterzeitabweichung etc. fest.
2.4 Datumswerte vergleichen
GregorianCalendar t1 = new GregorianCalendar( 1971, 3, 22 );
GregorianCalendar t2 = new GregorianCalendar( 1976, 9, 6 );
boolean b1 = t1.after ( t2 ); // false
boolean b2 = t1.before( t2 ); // true
boolean b3 = t1.equals( t2 ); // false
HRZ Einführungspraktikum Java
70
IV. Nützliches und Wissenswertes
71
2.5 Datumsteile abfragen
GregorianCalendar cal = new GregorianCalendar();
int era = cal.get( Calendar.ERA );
if( era == cal.AD ) System.out.println( "Anno Domini." );
int tag
int monat
int jahr
= cal.get( Calendar.DATE );
= cal.get( Calendar.MONTH );
= cal.get( Calendar.YEAR );
int stunde1 = cal.get( Calendar.HOUR_OF_DAY );
int stunde2 = cal.get( Calendar.HOUR
int amOrPm = cal.get( Calendar.AM_PM
);
);
int minute = cal.get( Calendar.MINUTE
);
int sekunde = cal.get( Calendar.SECOND
);
int milli
= cal.get( Calendar.MILLISECOND );
int wochej
int wochem
int tagj
= cal.get( Calendar.WEEK_OF_YEAR );
= cal.get( Calendar.WEEK_OF_MONTH );
= cal.get( Calendar.DAY_OF_YEAR
);
int moDiMi = cal.get( Calendar.DAY_OF_WEEK
if( moDiMi == Calendar.SUNDAY ) ...
);
... und noch ein paar andere für Zeitzone, Sommerzeit etc., siehe API-Dokumentation!
2.6 Datumsteile setzen
cal.set( Calendar.YEAR, 1976 );
cal.set( Calendar.MONTH,
9 );
...
Bei Verwendung älterer JDKs sollte man anschließend unbedingt
cal.setTime( cal.getTime() );
aufrufen, wodurch die internen Werte für beide Darstellungen des Zeitpunktes synchronisiert
werden. Dies behebt einen Bug in den älteren Java-Laufzeitumgebungen (JDK 1.1).
2.7 Datumswerte mit der Klasse DateFormat ausgeben
 Umfangreiche Möglichkeiten der Formatierung über die Klassen DateFormat und
SimpleDateFormat aus dem Paket java.text (siehe API-Dokumentation):
GregorianCalendar cal = new GregorianCalendar(); // jetzt
DateFormat df = new SimpleDateFormat( "dd.MM.yyyy HH:mm" );
// DateFormat df =
// DateFormat.getDateInstance(DateFormat.FULL, Locale.FRANCE);
String zeit = df.format( cal.getTime() );
System.out.println( zeit );
HRZ Einführungspraktikum Java
71
IV. Nützliches und Wissenswertes
72
3. Die Klasse Object
 In Java sind alle Klassen direkt oder indirekt Subklassen der Klasse Object. Wenn für
eine Klasse keine Superklasse angegeben ist, wird die Klasse von Object abgeleitet.
 Die Klasse Object wird oft dort eingesetzt, wo Methoden allgemein für die Verwendung
mit ganz verschiedenen Objekten ausgelegt werden sollen. Da man eine Instanz einer
Subklasse überall dort einsetzen darf, wo eine Instanz der Superklasse verwendet wird,
kann man z. B. an eine Methode, die ein Object erwartet, jedes beliebige Objekt
übergeben.
 Mit Hilfe des Operators instanceof läßt sich prüfen, ob ein Objekt eine Instanz einer
bestimmten Klasse ist.
Beispiel:
public static boolean ersterWertKleiner( Object a, Object b )
{
if ( a instanceOf String )
{
String stra = (String)a; // 'Casting' ist hier nötig
String strb = (String)b;
return ( stra.compareTo( strb ) < 0 );
}
else if ( a instanceof GregorianCalendar )
{
GregorianCalendar g1 = (GregorianCalendar)a;
GregorianCalendar g2 = (GregorianCalendar)b;
return( g1.before( g2 ) );
}
else ...
}
...
boolean b1 = ersterWertKleiner ( "Hund", "Hand" );
boolean b2 = ersterWertKleiner ( new GregorianCalendar( 1997,
7, 11 ), new GregorianCalendar( 1963, 1, 20 ) );
 Mit Objekt.getClass() erhält man ein Objekt der Klasse Class, das
Informationen über die Klasse des Objektes enthält. Einige nützliche Methoden:
Object o = "Ein String-Objekt"; // oder sonst irgend etwas...
Class c = o.getClass();
String klasse = c.getName(); // Name der Klasse
Class s = c.getSuperclass(); // Superklasse der Klasse
Object x = c.newInstance();
// Neue Instanz dieser Klasse,
// funktioniert nur, falls es einen Standardkonstruktor gibt
 Ab JDK 1.1 bietet die Java Reflection API im Paket java.lang.reflect wesentlich
weitreichendere Möglichkeiten (siehe API-Dokumentation)
HRZ Einführungspraktikum Java
72
IV. Nützliches und Wissenswertes
73
4. Nützliche Werkzeuge für den Java-Programmierer
4.1 Die Klasse StringTokenizer
 Die Klasse StringTokenizer aus dem Paket java.util dient dazu, einen
Teilstring in einzelne Elemente (Tokens) zu zerlegen.
 Die Elemente werden durch Trennzeichen voneinander getrennt.
 Die Menge der Trennzeichen wird dem Konstruktor als String mit übergeben.
Beispiel:
import java.util.StringTokenizer;
public class Zerleger
{
public static void main( String[] args )
{
String text = "Eins, zwei oder drei.";
String trenn = " ,."; // Blank, Komma, Punkt sind Trenner
StringTokenizer st = new StringTokenizer( text, trenn );
while ( st.hasMoreTokens() )
System.out.println( st.nextToken() );
}
}
//
//
//
//
//
Ausgabe:
Eins
zwei
oder
drei
Beachte:
 StringTokenizer erwartet als Trenner nur einzelne Zeichen, keine Zeichenketten!
Weitere Konstruktoren
st =
//
st =
//
//
new StringTokenizer( text );
Leerzeichen, Tab, Newline als Trenner
new StringTokenizer( text, delim, returnTokens );
falls der boolean-Wert returnTokens = true, dann
werden die Trennertoken selbst auch mit zurückgegeben
Weitere Methoden der Klasse StringTokenizer
int countTokens()
// Anzahl Token insgesamt
String nextToken( String delim )
// Setzt gleichzeitig eine neue Menge von Trennzeichen
HRZ Einführungspraktikum Java
73
IV. Nützliches und Wissenswertes
74
4.2 Wrapper-Klassen
 Viele nützliche Methoden der Klassen aus dem Paket java.util sind auf die
Verwendung mit Objekten ausgelegt. Ein Problem dieser Methoden ist aber nun, daß
ihnen nur Objekte, nicht aber Variablen einfacher Datentypen wie z. B. int übergeben
werden können. Für derartige Fälle, in denen man einfache Datentypen wie Objekte
behandeln will, stellt Java sogenannte Wrapper-Klassen zur Verfügung, die einfache
Datentypen in ein Objekt "verpacken".
 Im JDK 1.0 existieren die Wrapper-Klassen Boolean, Character, Double,
Float, Integer und Long für die jeweiligen primitiven Datentypen. Ab JDK 1.1
gibt es auch Wrapper-Klassen für Byte, Short und Void.
 Wrapper-Klassen sind auch nützlich, um Konvertierungen zwischen Datentypen
auszuführen (mehr dazu später).
Beispiel: (andere Wrapper-Klassen funktionieren analog...)
int
i = 3;
Integer j = new Integer( i ); // Die 3 in ein Objekt verpackt
int
k = j.intValue();
// Wieder auspacken...
Übung:
 Schauen Sie sich die Funktionsweise der Wrapper-Klassen in der API-Referenz an!
4.3 Die Klasse Stack
 Die Klasse Stack stellt einen Stapelspeicher für Objekte zur Verfügung (Last in, first out).
Stack s = new Stack();
// Leeren Stapel anlegen
...
s.push( new Integer( 1 ) );
// auf Stapel packen
s.push( "Die Zwei"
);
...
String s = (String)( s.pop() );
// vom Stapel entfernen
Object alsNaechstesKommt = s.peek(); // vorausschauen!
...
if ( s.empty() ) System.out.println( "nix mehr da!" );
HRZ Einführungspraktikum Java
74
IV. Nützliches und Wissenswertes
75
4.4 Die Klasse Vector
 Die Klasse Vector ist eine nützliche Alternative zu einem Array. In einem Vektor können
beliebige Objekte abgelegt werden, die Länge des Vektors ist dynamisch veränderbar.
Beispiel:
Vector namen = new Vector();
namen.addElement( "Helmut" );
namen.addElement( "Otto" );
namen.addElement( "Willi" );
namen.removeElementAt( 1 );
namen.insertElementAt( "Anton", 0 );
String name = (String)( namen.elementAt( 1 ) );
Konstruktoren für Vektoren:
new Vector();
new Vector( int initialCapacity );
new Vector( int initialCapacity, int capacityIncrement );
Den Inhalt des Vektors verändern:
void addElement( Object obj );
// obj Hinten anhängen
void insertElementAt( Object obj, int index );
// einfügen
void setElementAt( Object obj, int index );
// austauschen
void removeAllElements();
// alles löschen
void removeElementAt( int index );
// an index löschen
boolean removeElement( Object obj ); // obj entfernen
Auf Elemente zugreifen:
Object elementAt( int index );
Object firstElement();
Object lastElement();
// Element an Indexposition
// Erstes Element
// Letztes Element
Den Vektor durchsuchen:
boolean contains( Object obj );
int indexOf( Object obj );
int indexOf( Object obj, int index );
int lastIndexOf( Object obj );
int lastIndexOf( Object obj, int index );
//
//
//
//
//
Ist obj drin?
Suche vorwärts
Suche ab index
Suche rückwärts
rückw. ab index
Länge eines Vektors:
int size();
// Anzahl Elemente im Vektor
boolean isEmpty();
// Ist der Vektor leer?
void setSize( int newSize ); // Vektor 'zurechtschneiden'
HRZ Einführungspraktikum Java
75
IV. Nützliches und Wissenswertes
76
4.5 Die Klasse Hashtable
 Die Klasse Hashtable aus dem Paket java.util bietet die Funktionen einer
Hashtabelle, in der Schlüssel auf Werte abgebildet werden. Um diese Abbildung zu
ermöglichen, wird für jeden Schlüssel ein Hashcode benutzt.
 Als Schlüssel und Elemente der Hashtabelle können beliebige Objekte verwendet werden,
die die Methoden equals und hashcode bereitstellen. Mit Hilfe von Wrapper-Klassen
kann man auch primitive Datentypen benutzen.
 Beim Auffinden von Elementen anhand eines vorgegebenen Schlüssels wird dieser mit
equals mit den Schlüsseln in der Tabelle verglichen, es wird also auf inhaltliche
Gleichheit verglichen!
Hashtable h = new Hashtable( 10 );
// neue Tabelle anlegen, voraussichtlich 10 Werte
Wichtige Methoden:
Object put( Object key, Object value );
// Einen Wert unter einem bestimmten Schlüssel ablegen
Object get( Object key );
// In der Tabelle Wert zu diesem Schlüssel suchen
Object remove( Object key );
// Wert unter diesem Schlüssel entfernen
boolean contains
( Object value ); // Wert vorhanden?
boolean containsKey( Object key
); // Schlüssel vorhanden?
HRZ Einführungspraktikum Java
76
IV. Nützliches und Wissenswertes
77
Beispiel:
import java.util.Hashtable;
public class Buchstabierer
{
protected Hashtable buchstaben;
public Buchstabierer()
{
buchstaben = new Hashtable( 26 );
buchstaben.put( "a", "Anton" );
buchstaben.put( "b", "Berta" );
buchstaben.put( "c", "Cesar" );
}
// ...
public void buchstabiere( String s )
{
s = s.toLowerCase();
for ( int i = 0; i < s.length(); i++ )
{
String c = s.substring( i, i + 1 );
if ( buchstaben.containsKey( c ) )
System.out.print( buchstaben.get( c ) );
}
System.out.println();
}
public static void main( String[] args )
{
Buchstabierer bsb = new Buchstabierer();
for( int i = 0; i < args.length; i++ )
bsb.buchstabiere( args[ i ] );
}
}
Aufruf:
java Buchstabierer Hallo ein Test
HRZ Einführungspraktikum Java
77
IV. Nützliches und Wissenswertes
78
4.6 Die Klassen Runtime und Process
 Mit Hilfe der Klassen Runtime und Process lassen sich Kommandos aus Java heraus
absetzen, z. B. um ein externes Programm zu starten:
Runtime dieLaufzeitUmgebung = Runtime.getRuntime();
// sowas nennt man "Singleton": Es gibt nur eine Instanz!
Process p = dieLaufzeitUmgebung.exec( "arbeiten.bat" );
// Es gibt Varianten zum gleichzeitigen Setzen von
// Umgebungsvariablen, Übergeben von Argumenten...
p.waitFor();
// Wartet auf Beendigung
p.destroy();
// beendet den Prozeß
int i = p.exitValue(); // der zurückgegebene Exit-Code
 Läuft ein Prozess, kann man auf seinen Eingabe-, Ausgabe- und Fehlerstrom zugreifen:
InputStream is = p.getInputStream(); // Ausgabe von p
InputStream es = p.getErrorStream(); // Fehler von p
OutputStream os = p.getOutputStream(); // Eingabe an p
HRZ Einführungspraktikum Java
78
IV. Nützliches und Wissenswertes
79
5. Konvertieren zwischen Datentypen und Objekten
5.1 Zwischen primitiven Datentypen konvertieren
 Im Gegensatz zu anderen Sprachen führt Java in der Regel keine automatische
Typkonvertierung durch.
 Primitive Datentypen können durch Voranstellen von "(Datentyp)" konvertiert
werden. Dieses Casting erzeugt einen neuen Wert, der ursprüngliche Wert wird nicht
verändert!
 Casting von einem Datentyp zu einem anderen mit größerem Wertebereich (also z. B. von
int nach long) ist nicht explizit nötig.
 Casting von einem Datentyp zu einem anderen mit kleinerem Wertebereich (also z. B. von
double nach float) muß explizit erfolgen.
 Der Datentyp boolean kann nicht in andere Datentypen gecastet werden. Die int-Werte 0
und 1 können aber nach boolean gecastet werden.
 Da Casting eine sehr hohe Präzedenz hat, muß der zu castende Ausdruck geklammert
werden, falls es sich nicht um eine einzelne Variable handelt.
Beispiel:
int i = (int)( 38.5 / 10.7 );
5.2 Zwischen Objekten konvertieren
 Bei Casting zwischen Objekten müssen diese in einer Vererbungsbeziehung zueinander
stehen.
 Casting von der Subklasse zur Superklasse ist nicht explizit nötig. Instanzen von
Subklassen können überall dort verwendet werden, wo eine Instanz der Superklasse
erwartet wird, d. h. Sie können z. B. einen String jeder Methode übergeben, die ein Object
erwartet.
 Casting von der Superklasse zur Subklasse ist explizit durch Voranstellen von
(Klassenname) nötig, da hier Information verloren gegangen ist.
Beispiel:
 Vergleiche vorangegangene Beispiele zur Klasse Vector!
5.3 Objekte in Strings konvertieren

Viele Klassen besitzen eine Methode toString(), die eine String-Darstellung des
Objektes zurückgibt, z. B. die Wrapper-Klassen.
Beispiel:
Integer i = new Integer( 5 );
String s = i.toString();
HRZ Einführungspraktikum Java
79
IV. Nützliches und Wissenswertes
80
5.4 Primitive Datentypen in Strings konvertieren
 Die Klasse String besitzt die überladene Klassenmethode valueOf(), mit der die
primitiven Datentypen boolean, double, float, int, long, char und
char[]-Arrays in Strings konvertiert werden können.
Beispiele:
boolean b = true;
double d = 28.425;
String s = String.valueOf( b );
String t = String.valueOf( d );
5.5 Strings in primitive Datentypen konvertieren
 Die Wrapper-Klassen Integer und Long besitzen Klassenmethoden parseInt()
bzw. parseLong(), mit deren Hilfe Strings in int- und long-Werte konvertiert
werden können. Dabei kann auch eine Basis (z. B. 2, 10, 16) angegeben werden.
 Die Wrapper-Klassen Boolean, Integer, Long, Float und Double besitzen
Klassenmethoden valueOf(), mit deren Hilfe Strings in ein Objekt dieser Klasse und
von dort aus in einen primitiven Datentyp konvertiert werden können.
Beispiel:
String s = "4711";
String t = "C000";
String u = "100101";
int i = Integer.parseInt( s );
int j = Integer.parseInt( t, 16 );
int k = Integer.parseInt( u, 2 );
5.6 Wrapper-Objekte in primitive Datentypen konvertieren
 Alle Wrapper-Klassen besitzen Instanzmethoden, um sie zurück in die primitiven
Datentypen zu konvertieren, die sie repräsentieren, z. B. booleanValue() in der
Klasse Boolean, charValue() in der Klasse Character.
 Die Wrapper-Klassen Integer, Long, Float und Double besitzen alle jeweils
die vier Instanzmethoden intValue(), longValue(), floatValue() und
doubleValue(), über die diese Objekte in die entsprechenden primitiven Datentypen
konvertiert werden können.
Beispiel:
String
Double
double
float
s
d
x
y
=
=
=
=
"153.92";
Double.valueOf( s );
d.doubleValue();
d.floatValue();
Hinweis:
 Die numerischen Wrapper-Klassen besitzen außerdem die Konstanten MAX_VALUE,
MIN_VALUE, NEGATIVE_INFINITY und POSITIVE_INFINITY zur Ermittlung des
Wertebereiches der Primitivtypen bzw. Darstellung von + / - .
HRZ Einführungspraktikum Java
80
IV. Nützliches und Wissenswertes
81
6. Laufzeitfehler behandeln mit Exceptions
6.1 Grundlegendes über Laufzeitfehler
 Java bietet die Möglichkeit, nahezu alle auftretenden Laufzeitfehler abzufangen, zu
behandeln, weiterzuleiten oder eigene Laufzeitfehler zu erzeugen. Laufzeitfehler, die nicht
abgefangen werden, führen zum Abbruch des Programms oder zumindest (bei
graphischen Benutzeroberflächen) zum Abbruch des aktuellen Threads.
 Laufzeitfehler sind in Java Instanzen der Klasse "Throwable" oder einer ihrer
Unterklassen. Für jede Fehlerart gibt es eine spezielle Klasse. Bei Auftreten eines Fehlers
erzeugt Java eine Instanz der jeweiligen Klasse. Dieses Objekt kann Informationen über
den Fehler enthalten, z. B. den nicht gefundenen Dateinamen bei einer Instanz von
"FileNotFoundException".
 Es gibt zwei Unterklassen von "Throwable": Die Klasse "Error" stellt schwerwiegende
Fehler dar, die nicht abgefangen werden können. Die Klasse "Exception" stellt
Laufzeitfehler dar, die man abfangen und behandeln kann.
 Die Klasse "Exception" besitzt wiederum viele Unterklassen, eine davon ist
"RuntimeException". Instanzen von "RuntimeException" können, müssen aber nicht
abgefangen werden, z. B. eine "ArithmeticException" bei einer möglichen Division durch
Null. Instanzen von Klassen, die nicht Unterklassen von "RuntimeException" sind,
müssen unbedingt abgefangen werden. Methodenaufrufe, die eine solche Exception
eventuell auslösen, lassen sich nicht compilieren, wenn der aufrufende Code mögliche
Laufzeitfehler nicht abfängt oder explizit weiterleitet.
6.2 Laufzeitfehler abfangen und behandeln
 Zum Abfangen einer Exception werden Code-Teile, die eventuell eine Exception
erzeugen, in einen try-Block eingebetten, an dessen Ende eine eventuell auftretende
Exception in einem catch-Block abgefangen und behandelt werden kann.
Beispiel:
public static void main( String[] args )
{
String versuch = "Test";
try
{
versuch = args[ 0 ];
System.out.println( "Es hat funktioniert!" );
}
catch( ArrayIndexOutOfBoundsException ex )
{
System.out.println( "Ein Fehler ist aufgetreten." );
ex.printStackTrace();
// Zeige Position, an der der Fehler aufgetreten ist.
System.out.println( ex.getClass().getName() );
System.out.println( ex.getMessage()
);
}
System.out.println( versuch );
}
HRZ Einführungspraktikum Java
81
IV. Nützliches und Wissenswertes
82
Beachte:
 Es können mehrere catch-Blöcke angegeben werden, um verschiedene Klassen von
Exceptions abzufangen, oder nur eine Superklasse (Exception) wird abgefangen und
dann mit instanceOf überprüft, um welche als Exception es sich handelt. So kann die
Klassenhierarchie der Exception-Arten genutzt werden.
try{ ... }
catch( ArithmeticException ex
){
catch( FileNotFoundException ex ){
... }
... }
try{ ...}
catch ( Exception ex )
{
if ( ex instanceof ArithmeticException
) { ... } else
if ( ex instanceof FileNotFoundException ) { ... }
}
Beispiel:
try{ Thread.sleep( 500 ); /* Schlafe 500 ms */ }
catch( InterruptedException ex ){} // Fehler ignorieren
6.3 Laufzeitfehler weiterleiten
 Es gilt die catch-or-throw-Regel: Exceptions, die nicht RuntimeExceptions sind, müssen
in der Methode, in der sie auftreten können, mit catch behandelt werden, oder die
Methode hat eine entsprechende throws-Anweisung, die die Exception dann wiederum
weitergibt, so daß sie weiter nach oben in der Aufrufhierarchie durchwandert. Dort muß
sie wiederum behandelt oder weitergegeben (catch or throw) werden.
Beispiel:
public void a() throws IOException
{
FileInputStream fis = new FileInputStream( "test.xy" );
int i = fis.read();
System.out.println( i );
}
public void b() throws IOException
{ a(); System.out.println( "Grüsse von b()!" ); }
public void c()
{
try{ b(); }
catch( IOException ex )
{ System.out.println( "Da ging was schief." ); }
}
HRZ Einführungspraktikum Java
82
IV. Nützliches und Wissenswertes
83
6.4 Finally
 Hinter dem catch- oder try- Teil kann auch noch ein finally-Teil angegeben
werden, der immer ausgeführt wird, egal, ob der try-Block normal beendet wurde oder
eine Ausnahme erzeugt wurde:
FileInputStream fis;
try
{
fis = new FileInputStream( "test" );
int i = fis.read(); System.out.println( i );
}
finally
{ if( fis != null ) fis.close(); }
6.5 Eigene Exceptions definieren
 Eigene Exceptions lassen sich durch Ableiten von der Klasse Exception (für unbedingt
abzufangende Fehler) oder RuntimeException (für nicht zwingend abzufangende
Fehler) definieren.
Beispiel:
public class UnsinnException extends RuntimeException
{
public UnsinnException( String nachricht )
{ super( nachricht ); }
}
public class Textverarbeitung
{
public static void verarbeite( String s )
{
if ( s.toLowerCase().indexOf( "unsinn" ) != -1 )
throw new UnsinnException
( "Unsinn wird nicht verarbeitet!" );
System.out.println( s.toUpperCase() );
}
public static void main( String[] args )
{
for( int i = 0; i < args.length; i++ )
{
try{ verarbeite( args[ i ] ); }
catch ( UnsinnException ex )
{ System.out.println( "Fehler bei " + args[ i ]
+ ": " + ex.getMessage() );
}
}
}
}
HRZ Einführungspraktikum Java
83
IV. Nützliches und Wissenswertes
84
HRZ Einführungspraktikum Java
84
V. Applets, Grafik- und Soundausgabe, Ereignisse
85
V.
Applets,
Grafik- und
Soundausgabe,
Ereignisse
HRZ Einführungspraktikum Java
85
V. Applets, Grafik- und Soundausgabe, Ereignisse
86
1. Applets
 Es gilt das "Sandkastenprinzip" bei heruntergeladenen Java-Applets: Das Applet kann in
einem kontrollierten 'Sandkasten' spielen, der Java Virtual Machine des Browsers, darf
diesen aber nicht 'verlassen'.
Was aus dem Netz heruntergeladene Applets nicht dürfen:




Zugriffe auf das Dateisystem des Clients (Schreiben, Lesen von Dateien)
Kommunikation mit beliebigen Servern im Netz
Programme starten oder Kommandos ausführen
Zugriff z. B. auf die Windows Registry
Was Applets dürfen:
 Kommunikation mit dem Heimat-Server über das Netz (z. B. über CGI-Aufrufe, FTP,
HTTP, POP3, SMNP, SNMP, ...)
Beachte:
 In einigen älteren Browsern haben Applets, die lokal von der Festplatte des Clients
geladen werden, mehr Rechte als solche, die über das Netz geladen werden.
 Bei Verwendung der Microsoft-eigenen Java-Erweiterungen für ActiveX kann ein JavaApplet auf alle Windows-Ressourcen zugreifen.
Was Applikationen dürfen: Alles, außer direkt auf Hardware zugreifen!




Kommunikation mit beliebigen Servern über das Netz
Neue Prozesse erstellen, Programme starten, Kommandos ausführen
Native Code ausführen (Java Native Interface): C-Module einbinden
Zugriff auf das Dateisystem
Hinweis:
 Der Sprachumfang des JDK 1.1 und 1.2 bietet weiterführende Konzepte, z .B das
Signieren von Applets. Digital signierten Applets kann man individuelle Rechte
gewähren, z. B. auch den Zugriff auf das lokale Dateisystem des Clients. Leider
verwenden Netscape, Microsoft und Sun hier jeweils unterschiedliche
Signierungstechniken und APIs, so daß man je nach Browser noch unterschiedliche
Verfahren anwenden muß. Die in der Praxis sinnvollste Lösung ist hier die Verwendung
des Java Plug-ins.
HRZ Einführungspraktikum Java
86
V. Applets, Grafik- und Soundausgabe, Ereignisse
87
1.1 Grundgerüst eines Applets
import java.applet.Applet;
import java.awt.Graphics;
public class MyApplet extends Applet
{
public void init()
{
// Wird aufgerufen, wenn das Applet geladen wurde
// Typische Aufgaben hier z. B. Parameter abfragen,
//
Grafik- und Sounddateien laden, ...
}
public void start()
{
// Wird aufgerufen nach init() oder wenn der Benutzer
// zu dieser Webseite zurückkehrt
// Aufgaben z. B. Netzverbindung aufbauen, ...
}
public void stop()
{
// Wird aufgerufen, wenn der Benutzer diese Webseite
// verläßt.
// Aufgaben z. B. Netzverbindung beenden, ...
}
public void destroy()
{
// Wird aufgerufen, wenn das Applet zerstört wird,
// in der Regel bei Beenden des Browsers.
// Wird nur selten angewandt.
}
public void paint( Graphics g )
{
// Applet-Bereich auf der HTML-Seite zeichnen
}
}
HRZ Einführungspraktikum Java
87
V. Applets, Grafik- und Soundausgabe, Ereignisse
88
1.2 Aufruf eines Applets innerhalb einer Webseite
<HTML>
<HEAD>
<TITLE>Applet-Testseite</TITLE>
</HEAD>
<BODY>
Hier kommt das Applet:<P>
<APPLET CODE
CODEBASE
ARCHIVE
WIDTH
HEIGHT
HSPACE
VSPACE
ALIGN
=
=
=
=
=
=
=
=
"MyApplet.class"
Name der Klassendatei
"foo/bar/classes"
Verzeichnis mit class-Dateien
"MyAppletClasses.jar" Archivdatei mit *.class
300
Breite auf der Seite
200
Höhe auf der Seite
10
Horizontaler Abstand um das Applet
10
Vertikaler Abstand um das Applet
LEFT
Ausrichtung zum umgebenden Text,
wie beim <IMG>-Tag in HTML
>
<PARAM NAME="user" VALUE="John Doe"
>
<PARAM NAME="font" VALUE="TimesRoman" >
<PARAM NAME="size" VALUE="36"
>
Parameter
Dieser Text erscheint,
wenn der Browser kein Java versteht.
</APPLET>
<P>Hier kommt der Rest der Seite.
</BODY>
</HTML>
 Parameter können über das <PARAM>-Tag zwischen <APPLET> und </APPLET>
übergeben werden. Beachte, daß Value immer eine Zeichenkette ist und im Gegensatz
zu HTML allgemein die Groß-/Kleinschreibung beim Parameternamen wichtig ist!
HRZ Einführungspraktikum Java
88
V. Applets, Grafik- und Soundausgabe, Ereignisse
89
1.3 Aufruf-Parameter aus der Webseite auslesen
import java.applet.*;
import java.awt.*;
public class MyApplet extends Applet
{
protected Font
f;
protected String name;
public void init()
{
// Parameter auslesen
String userName = getParameter( "user" );
String fontName = getParameter( "font" );
String fontSize = getParameter( "size" );
//
//
if
if
if
Wurden alle Parameter angegeben?
Ansonsten Standardwerte nehmen:
( userName == null ) userName = "Nobody";
( fontName == null ) fontName = "Courier";
( fontSize == null ) fontSize = "12";
// fontSize von String nach int konvertieren:
int fsize = Integer.parseInt( fontSize );
// Zeichensatz-Objekt erzeugen, Instanzvariablen setzen:
f
= new Font( fontName, Font.BOLD, fsize );
name = userName;
}
public void paint( Graphics g )
{
g.setFont( f );
g.setColor( Color.blue );
g.drawString( "Hallo " + name + "!", 10, 50 );
}
}
HRZ Einführungspraktikum Java
89
V. Applets, Grafik- und Soundausgabe, Ereignisse
90
2. Zeichnen mit der Graphics-Klasse
 Das Graphics-Objekt repräsentiert den Zeichenbereich eines Applets.
 Im Koordinatensystem der Graphics-Klasse liegt der Punkt (0,0) oben links!
 Mit der Graphics-Klasse kann man folgende einfache Formen zeichnen:
2.1 Farben setzen und Text ausgeben
public void paint( Graphics g )
{
this.setBackground( Color.red );
Font f = new Font( "TimesRoman", Font.BOLD, 36 );
g.setFont( f );
g.setColor( Color.blue );
g.drawString( "Hallo!", 10, 50 );
g.setColor( Color.yellow );
g.drawString( "Wie geht's?", 10, 100 );
}
 Die Klasse java.awt.Color bietet weitreichende Methoden zum Umgang mit
Farbwerten. Man kann z. B. eine beliebige Farbe durch Angabe ihrer Rot/Grün/BlauAnteile erzeugen:
Color c = new Color( 100, 80, 140 );
g.setColor( c );
HRZ Einführungspraktikum Java
90
V. Applets, Grafik- und Soundausgabe, Ereignisse
91
2.2 Linien und Rechtecke zeichnen
g.drawLine( 10, 10, 50, 50 );
// Linie von (10,10) nach (50,50)
g.drawRect( 5, 10, 45, 50 );
// Rechteck oben links = (5,10) mit Breite 45 u. Höhe 50
g.fillRect( 5, 10, 45, 50 );
// Gefülltes Rechteck
g.drawRoundRect( 5, 10, 45, 50, 10, 10 );
// mit gerundeten Ecken von 10*10 Pixeln im Quadrat
g.fillRoundRect( 5, 10, 45, 50, 10, 10 );
// Gefülltes, gerundetes Rechteck
g.draw3DRect( 10,
// Schattiertes
g.fill3DRect( 10,
// Schattiertes
10, 30, 30, true );
Rechteck (3D-Look), Rechteck erhaben
10, 30, 30, false );
Rechteck (3D-Look), Rechteck vertieft
Hinweis:
Nicht gefüllte Rechtecke sind in Java immer 1 Pixel breiter und höher als gefüllte Rechtecke
bei Verwendung der gleichen Parameter!
2.3 Polygone (Vielecke) zeichnen
int x[] = { 10, 20, 15, 30, 45, 70 };
int y[] = { 10, 15, 30, 40, 30, 40 };
g.drawPolygon( x, y, x.length );
g.fillPolygon( x, y, x.length );
Polygon p = new Polygon( x, y, x.length );
p.addPoint( 10, 10 );
...
g.drawPolygon( p );
g.fillPolygon( p );
2.4 Ovale, Kreise und Ellipsen zeichnen
 Kreise und Ellipsen werden durch das Rechteck definiert, das sie einschließt.
g.drawOval( 10, 10, 30, 50 );
// Ellipse, die genau eingeschlossen wird durch das
// Rechteck, das bei drawRect() mit den gleichen
// Parametern entstehen würde
g.fillOval( 25, 25, 40, 40 );
// Gefülltes Oval, sonst wie oben
// Ist ein Kreis, da Breite = Höhe = 40
// Mitte ist demnach bei (45,45) und Radius = 20
HRZ Einführungspraktikum Java
91
V. Applets, Grafik- und Soundausgabe, Ereignisse
92
2.5 Kreis- und Ellipsenbögen zeichnen
 Die Parameter für Bögen lassen sich am einfachsten bestimmen, in dem man sich den
Bogen zunächst als vollendete Ellipse vorstellt:
g.drawOval( 25, 25, 40, 40 );
// Kreis aus dem obigen Beispiel




Anschließend wird angegeben, ab welchem Gradwert der Bogen zu sehen sein soll:
0 Grad = 3 Uhr = Osten, 90 Grad = 12 Uhr = Norden usw.
Außerdem muß angegeben werden, wieviel Grad der Bogen einnehmen soll:
z. B. 180 Grad für eine halbe "Umrundung" gegen den Uhrzeigersinn, -90 Grad für ein
Viertel im Uhrzeigersinn
g.drawArc( 25, 25, 40, 40, 90, 90 );
// Der Teilbogen des obigen Kreises, der bei 12 Uhr beginnt
// und bei 9 Uhr endet, also das linke obere Viertel
Hinweis:
 Bei all diesen Methoden kann die Liniendicke nicht bestimmt werden!
HRZ Einführungspraktikum Java
92
V. Applets, Grafik- und Soundausgabe, Ereignisse
93
3. Arbeiten mit Fonts
3.1 Font-Objekte erzeugen
 Zur Textausgabe in Applets lassen sich verschiedene Zeichensätze verwenden. Hierzu
dient die Klasse Font.
 Der Font-Konstruktor erwartet als Parameter den Fontnamen, den Stil und die
Schriftgröße in Punkt:
Font f = new Font( "Serif", Font.BOLD, 12 );
 Fontstile sind int-Werte, die als Konstanten in der Klasse Font definiert sind, z .B.
Font.BOLD, Font.PLAIN, Font.ITALIC. Diese lassen sich kombinieren:
Font f = new Font( "Monospaced", Font.BOLD + Font.ITALIC, 8 );
Beachte:
 Die Menge der unterstützten Zeichensätze ist systemabhängig! Um herauszufinden,
welche Fonts vom Laufzeitsystem unterstützt werden, existiert die Methode
getFontList() in der Klasse Toolkit des Paketes java.awt:
String[] fontnames =
Toolkit.getDefaultToolkit().getFontList();
 In allen Java-Systemen sollten die Fonts "Serif", "SansSerif" und
"Monospaced" unterstützt sein. Die Java-Laufzeitumgebung bildet diese symbolischen
Fontnamen auf Systemfonts ab, unter Windows z. B. auf die True-Type-Schriften
"Times New Roman", "Arial" und "Courier".
 Im JDK 1.0 hießen die Standardfonts (statt obiger Bezeichner) "TimesRoman",
"Helvetica" und "Courier".
HRZ Einführungspraktikum Java
93
V. Applets, Grafik- und Soundausgabe, Ereignisse
94
3.2 Zeichensätze verwenden:
Font f1 = new Font( "TimesRoman", Font.BOLD, 36 );
g.setFont( f1 ); // g ist eine Graphics-Instanz
g.drawString( "HRZ", 20, 20 );
Font f2 = g.getFont();
// Gerade aktiven Font ermitteln
String name = f2.getName();
int
size = f2.getSize();
int
style = f2.getStyle(); // 0 = PLAIN, 1 = BOLD,
// 2 = ITALIC, 3 = 1 + 2 :-)
boolean b1 = f2.isPlain();
boolean b2 = f2.isBold();
boolean b3 = f2.isItalic();
3.3 Größeninformationen über Zeichensätze
 Die Klasse FontMetrics enthält Größeninformationen über einen Font, z. B. über die
Maße der Zeichen in einem Font. Damit läßt sich z. B. ermitteln, welche Breite ein Text
mit einem bestimmten Font benötigt:
// g ist eine Graphics-Instanz, z. B. aus paint( Graphics g );
// f2 ist eine Font-Instanz, z. B. erzeugt mit new Font(...)
int breite = g.getFontMetrics( f2 ).stringWidth( "Hallo" );
 Die wichtigsten Methoden der Klasse FontMetrics:
public int charWidth( char c );
// Breite eines Zeichens
public int StringWidth( String s ); // Breite eines Strings
public
public
public
public
int
int
int
int
getAscent();
getDescent();
getHeight();
getLeading();
HRZ Einführungspraktikum Java
//
//
//
//
Oberlänge, vgl. Buchstabe 'H'
Unterlänge, vgl. Buchstabe 'j'
Gesamte Höhe
Zeilenabstand (ohne Font-Höhe)
94
V. Applets, Grafik- und Soundausgabe, Ereignisse
95
4. Verwenden von Bilddateien
 Java ist in der Lage, Grafikdateien vom Typ "GIF" und "JPEG" (die auch von HTML
unterstützten Grafiktypen) direkt darzustellen. Diese werden durch die Klasse Image
realisiert.
4.1 Laden von Images
 Die Klasse Applet besitzt eine Methode, um ein Image aus dem Netz nachzuladen. Ihr
wird eine Instanz der Klasse URL übergeben, das die URL der Grafikdatei enthält:
import java.net.URL;
import java.awt.*;
import java.applet.*;
...
URL
url1 = new URL("http://www.irgendwo.com/bild1.gif" );
Image bild1 = this.getImage( url1 );
 Um die Position des Bildes auf dem Server relativ zur Position des Applets (d. h. der
class-Datei) anzugeben, existiert eine Variante von getImage, die eine URL und
einen dazu relativen Pfadnamen erwartet:
// Position der Bilddatei relativ zur aufrufenden HTML-Seite
URL
url2 = this.getDocumentBase();
Image bild2 = this.getImage( url2, "bild2.jpg" );
// Position relativ zum Verzeichnis der class-Datei(en)
URL
url3 = this.getCodeBase();
Image bild3 = this.getImage( url3, "bilder/bild3.gif" );
 Wird ein Bild nicht gefunden, liefert getImage() den Wert null zurück.
 In Java-Applications kann man Images über die Klasse Toolkit laden:
URL
url4 = new URL( "http://www.irgendwo.de/bild.gif" );
Image bild4 = Toolkit.getImage( url4
);
Image bild5 = Toolkit.getImage( "xy.gif" );
 Ab JDK 1.1 kann man Images als Resource laden, d.h. sie werden wie die Klassen im
Klassenpfad gesucht und automatisch geladen. Das geht im Applet in etwa wie folgt:
URL url = getClass().getResource( "companylogo.gif" );
Image i = createImage( (ImageProducer) url.getContent() );
4.2 Breite und Höhe eines Bildes bestimmen
int bx = bild3.getWidth( this ); // Breite
int by = bild3.getHeight( this ); // Höhe
HRZ Einführungspraktikum Java
95
V. Applets, Grafik- und Soundausgabe, Ereignisse
96
4.3 Anzeigen von Images
 Die Klasse Graphics besitzt überladene Methoden drawImage(), um das Bild
anzuzeigen.
 Die drawImage-Methoden liefern einen boolean-Wert zurück, der angibt, ob alle Bits
des Bildes verfügbar waren.
 Der letzte Parameter von drawImage ist wieder der ImageObserver.
boolean ok;
ok = g.drawImage( bild1, 5,
// Bild mit oberer linker
ok = g.drawImage( bild2, 5,
// Bild auf die Größe von
5, this );
Ecke bei (5,5) ausgeben
5, 100, 120, this );
100 * 120 Pixeln skalieren
 GIF-Bilder erlauben es, sie so abzuspeichern, daß Punkte mit einer bestimmten Farbe als
transparent angesehen werden, d. h. die Grafik ist an diesen Stellen "durchsichtig". Die
obigen Methoden geben diese Bildpunkte ebenfalls transparent aus, d. h. schon in der
Methode gezeichnete Dinge werden durch diese Bildpunkte nicht verändert.
 Alternativ kann man die transparenten Bildpunkte durch eine Farbe einfärben:
ok =
//
ok =
//
g.drawImage(
Transparente
g.drawImage(
Transparente
bild1,
Punkte
bild2,
Punkte
5, 5, Color.blue, this );
blau darstellen
5, 5, 100, 120, Color.blue, this );
blau darstellen und skalieren
4.4 Ladevorgänge überwachen mit der Klasse MediaTracker
import java.applet.*;
import java.awt.*;
import java.net.*;
public class ImageApplet extends Applet
{
protected Image bild;
public void init()
{
URL dir = this.getDocumentBase();
bild = this.getImage( dir, "bild.jpg" );
MediaTracker mt = new MediaTracker( this );
mt.addImage( bild, 0 );
try{ mt.waitForAll(); }
catch( Exception ex )
{ System.out.println( "Fehler beim Laden des Bildes!"); }
}
public void paint( Graphics g )
{ if( bild != null ) g.drawImage( bild, 0, 0, this ); }
}
HRZ Einführungspraktikum Java
96
V. Applets, Grafik- und Soundausgabe, Ereignisse
97
5. Ausgabe von Audiodateien
 Java unterstützt das direkte Abspielen von Audiodateien, die im AU-Format vorliegen.
Dies ist ein Sun-eigenes Format, dessen Dateien zum Preis einer geringeren Tonqualität
relativ klein sind.
 Im Internet findet man Konvertierungsprogramme, um z. B. WAV-Dateien in das AUFormat umzuwandeln.
5.1 Direktes Laden und Abspielen von Audiodateien
 Über die Methode play() der Klasse Applet lassen sich analog zum Vorgehen bei
getImage() AU-Dateien herunterladen und unmittelbar abspielen:
URL url1 =
this.play(
URL url2 =
this.play(
new URL( "http://www.irgendo.com/ton.au" );
url1);
this.getDocumentBase();
url1, "sounds/spacemusic.au" );
5.2 AudioClip-Instanzen erzeugen und abspielen
 Will man den Sound wiederholt verwenden, kann man analog zur Klasse Image
Audiodateien als Instanzen der Schnittstelle AudioClip erzeugen:
URL url3 = this.getDocumentBase();
AudioClip sound = this.getAudioClip( url3, "spacemusic.au" );
sound.play(); // einmaliges Abspielen
sound.loop(); // wiederholtes Abspielen
sound.stop(); // Abspielen stoppen
Beispiel: Hintergrundmusik für die Webseite
import java.applet.*;
import java.net.*;
public class AudioApplet extends Applet
{
protected AudioClip sound;
public void init()
{
URL dir = this.getDocumentBase();
sound = this.getAudioClip( dir, "spacemusic.au" );
}
public void start() { sound.loop(); }
public void stop() { sound.stop(); }
}
HRZ Einführungspraktikum Java
97
V. Applets, Grafik- und Soundausgabe, Ereignisse
98
6. Auf Ereignisse reagieren
 Um eine graphische Oberfläche realisieren zu können, muß das System dem Programm
eine Mitteilung senden, sobald bestimmte Ereignisse auftreten (Mausklick, Taste
losgelassen, ...).
 In Java dient dazu der Event-Mechanismus, der durch die Klassen im Paket
java.awt.event realisiert wird. Den verschiedenen Ereignissen entsprechen Klassen
in diesem Paket, deren gemeinsame Superklasse die Klasse AWTEvent ist und die in
einer Hierarchie zueinander stehen.
 Komponenten, die Ereignisse auslösen (also Event-Objekte erzeugen) werden
Ereignisquellen genannt. Ein Button löst z. B. einen ActionEvent aus, wenn er
gedrückt wird, eine Mausbewegung in einer Komponente löst einen MouseEvent aus.
 Man kann nun auf Ereignisse reagieren, indem man für bestimmte Ereignisse
Ereignisempfänger (Event Listeners) bei der Komponente anmeldet. Ereignisempfänger
sind Klassen, die ein zu einem Ereignistyp passendes Interface implementieren, dessen
Methoden das System dann bei Auftreten des Ereignisses aufruft. Diese ListenerInterfaces sind Subklassen von EventListener.
 Dieses Modell wird ab JDK 1.1 verwendet und wird Delegation Event Model genannt,
da es die Möglichkeit bietet, die Ereignisverarbeitung einer Komponenten beliebige
andere Klassen zu delegieren.
Beispiele anhand von Mausereignissen:
 Komponenten, z. B. Applets, lösen MouseEvents aus, wenn ein Mausereignis auftritt. Um
Mausereignisse zu verarbeiten, registriert man bei der Komponente MouseListener oder
MouseMotionListener, das sind Klassen, die das entsprechende Interface implementieren.
Tritt das Ereignis auf, wird die entsprechende Methode der registrierten Listener
aufgerufen und ihr eine Instanz der Klasse MouseEvent übergeben, die Details über das
Ereignis enthält.
 Die Menge der registrierten Listener kann für eine Komponente über entsprechende
add/remove-Anweisungen verändert werden. Es ist also auch möglich, mehr als einen
Listener für ein bestimmtes Ereignis zu registrieren.
HRZ Einführungspraktikum Java
98
V. Applets, Grafik- und Soundausgabe, Ereignisse
99
 Bei einem Mausereignis ruft die Ereignisquelle z. B. die Methode mouseClicked() des
MouseListeners auf:
public void mouseClicked( MouseEvent e )
{
int x
= e.getX();
// Wo?
int y
= e.getY();
Point p
= e.getPoint();
int clickCount = e.getClickCount(); // Doppelklick?
int mods
= e.getModifiers(); // Welche Maustaste?
int buttonNr;
if( ( mods & InputEvent.BUTTON3_MASK) != 0 )
buttonNr = 3;
else if( ( mods & InputEvent.BUTTON2_MASK) != 0 )
buttonNr = 2;
else if( ( mods & InputEvent.BUTTON1_MASK) != 0 )
buttonNr = 1;
// Weitere Codezeilen, um auf das Ereignis zu reagieren...
}
HRZ Einführungspraktikum Java
99
V. Applets, Grafik- und Soundausgabe, Ereignisse
100
6.1 Die Komponente 'hört sich selbst zu'
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class MausApplet extends Applet
implements MouseListener, MouseMotionListener
{
public void init()
{
this.addMouseListener( this );
this.addMouseMotionListener( this );
}
// Methoden des MouseListener Interfaces:
public void mouseClicked( MouseEvent e )
{
int x = e.getX();
int y = e.getY();
Graphics g = getGraphics();
g.drawOval( x - 2, y - 2, 4, 4 );
g.dispose();
}
public void mousePressed( MouseEvent e ){}
public void mouseReleased( MouseEvent e ){}
public void mouseEntered( MouseEvent e ){}
public void mouseExited( MouseEvent e ){}
// Methoden des MouseMotionListener Interfaces:
public void mouseDragged( MouseEvent e ){}
public void mouseMoved( MouseEvent e ){}
}
HRZ Einführungspraktikum Java
100
V. Applets, Grafik- und Soundausgabe, Ereignisse
101
6.2 Eine andere Klasse hört zu:
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class MausApplet extends Applet
{
public void init()
{
MouseListener ml = new MausLauscher();
this.addMouseListener( ml );
}
}
class MausLauscher implements MouseListener
{
...
// Methoden des MouseListener Interfaces:
public void mousePressed( MouseEvent e ){}
public void mouseReleased( MouseEvent e ){}
...
}
6.3 Arbeiten mit Adapter-Klassen:
 Da Listener Interfaces sind, ist man gezwungen, alle Methoden des Interfaces zu
implementieren, auch wenn wan vielleicht nur einige Methoden benötigt und nicht auf
alle Ereignisse reagieren will.
 Daher stellt Java sogenannte Adapter-Klassen für die Listener zur Verfügung, die mehr
als eine Methode anbieten. Diese Adapter-Klassen besitzen alle Methoden des
entsprechenden Interfaces, die aber einfach nichts tun, also leer sind. Durch Ableiten einer
Klasse von einem Adapter kann man die leeren Methoden so einfach erben, statt sie selbst
noch einmal aufführen zu müssen:
class MausLauscher
extends MouseAdapter // bzw. MouseMotionAdapter bei Bedarf
{
// Überschreibe das leere mousePressed von MouseAdapter
public void mousePressed( MouseEvent e )
{
...
}
// Der Rest wird geerbt.
}
HRZ Einführungspraktikum Java
101
V. Applets, Grafik- und Soundausgabe, Ereignisse
102
6.4 Arbeiten mit Inner Classes
 Ab JDK 1.1 hat man die Möglichkeit, eine Klasse innerhalb einer anderen Klasse zu
definieren (Inner Class). Diese Klasse ist dann nur innerhalb der definierenden Klasse
benutzbar und daher lokal.
 Instanzen einer Inner Class haben Zugriff auf die Methoden und Variablen der Klasse, der
sie gehören, bzw. des Blockes, in dem sie definiert sind.
 Dieses Konstrukt wird sehr oft wie folgt zur Ereignisverarbeitung verwendet:
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class MausApplet extends Applet
{
public void init()
{
this.addMouseListener( new LokalerMausLauscher() );
}
class LokalerMausLauscher extends MouseAdapter
{
public void mousePressed( MouseEvent e )
{
int x = e.getX();
int y = e.getY();
Graphics g = getGraphics();
g.fillRect( x, y, 2, 2 );
g.dispose();
}
}
}
HRZ Einführungspraktikum Java
102
V. Applets, Grafik- und Soundausgabe, Ereignisse
103
6.5 Anonyme innere Klassen
 Eine Variante lokaler Klassen sind anonyme Klassen. Diese Klassen werden innerhalb
einer Anweisung definiert, in einer Kombination aus new, der Angabe einer Oberklasse
und der Definition der Variablen und Methoden der Klasse. Das sieht dann etwa wie folgt
aus:
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class MausApplet
extends Applet
{
public void init()
{
this.addMouseListener(
new MouseAdapter() // anonyme Subklasse von MouseAdapter
{
public void mousePressed( MouseEvent e )
{
int x = e.getX();
int y = e.getY();
Graphics g = getGraphics();
g.fillRect( x, y, 2, 2 );
g.dispose();
}
}
); // Ende Aufruf addMouseListener
}
}
HRZ Einführungspraktikum Java
103
V. Applets, Grafik- und Soundausgabe, Ereignisse
104
6.6 Auf Tastaturereignisse reagieren
 Tastaturereignisse lösen in einer Komponente einen KeyEvent aus, wenn diese den
Eingabefocus besitzt.
 Entsprechend existiert ein KeyAdapter, Methoden addKeyListener und
removeKeyListener und ein KeyListener-Interface, das die folgenden Methoden
besitzt:
void keyTyped
( KeyEvent e ); // UniCode-Taste getippt
void keyPressed ( KeyEvent e ); // Taste gedrückt
void keyReleased( KeyEvent e ); // Taste losgelassen
 Eine Instanz von KeyEvent besitzt die folgenden Methoden:
 Jeder Taste ist ein Tastencode zugeordnet:
int code = e.getKeyCode(); // Tastencode
if( code = KeyEvent.VK_F1 )
System.out.println( "You pressed F1, need some help?" );
 Die statische Methode getKeyText liefert die Beschriftung der Taste:
String label = KeyEvent.getKeyText( code ); // label = "F1"
 Die statische Methode getKeyModifiersText liefert die Modifier-Label:
String mods = KeyEvent.getKeyModifiersText( code );
// mods = "Ctrl+Shift" etc.
 Die Methode getKeyChar liefert das getippte Zeichen:
if( code != KeyEvent.CHAR_UNDEFINED )
char c = e.getKeyChar(); // UniCode-Zeichen der Taste
6.6.1 Die Klasse InputEvent
 Die Klasse InputEvent ist die gemeinsame Basisklasse von MouseEvent und
KeyEvent und besitzt noch einige weitere Methoden, die sich also sowohl bei
MouseEvents als auch bei KeyEvents abfragen lassen:
boolean
boolean
boolean
boolean
isShiftDown();
isAltDown();
isControlDown();
isMetaDown();
HRZ Einführungspraktikum Java
//
//
//
//
true,
true,
true,
true,
falls
falls
falls
falls
Shift
Alt
CTRL
Meta
gedrückt
gedrückt
gedrückt
gedrückt
war
war
war
war
104
VI. Graphische Benutzeroberflächen mit dem AWT
105
VI.
Graphische
Benutzeroberflächen
mit dem AWT
HRZ Einführungspraktikum Java
105
VI. Graphische Benutzeroberflächen mit dem AWT
106
1. Grundlagen graphischer Oberflächen
 Graphische Benutzeroberflächen können in Java mit Hilfe des Paketes java.awt
erzeugt werden. Dieses Paket beinhaltet das Abstract Windowing Toolkit, das es
ermöglicht, auf Elemente wie z. B. Buttons oder Checkboxes systemunabhängig
zuzugreifen.
 Dies wird ermöglicht, indem für jedes Element einer Oberfläche (Fenster, Knopf, ...) eine
sie abbildende Klasse existiert, die durch das Laufzeitsystem implementiert werden muß.
Dies ist Aufgabe der Schnittstellensammlung im Paket java.awt.peer.
 Die Elemente der Oberfläche sehen daher immer so aus, wie sie in der Regel auch auf
dem jeweiligen System erscheinen, abhängig davon, wo das Java-Programm ausgeführt
wird.
 Sowohl Applets, als auch Applications können eine graphische Oberfläche besitzen,
wobei Applets AWT-Grundelemente direkt im Appletbereich positionieren können,
während Applications dazu erst ein Fenster erstellen müssen.
1.1 Die Bausteine des AWT
Die Bausteine des AWT kann man in vier Kategorien aufteilen:
 Einfache Komponenten, wie z. B. Buttons, Checkboxes und Labels, mit deren Hilfe
der Benutzer letztendlich das Programm bedient
 Container, wie z. B. Fenster , Panels und Applets, die die Aufgabe haben, die
Komponenten in sich aufzunehmen.
 LayoutManager, die für die Ausrichtung und Anordnung von Komponenten in einem
ihnen zugeordneten Container verantwortlich sind.
 Events, die von Komponenten erzeugt werden, wenn bestimmte Ereignisse wie z. B.
das Drücken eines Buttons auftreten, und durch entsprechende EventListener
verarbeitet werden können.
 Fast alle Elemente des AWT sind direkte oder indirekte Subklassen der abstrakten Klasse
Component. Diese Klasse besitzt Methoden, die an jede Subklasse vererbt werden, z. B.
die Funktionalität, Maus- und Tastaturereignisse auszulösen und angezeigt oder verborgen
zu werden. Hier ein Ausschnitt aus der Klassenhierarchie:
HRZ Einführungspraktikum Java
106
VI. Graphische Benutzeroberflächen mit dem AWT
107
1.2 Arbeiten mit einfachen Komponenten
1.2.1 Die Klasse Label
 Label dienen der Beschriftung von Elementen der Oberfläche, z. B. zur Beschriftung eines
Texteingabefeldes:
Label l1
Label l2
Label l3
// Mit
= new Label(); // Leere Beschriftung (Platzhalter)
= new Label( "ArtikelNr:" );
= new Label( "ArtikelNr:", Label.RIGHT );
Ausrichtung: LEFT, RIGHT, CENTER als int-Konstante
String t = l1.getText();
l1.setText( "Eingabe:" );
// Beschriftung holen
// Beschriftung setzen
int i = l1.getAlignment();
// Ausrichtung holen
l1.setAlignment( Label.CENTER ); // Ausrichtung setzen
1.2.2 Die Klasse Button
 Buttons realisieren Knöpfe, die gedrückt bzw. angeklickt werden können und dabei ein
entsprechendes Ereignis auslösen:
Button b = new Button( "Abbrechen" );
String t = b.getLabel();
b.setLabel( "Cancel" );
// Beschriftung holen
// Beschriftung setzen
1.2.3 Die Klasse Checkbox
 Checkboxes sind Schalter-Felder, die durch Anklicken aktiviert oder deaktiviert werden
können und eine eigene Beschriftung besitzen können:
Checkbox c1 = new Checkbox(); // Unbeschriftet
Checkbox c2 = new Checkbox( "mit Mayo, bitte!" );
String t = c1.getLabel();
c1.setLabel( "Mit Ketchup" );
// Beschriftung holen
// Beschriftung setzen
boolean angekreuzt = c1.getState(); // Status holen
c1.setState( true );
// Status setzen
HRZ Einführungspraktikum Java
107
VI. Graphische Benutzeroberflächen mit dem AWT
108
1.3 Arbeiten mit Containern
 Container-Instanzen haben die Aufgabe, Elemente der Oberfläche, wie z. B. Buttons in
sich aufzunehmen.
 Container ist eine abstrakte Klasse. Entsprechend den verschiedenen Arten von
Containern existieren die Subklassen Panel, ScrollPane (seit JDK 1.1) und
Window.
 Die Klasse Window ist die Superklasse für Container, die auf dem Bildschirm bewegbar
sind und in einem eigenen Fenster dargestellt werden. Es existieren die Subklassen
Frame und Dialog.
 Die Klasse ScrollPane ist ein besonderer Container, der die in ihm enthaltene
Komponente automatisch mit Scrollbalken versieht, um den sichtbaren Bereich der
Komponente, z. B. eines Bildes, zu verändern.
 Die Klasse Panel ist ein Container, der im Gegensatz zu einem Window fest an einer
bestimmten Position der Oberfläche fixiert ist. Da ein Container auch wie die einfachen
Komponenten eine Subklasse von Component ist, lassen sich Panels und ScrollPanes
ineinander verschachteln, was vielfältige Layout-Möglichkeiten bietet. Da jedes Panel
seinen eigenen Layout-Manager besitzt, lassen sich so komplexe Anordnungen
realisieren. Außerdem kann man durch Vererbung eigene Panel-Subklassen erzeugen und
seine Oberflächen damit aus wiederverwendbaren Teilen zusammensetzen (Beispiele
folgen).
 Die Klasse Applet ist eine Subklasse von Panel. Daher ist jedes Applet auch
gleichzeitig ein Container, so daß sich in einem Applet auch AWT-Komponenten
anordnen lassen. Applets besitzten gegenüber normalen Panels nur die bereits
kennengelernten zusätzlichen Eigenschaften, wie z. B. mit dem Browser interagieren zu
können( init(), start(), stop() usw.).
 Über die Methoden add() und remove() lassen sich Komponenten zu einem
Container hinzufügen bzw. entfernen, so daß man auch dynamisch die Bestandteile der
Oberfläche verändern kann.
Beispiel:
public class GUIApplet extends Applet
{
protected Button
b;
protected Checkbox c;
public void init()
{
b = new Button( "Hit Me!" );
c = new Checkbox( "Diesen Unsinn nicht mehr anzeigen" );
add( b );
add( c );
}
}
Hinweis:
 Das Positionieren der Elemente ist Aufgabe eines sog. Layout-Managers. Mehr dazu
später!
HRZ Einführungspraktikum Java
108
VI. Graphische Benutzeroberflächen mit dem AWT
109
1.4 Auf Ereignisse in der Oberfläche reagieren
1.4.1 Auf Buttons reagieren
 Wenn ein Button angeklickt wird, wird ein ActionEvent erzeugt, den ein registrierter
ActionListener in einer Methode actionPerformed() als Parameter erhält.
public class Buttons extends Applet implements ActionListener
{
protected Button bBlau, bRot;
public void init()
{
bBlau = new Button( "Blau" );
bRot = new Button( "Rot" );
add( bBlau );
add( bRot );
bBlau.addActionListener( this );
bRot .addActionListener( this );
}
public void actionPerformed( ActionEvent e )
{
Graphics g = getGraphics();
g.setColor(
( e.getSource() == bBlau ? Color.blue : Color.red ) );
g.drawRect( 0, 0, 100, 100 );
g.dispose();
}
}
1.4.2 Auf Checkboxes unmittelbar reagieren
public class Ankreuzen extends Applet implements ItemListener
{
protected Checkbox c;
public void init()
{
c = new Checkbox( "Diesen Unsinn nicht mehr anzeigen" );
c.addItemListener( this );
add( c );
}
public void itemStateChanged( ItemEvent e )
{
System.out.println( "Zustand von c hat sich geändert" );
}
}
HRZ Einführungspraktikum Java
109
VI. Graphische Benutzeroberflächen mit dem AWT
110
1.5 Arbeiten mit Texteingabe-Komponenten
1.5.1 Die Klasse TextField
 Diese Klasse stellt ein einzeiliges Eingabefeld für Text zur Verfügung.
 Es ist möglich, statt der Eingabe ein anderes Zeichen als Echo auszugeben (sinnvoll bei
Feldern, die z. B. Passwörter abfragen).
 Auch der Zugriff auf den markierten Teil der Eingabe ist möglich.
TextField anlegen
TextField
TextField
TextField
TextField
tname
tname
tname
tname
=
=
=
=
new
new
new
new
TextField();
// Leer
TextField( 20 );
// Breite 20
TextField( "Willi" );
// Mit Vorgabe
TextField( "Willi", 20 );
Echo-Zeichen setzen und abfragen
TextField tpasswd = new TextField( 20 );
tpasswd.setEchoChar( '*' );
char c;
if ( tpasswd.echoCharIsSet() ) c = tpasswd.getEchoChar();
Text abfragen und setzen
String name = tname.getText();
tname.setText( "Hallo Welt!" );
Markierten Textteil abfragen und Markierungsbereich setzen
String markiert = tname.getSelectedText();
int von
= tname.getSelectionStart();
int bis
= tname.getSelectionEnd();
tname.select( 0, 10 ); // Markiert die ersten 10 Zeichen
tname.selectAll();
// Markiert alles
Cursorposition abfragen und setzen
int pos = tname.getCaretPosition();
// Cursor hinter den letzten Buchstaben setzen:
tname.setCaretPosition( tname.getText().length() );
Textfeld aktivieren und deaktivieren
tname.setEditable( false ); // Keine Eingabe möglich, grau
if ( tname.isEditable() ) doSometing();
HRZ Einführungspraktikum Java
110
VI. Graphische Benutzeroberflächen mit dem AWT
111
1.5.2 Die Klasse TextArea
 Während ein TextField für eine einzeilige Information gedacht ist, stellt eine TextArea
einen größeren, rechteckigen Bereich für Textein-/ausgabe zur Verfügung, der auch mit
endsprechenden Scrollbalken ausgestattet ist.
TextArea anlegen
TextArea guestbook = new TextArea();
TextArea guestbook = new TextArea( "Mit Vorgabe" );
TextArea guestbook = new TextArea( 5, 50 ); // Zeilen, Sp.
TextArea guestbook = new TextArea( "Mit Vorgabe", 5, 50 );
TextArea guestbook = new TextArea( "Mit Vorgabe", 5, 50,
SCROLLBARS_HORIZONTAL_ONLY ); // etc., siehe API-Doku...
Textinhalt verändern
guestbook.append( "Killroy was here" );
guestbook.insert( "me too!", 30 );
// Text an Position 30 einfügen
guestbook.replaceRange( "Test", 18, 24 );
// Zeichen 18 bis 23 durch "Test" ersetzen
Weitere Methoden
 TextArea und TextField sind Subklassen von TextComponent. Aus diesem
Grunde stehen die bereits zuvor bei TextField erklärten Methoden bis auf die
Methoden zur Behandlung von Echo-Zeichen auch für eine TextArea zur Verfügung,
denn sie werden aus TextComponent vererbt.
Ereignisse bei Textkomponenten
 Wenn innerhalb einer TextComponent die Enter-Taste gedrückt wird, wird ein
ActionEvent erzeugt. In diesem Fall liefert die Methode getActionCommand()
der ActionEvent den eingegebenen Text, getSource() liefert die auslösende
TextComponent (vgl. Button-Beispiel).
 Wenn sich der Text in einer TextComponent verändert, erzeugt dies jedesmal einen
TextEvent. Als TextListener implementiert man die entsprechende Methode
textValueChanged( TextEvent e);
HRZ Einführungspraktikum Java
111
VI. Graphische Benutzeroberflächen mit dem AWT
112
2. Arbeiten mit Layout-Managern
2.1 Allgemeines zu Layout-Managern
 Jeder Container besitzt einen ihm zugeordneten Layout-Manager. Dieser hat die Aufgabe,
die Komponenten in dem Container nach bestimmten Regeln anzuordnen und dabei auch
ihre Größe festzulegen.
 Um eine plattformunabhängige Lösung zu ermöglichen, sind im Paket java.awt nur
Layout-Manager zur Verfügung gestellt, die relative Positionierungsangaben erlauben. Es
ist jedoch möglich, eigene Layout-Manager zu schreiben, die auch direkte
Positionierungen an bestimmten Koordinaten erlauben. Borland JBuilder besitzt z. B.
einen derartigen LayoutManager XYLayout.
 Java bietet die fünf Layout-Manager FlowLayout, BorderLayout,
GridLayout, GridBagLayout und CardLayout.
 Durch Aufruf der Methode Container.setLayout() wird ein LayoutManager für einen
Container festgelegt. Dazu wird eine Instanz des LayoutManagers erzeugt und als
Parameter übergeben. Der LayoutManager interagiert selbständig mit dem Container, um
das Layout durchzuführen.
Beispiel:
import java.awt.*; import java.applet.*;
public class GUIApplet extends Applet
{
protected Button b;
public void init()
{
setLayout( new BorderLayout() ); // Layout festlegen
b = new Button( "Hit Me!" );
// Komponente erzeugen
add( BorderLayout.CENTER, b );
// Komponente hinzufügen
}
}
2.2 FlowLayout
 FlowLayout ist das Standard-Layout der Container.
 In diesem sehr einfachen Layout werden die Komponenten bei jedem add() einfach der
Reihe nach in einer Zeile hintereinander angeordnet, bis der rechte Rand erreicht ist. Dann
erfolgt quasi ein Zeilenumbruch. Die Anordnung innerhalb der Zeilen kann wie folgt
beeinflußt werden:
setLayout( new FlowLayout() ); // Default: Zeilen zentrieren
setLayout( new FlowLayout( Ausrichtung ) );
// FlowLayout.LEFT, FlowLayout.CENTER, FlowLayout.RIGHT
setLayout( new FlowLayout( Ausrichtung, h, v );
// Zwischen den Komponenten h Pixel horizontal, v Pixel
// vertikaler Abstand (Ohne Angabe jeweils 5 Pixel)
HRZ Einführungspraktikum Java
112
VI. Graphische Benutzeroberflächen mit dem AWT
113
2.3 BorderLayout
 Dieses Layout ist gut geeignet, um bis zu fünf Komponenten in einem Container am
linken, rechten, oberen und unteren Rand und im Zentrum anzuordnen.
 Der Platz für leere Teile des BorderLayouts darf beliebig schrumpfen, um für die anderen
Komponenten Platz zu schaffen.
setLayout( new BorderLayout() );
setLayout( new BorderLayout( 10, 10 ) );
// 10 * 10 Pixel Abstand zwischen den Bereichen
 Bei Aufruf von add() wird mit einer Richtungsangabe angezeigt, wo die Komponente
platziert werden soll:
add( BorderLayout.NORTH, new Label( "Hier ist oben" ) );
add( BorderLayout.CENTER, new Label( "Hier die Mitte" ) );
2.4 GridLayout
 Bei einem GridLayout wird der Container-Bereich tabellenartig in ein Gitter unterteilt.
Jede Zelle des Gitters ist gleich groß.
setLayout( new GridLayout( 3, 2 ) );
// Gitter mit drei Zeilen und zwei Spalten
setLayout( new GridLayout( 3, 2, 10, 10 ) );
// 10 * 10 Punkte Abstand zwischen den Zellen
 Beim Füllen des Containers wird oben links begonnen und bei jedem add() die jeweils
nächste Zelle benutzt.
 Zellen lassen sich "überspringen", indem man in ihnen z. B. ein leeres Label einfügt.
HRZ Einführungspraktikum Java
113
VI. Graphische Benutzeroberflächen mit dem AWT
114
2.5 GridBagLayout
 GridBagLayout ist der flexibelste Layout-Manager. Auch hier wird der
Containerbereich in ein Gitter unterteilt, jedoch kann man einzelne Komponenten direkt in
eine bestimmte Zelle positionieren und hat wesentlich mehr Steuerungsmöglichkeiten.
 Die Größe der einzelnen Zellen hängt von den verwendeten Komponenten und
Parametern ab. Am ehesten ist das Verhalten eines GridBagLayouts mit dem einer
HTML-Tabelle vergleichbar, was die Ausrichtungsmöglichkeiten und Reaktion auf nicht
benutzte Zellen, Zeilen und Spalten und die Berechnung der Zellengrößen betrifft.
Anordnung der Komponenten
 Die Anordnung der Komponenten erfolgt nicht direkt, sondern mit Hilfe eines
zusätzlichen Objektes vom Typ GridBagConstraints.
 Zunächst muß eine Instanz von GridBagConstraints erzeugt werden. Anschließend
werden die Instanzvariablen dieses Objektes angepaßt und es wird beim Aufruf von add()
mit übergeben:
public void init()
{
...
// Erzeuge und setze GridBagLayout
GridBagLayout gbl = new GridBagLayout();
setLayout( gbl );
...
GridBagConstraints gbc = new GridBagConstraints();
...
// Setze Parameter für die Komponente
gbc.fill
= GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.gridx
= 2;
gbc.gridy
= 1; // usw., siehe API-Dokumentation
...
// Füge die Komponente mit diesen Parametern hinzu
Button bOk = new Button( "Ok" );
gbl.setConstraints( bOk, gbc );
add( bOk );
...
}
 Die GridBagConstraints-Instanz muß nicht für jede hinzuzufügende Komponente neu
erzeugt werden, sondern kann für alle Komponenten wiederverwendet werden, da der
Layout-Manager sich beim Aufruf von setConstraints() 'Kopien' der gesetzten
Werte macht:
... // Nach Einfügen des Buttons bOk geht es weiter:
gbc.gridx
= 3;
Button bAbbr = new Button( "Abbrechen" );
gbl.setConstraints( bAbbr, gbc );
add( bAbbr );
HRZ Einführungspraktikum Java
114
VI. Graphische Benutzeroberflächen mit dem AWT
115
 Es lassen sich die folgenden Instanzvariablen eines GridBagConstraints setzen:
public int gridx;
X-Koordinate der Zielzelle, die erste Zelle hat den Index 0, int-Wert oder
GridBagConstraints.RELATIVE = hinter der zuvor hinzugefügten Komponente plazieren
public int gridy;
Entsprechend für die Y-Koordinate...
public int gridwidth;
Breite des Darstellungsbereiches, als Anzahl der überspannenden Zellen, int-Wert oder
GridBagConstraints.REMAINDER = Komponente als letzte ihrer Zeile plazieren
GridBagConstraints.RELATIVE = Komponente als vorletzte ihrer Zeile plazieren
public int gridheight;
Entsprechend für die Höhe des Darstellungsbereiches...
public int fill;
Anpassung der Komponentengröße an die ihres Darstellungsbereiches, falls dieser
mehr Platz bietet, als eigentlich nötig ist:
GridBagConstraints.NONE, HORIZONTAL, VERTICAL, BOTH
public int anchor;
Verankerung der Komponente in ihrem Darstellungsbereich, falls dieser mehr Platz bietet,
als eigentlich nötig ist:
GridBagConstraints.CENTER, NORTH, NORTHEAST, EAST, usw.
public double weightx;
public double weighty;
Gewichtung dieser Komponente bei der Vergabe von zusätzlich verfügbarem Platz, relativ
für die horizontale und vertikale Anpassung
public int ipadx;
public int ipady;
Innerer leerer Rand um die Komponente in Pixeln, vergrößert ihre minimale Größe
public Insets insets;
Äußerer Mindestabstand zwischen Komponente u. dem Rand ihres Darstellungsbereiches
Beispiel:
HRZ Einführungspraktikum Java
115
VI. Graphische Benutzeroberflächen mit dem AWT
116
2.6 CardLayout
 CardLayout ist in gewisser Weise ein Sonderfall. Er teilt den Container in einer
zusätzlichen Dimension auf und ermöglicht es, ähnlich wie unter einer Karteikarte die
Komponenten abzulegen. Dies sind in der Regel Panels oder Canvas-Instanzen (mehr
zu diesen Klassen später).
 Beim Aufruf der add-Methode wird der Name der Karteikarte mit übergeben.
setLayout( new CardLayout() );
Panel one = new Panel();
// hier würde man noch Komponenten dem Panel one hinzufügen...
// ...
// Karte unter dem Namen "eins" hinzufügen:
add( "eins", one );
Panel two = new Panel();
add( "zwei", two );
Panel three = new Panel();
add( "drei", three );
//...
//...
 Es sind nicht alle Karten zeitgleich zu sehen, sondern es ist immer nur eine im
Vordergrund. Die anderen Karten lassen sich dann vergleichbar mit einer Diaschau bei
Bedarf in den Vordergrund bringen, es kann auch 'geblättert' werden:
show( this, "zwei" ); // Karte "zwei" anzeigen
show( this, "drei" ); // Karte "drei" anzeigen
next( this );
// Nächste Karte anzeigen
previous( this ); // Zurück zur vorhergehenden Karte
first( this );
// Sprung zur ersten Karte
last( this );
// Sprung zur letzten Karte
Beachte:
 Auf der Oberfläche selbst sind keine Karteikartenreiter mit den entsprechenden Labels zu
sehen! Die Labels dienen nur anwendungsintern der Unterteilung in verschiedene
Bereiche.
2.7 Arbeiten ohne LayoutManager
 Mit setLayout( null ) kann man erreichen, daß für diesen Container kein
LayoutManager verwendet wird. Man muß dann selbst die Größe und Position aller
Komponenten im Container festlegen. Dies geschieht durch Aufruf der Methode
setBounds( int x, int y, int width, int height) der Komponente:
setLayout( null );
Button b = new Button( "Klick mich" );
b.setBounds( 20, 20, 100, 100 ); // Geerbt von Component
add( b );
HRZ Einführungspraktikum Java
116
VI. Graphische Benutzeroberflächen mit dem AWT
117
3. Mehr über Komponenten
3.1 Allgemeine Eigenschaften von Komponenten
 Nahezu alle AWT-Klassen sind Subklassen der Klasse Component und erben damit
deren Eigenschaften. Dazu gehört z. B. die Möglichkeit, Mauscursor, Standard-Font und
Farben zu setzen etc.
 Auch die im Applet verwendeten Methoden paint(), repaint(), update() etc.
sind von Component geerbt. Klassen können die Methode paint() überschreiben,
um ihre Darstellung auf der Oberfläche zu zeichnen. Im Fall eines Containers wird
zunächst dessen (standardmäßig leeres) paint() aufgerufen und danach erst die
enthaltenen Komponenten gezeichnet. Überschreibt man paint() für einen Container
(Applet-Beispiele!) und fügt dann Komponenten hinzu, überlagern diese also den durch
paint() gezeichneten Hintergrund.
 Nützliche Methoden der Klasse Component:
// c sei eine Komponente, z. B. ein Button
c.setCursor( new Cursor( Cursor.WAIT_CURSOR ) );
// Eieruhr-Cursor als aktuellen Cursor setzen
// DEFAULT, CROSSHAIR, MOVE, TEXT, WAIT sind möglich
c.setBackground( Farbe );
c.setForeground( Farbe );
// Vorder- und Hintergrundfarbe
c.setFont( Font );
// Standardfont setzen
c.setVisible( boolean );
// Ein- und Ausblenden der Komponente
c.setEnabled( boolean );
// Eingabemöglichkeit einstellen, z. B. bei einem Button
// Setzen auf false verhindert die Auslösung eines Events
3.2 Ereignisverarbeitung von Komponenten
 Die bereits behandelten Key- und Mouse-Events stehen in gleicher Weise auch für jede
andere Component zur Verfügung, so daß man sich dafür dort registrieren kann.
 Beim Verschieben, Ändern der Größe, Ein- und Ausblenden einer Komponente entsteht
ein ComponentEvent, für den man sich bei der Komponente als
ComponentListener registrieren lassen kann. ComponentListener implementieren
die entsprechenden Methoden componentShown(), componentHidden(),
componentMoved() und componentResized(). Durch Aufruf der Methode
getComponent() des ComponentEvents kann man die auslösende Komponente
ermitteln.
 Beim Wechsel des Eingabefocus entsteht in den betroffenen Komponenten ein
FocusEvent, für den man sich als FocusListener registrieren kann. Die
entsprechenden Methoden lauten focusGained() und focusLost(). Den
übergebenen FocusEvent kann man mit getSource() nach der auslösenden
Komponente fragen.
HRZ Einführungspraktikum Java
117
VI. Graphische Benutzeroberflächen mit dem AWT
118
4. Mehr über Container
4.1 Container-Events
 Wird eine Komponente einem Container hinzugefügt oder weggenommen, wird ein
ContainerEvent durch den Container erzeugt. Ein ContainerListener
implementiert entsprechende Methoden componentAdded() und
componentRemoved(), der ContainerEvent bietet die Methode
getContainer() und die Methode getChild(), die die Komponente zurückliefert.
4.2 Verschachtelte Layouts mit Panels
 Mit Hilfe der Klasse Panel, die einen leeren, unbeweglichen Container darstellt, kann
man besonders gut verschiedene Layouts miteinander kombinieren, indem man Panels
innerhalb von anderen Panels erzeugt.
Beispiel:
import java.applet.*;
import java.awt.*;
public class PanelTest extends Applet
{
public void init()
{
setLayout( new GridLayout( 1, 2 ) );
Panel p1 = new Panel();
p1.setLayout( new BorderLayout() );
p1.add( "North", new Button( "p1-North" ) );
p1.add( "South", new Button( "p1-South" ) );
Panel p2 = new Panel();
p2.setLayout( new FlowLayout() );
p2.add( new Button( "p2-1" ) );
p2.add( new Button( "p2-2" ) );
p2.add( new Button( "p2-3" ) );
p1.add( "Center", p2 );
add( p1 );
add( new Button( "Test" ) );
}
}
HRZ Einführungspraktikum Java
118
VI. Graphische Benutzeroberflächen mit dem AWT
119
4.3 Die Klasse ScrollPane
 Ein ScrollPane ist ein spezieller Container, der genau eine Komponente aufnimmt und
diese automatisch horizontal und vertikal scrollt. Die Komponente kann also größer sein
als das ScrollPane, das sie aufnimmt.
ScrollPane erzeugen
ScrollPane sp = new ScrollPane();
ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
// ALWAYS, NEVER oder AS_NEEDED angeben
Panel content = new Panel();
... // Panel content mit Komponenten füllen
sp.add( content );
sp.setSize( 200, 100 ); // Breite und Höhe festlegen
add( sp );
Programmgesteuert scrollen
Dimension d = sp.getViewportSize(); // Dimensionen Ausschnitt
sp.setScrollPosition( 50, 200 );
// Scrolle nach x, y
Point p = sp.getScrollPosition();
// Aktuelle Position
Schieberegler beeinflussen
sp.getVAdjustable().setUnitIncrement( 1 ); // vertikal
sp.getHAdjustable().setUnitIncrement( 2 ); // horizontal
... vergleiche Möglichkeiten im Interface Adjustable
HRZ Einführungspraktikum Java
119
VI. Graphische Benutzeroberflächen mit dem AWT
120
5. Weitere einfache Komponenten
5.1 CheckboxGroup
 Checkbox-Objekte können zu einer CheckboxGroup zusammengefaßt werden. Im
Unterschied zu einzeln verwendeten Checkboxen kann in einer CheckboxGroup immer
nur eine der Checkboxen ausgewählt sein. Damit lassen sich also "RadioButtons"
realisieren.
CheckboxGroup anlegen
 Der CheckboxGroup-Instanz werden nacheinander die einzelnen Checkboxen
zugeordnet, indem man für diese Checkboxen einen anderen Konstruktor wie folgt
benutzt:
Checkbox cbJa, cbNein, cbVielleicht, cbKeineAhnung;
CheckboxGroup wahl = new CheckboxGroup();
...
cbJa
= new Checkbox( "Ja",
wahl,
cbNein
= new Checkbox( "Nein",
wahl,
cbVielleicht = new Checkbox( "Vielleicht",
wahl,
cbKeineAhnung = new Checkbox( "Keine Ahnung", wahl,
add(
add(
add(
add(
cbJa
cbNein
cbVielleicht
cbKeineAhnung
false
false
true
false
);
);
);
);
);
);
);
);
Beachte:
 Eine der Checkboxen muß als Vorgabe aktiviert sein (vgl. cbVielleicht).
 Die CheckboxGroup selbst muß nicht dem Container hinzugefügt werden, somit lassen
sich die Teile der Checkboxgroup frei und nicht zwingend beieinander positionieren.
 Die Klasse Checkbox besitzt Methoden getCheckboxGroup() und
setCheckboxGroup(), mit denen man zusätzlich die Zugehörigkeit beeinflussen kann.
 Wird eine Auswahl gemacht, erzeugt die betroffene Checkbox einen ItemEvent, auf
den man entsprechend reagieren kann (siehe vorne).
Bestimmen und Setzen der ausgewählten Checkbox
Checkbox gew = wahl.getSelectedCheckbox();
if ( gew == cbJa ) { ... }
wahl.setSelectedCheckbox( cbNein );
HRZ Einführungspraktikum Java
120
VI. Graphische Benutzeroberflächen mit dem AWT
121
5.2 Choice
 Instanzen der Klasse Choice repräsentieren Auswahlfelder und werden je nach System
als Popup- oder Dropdown-Liste dargestellt und dienen dazu, aus einer Liste einen Wert
auszuwählen
Choice anlegen
 Nach dem Erzeugen einer Choice-Instanz werden ihr mit addItem einzelne
Listenwerte hinzugefügt, dann wird das Auswahlfeld dem Darstellungsbereich
hinzugefügt:
Choice cPizza =
cPizza.addItem(
cPizza.addItem(
cPizza.addItem(
cPizza.addItem(
add( cPizza );
new Choice();
"Pizza Salami"
"Pizza Tonno"
"Pizza Hawaii"
"Pizza Calzone"
);
);
);
);
Werte hinzufügen und entfernen
cPizza.insert( "Pizza Mista", 2 );
cPizza.remove( 1 );
cPizza.remove( "Pizza Salami" );
cPizza.removeAll();
Anzahl und Inhalte abfragen
int
String
anzahl = cPizza.getItemCount();
p
= cPizza.getItem( 2 );
Auswahl abfragen
String pizzaName = cPizza.getSelectedItem();
int
pizzaNr
= cPizza.getSelectedIndex();
Auswahl setzen
cPizza.select( "Pizza Hawaii" );
cPizza.select( 3 );
Auf Ereignisse reagieren
 Ebenso wie eine Checkbox sendet auch eine Choice bei einer Auswahl einen
ItemEvent. Mit Hilfe der Methode getItemSelectable() des ItemEvents
kann man in der entsprechenden Methode itemStateChanged() des
ItemListeners die auslösende Choice ermitteln.
HRZ Einführungspraktikum Java
121
VI. Graphische Benutzeroberflächen mit dem AWT
122
5.3 List
 List-Instanzen sind rechteckige Bereiche, in denen eine Liste dargestellt wird. Aus dieser
können auch mehrere Werte ausgewählt werden.
 Ist die Liste länger als der Darstellungsbereich, werden automatisch Bildlaufleisten
hinzugefügt.
Liste anlegen
 Die Anzahl der am Bildschirm sichtbaren Zeilen kann im Konstruktor vorgegeben
werden. Außerdem muß angegeben werden, ob jeweils nur ein Element (false) oder
mehrere (true) ausgewählt werden dürfen:
List plan = new List();
// Keine Mehrfachauswahl
List plan = new List( 3, true ); // Mehrfachauswahl
plan.addItem(
plan.addItem(
plan.addItem(
plan.addItem(
plan.addItem(
add( plan );
"Merkur"
"Venus"
"Erde"
"Mars"
"Jupiter"
);
);
);
);
);
Mit der Liste arbeiten
 List bietet sehr viele Methoden, die z. B. wie folgt eingesetzt werden können:
plan.setMultipleMode( false );
if ( plan.isMultipleMode() ) ...
plan.addItem( "Saturn" );
plan.addItem( "Pluto", 0 ); // Vorne einfügen
plan.replaceItem( "Uranus", 2 ); // Nr. 2 ersetzen
plan.delItem( 3 );
String
s
String
sel
String[] sels
int
isel
int[]
isels
=
=
=
=
=
plan.getItem( 1 );
plan.getSelectedItem();
plan.getSelectedItems();
plan.getSelectedIndex();
plan.getSelectedIndexes();
int num = plan.getItemCount();
... und einige mehr, siehe API-Dokumentation!
Auf Ereignisse reagieren
 Wie die Choice erzeugt auch die List entsprechende ItemEvents, wenn Items
selektiert oder deselektiert werden. Ein Doppelklick auf einen Eintrag löst einen
ActionEvent aus...
HRZ Einführungspraktikum Java
122
VI. Graphische Benutzeroberflächen mit dem AWT
123
6. Frames und Dialoge
6.1 Die Klasse Frame
 Eigenständige Fenster sind im AWT Instanzen der Klasse Frame. Diese können dann aus
einem Applet oder einer Application heraus erzeugt und angezeigt werden.
Beispiel:
import java.awt.*;
public class FrameTester
{
public static void main( String[] args )
{
Frame f = new Frame( "Fenstertitel" ); // Erzeugen
// f.setTitle( String s );
// (Titel setzen)
// String t = f.getTitle();
// (Titel holen)
f.setSize( 300, 200 );
f.setLocation( 0, 0 );
//f.setIconImage( Image i );
f.setLayout( new FlowLayout() );
//
//
//
//
Fenstergröße
Fensterposition
(Icon des Fensters)
Layout-Manager
Button b = new Button( "Ok" );
//...
f.add( b );
// Button erzeugen
// Listener erzeugen...
// Komponenten hinzuf.
f.setVisible( true );
f.requestFocus();
// Fenster anzeigen
// Focus erbitten
try{ Thread.sleep( 10000 ); }
// 10 Sek. warten
catch( InterruptedException ex ){}
f.setVisible( false );
f.dispose();
System.exit( 0 );
// Fenster ausblenden
// Ressourcen freigeben
// Exit-Code aus Anwendung zurückgeben
}
}
Hinweis:
 Die Auflösung des Bildschirms läßt sich über die Klasse Toolkit ermitteln, so daß man
z. B. den Frame als Vollbild oder zentriert anzeigen kann:
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int w = d.width;
int h = d.height; // Breite und Höhe in Pixeln
HRZ Einführungspraktikum Java
123
VI. Graphische Benutzeroberflächen mit dem AWT
124
6.2 Auf Fensterereignisse reagieren
 Bei Auftreten entsprechender Ereignisse in Frame oder Dialog wird ein WindowEvent
ausgelöst, den beim Fenster registrierte WindowListener bearbeiten. Es existieren
folgende Methoden
public void windowActivated( WindowEvent e )
// Fenster gerade neu erzeugt oder wieder im Vordergrund
public void windowDeactivated( WindowEvent e )
// Fenster geht in den Hintergrund
public void windowIconified( WindowEvent e )
// Fenster auf Icongröße verkleinert
public void windowDeiconified( WindowEvent e )
// Fenster aus Icon wieder vergrößert
public void windowOpened( WindowEvent e )
// Fenster wurde geöffnet
public void windowClosing( WindowEvent e )
// Fenster soll geschlossen werden, z. B. mit ALT+F4
public void windowClosed( WindowEvent e )
// Fenster wurde geschlossen
 Java-Fenster lassen sich nicht automatisch schließen. Die Applikation muß das Ereignis
windowClosing abfangen und das Fenster dann kontrolliert schließen, z. B. wie folgt:
import java.awt.*;
public class FrameTester
{
protected static Frame f;
public static void main( String[] args )
{
f = new Frame( "Fenstertitel" );
f.addWindowListener( new WindowAdapter()
{
public void windowClosing( WindowEvent e )
{
f.setVisible( false );
f.dispose();
System.exit( 0 );
}
} );
f.setSize( 300, 200 );
f.setLocation( 0, 0 );
f.setVisible( true );
f.requestFocus();
}
}
 Die Vorgehensweise ist für die Klassen Frame und Dialog identisch.
HRZ Einführungspraktikum Java
124
VI. Graphische Benutzeroberflächen mit dem AWT
125
6.3 Die Klasse Dialog
 Neben Frames existiert noch eine weitere Fensterklasse, die Klasse Dialog. Sie realisiert
ein Dialogfenster, z. B. einen Suchen-Dialog. Dialogfenster sind an einen Frame
gebunden, der sie "besitzt", daher wird eine Referenz auf diesen Frame im Konstruktor
mit übergeben.
 Dialogfenster können modal sein, d. h. sie blockieren den Eingabefocus, so daß solange
der Dialog angezeigt wird, kein anderes Fenster aktiv sein kann.
Beispiel:
Dialog erzeugen
Frame frame; // ... frame erzeugen usw.
Dialog d1 = new Dialog( frame, false );
// nicht modal
Dialog d2 = new Dialog( frame, "Suchen", true );// modal
Modal-Modus setzen / ermitteln
boolean modal = d1.isModal();
d2.setModal( false );
//Ist der Dialog modal?
Größenänderung unterbinden / ermöglichen
boolean res = d1.isResizable(); //Ist das Fenster veränderbar?
d1.setResizable( false );
6.4 Die Klasse FileDialog
 Java bietet einen plattformunabhängigen Zugriff auf den (plattformabhängigen) DateiDialog über die Klasse FileDialog.
Beispiele:
FileDialog dLoad = new FileDialog( frame, "Datei öffnen" );
dLoad.show();
// blockiert bis Auswahl erfolgt ist
String datei = dLoad.getFile();
String verz = dLoad.getDirectory();
if( datei != null ) ...
FileDialog dSave = new FileDialog( frame,
"Datei speichern", FileDialog.SAVE );
// Man kann Vorgaben für Datei und Verzeichnis machen:
// dSave.setFile( "img0000.gif" );
// dSave.setDirectory( "c:\\windows\\temp" );
dSave.show();
String datei = dSave.getFile();
String verz = dSave.getDirectory();
if( datei != null ) ...
HRZ Einführungspraktikum Java
125
VI. Graphische Benutzeroberflächen mit dem AWT
126
7. Menüs und Menüleisten
 Die Klassen MenuBar, Menu, MenuItem und CheckboxMenuItem ermöglichen
den Aufbau von Menüs in graphischen Oberflächen.
 Nur ein Frame darf eine MenuBar besitzen, kein Dialog, kein Applet usw.!
7.1 Menüs definieren
MenuBar mb = new MenuBar();
Menu mDatei = new Menu( "Datei" );
mDatei.add( new MenuItem( "Neu" ) );
...
Menu mBearb = new Menu( "Bearbeiten" );
mBearb.add( new MenuItem( "Ausschneiden" ) );
mBearb.add( new MenuItem( "Kopieren" ) );
mBearb.add( new MenuItem( "Einfügen" ) );
mBearb.addSeparator();
mBearb.add( new CheckboxMenuItem( "AutoDelete an" ) );
mBearb.disable();
Menu mHilfe = new Menu( "?" );
mHilfe.add( new MenuItem( "Info" ) );
mb.add( mDatei );
mb.add( mBearb );
mb.setHelpMenu( mHilfe );
Frame f; ...
// ... von irgedwo her
f.setMenuBar( mb ); // Das geht nur in einem Frame...
Hinweis:
 Da Menu eine Subklasse von MenuItem ist, ist jedes Menu also auch ein MenuItem,
d. h. man kann also Untermenüs erzeugen...
7.2 Auf Menüereignisse reagieren
 Wenn der Benutzer einen Menüpunkt anklickt, wird ein ActionEvent durch das
entsprechende MenuItem erzeugt und an die beim MenuItem registrierten
ActionListener weitergeleitet. Für jedes relevante MenuItem muß man bei diesem
einen Listener registrieren, d. h. innerhalb des gleichen Menüs können auch verschiedene
Listener auf verschiedene MenuItems reagieren.
 In der Methode actionPerformed des Listeners kann der ActionEvent e
untersucht werden:
String
menuItemLabel = e.getActionCommand();
MenuItem menuItem
= (MenuItem)( e.getSource() );
HRZ Einführungspraktikum Java
126
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
127
VII.
Ein- und Ausgabe,
Netze,
Dateien und
Fortgeschrittenes
HRZ Einführungspraktikum Java
127
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
128
1. Ein- und Ausgabeströme in Java
 Klassen für Ein-/Ausgabeoperationen sind im Paket java.io untergebracht. Ein- und
Ausgabe in Java ist stromorientiert: Man liest aus einem Strom von Eingabedaten, der
z. B. aus dem Netz oder aus einer Datei kommt und schreibt Daten in einen Ausgabestrom, der als Senke z. B. ebenfalls eine Netzverbindung, eine Datei o. ä. haben kann.
 Als Basis aller Ein- und Ausgabeströme existieren die Klassen InputStream und
OutputStream für elementare, Byte-orientierte Ein- und Ausgabe. Der StandardEingabestrom System.in ist z. B. eine Instanz von InputStream. Auf diesen
Basisströmen bauen spezialisiertere Stream-Klassen auf, z. B. PrintStream zur
Ausgabe (System.out und System.err sind PrintStreams).
Byteorientierte Ein- und Ausgabe mit InputStream und OutputStream
 Alle Basis-Ein- und Ausgabeströme besitzen Methoden read() und write() zum Lesen
und Schreiben von Bytes. Mit den Unterklassen FileInputStream und
FileOutputStream kann man z. B. Dateien byteweise lesen und schreiben:
Beispiel: Kopieren einer Datei
import java.io.*;
public class CopyFile
{
public static void main( String[] args )
throws Exception
{
InputStream is = new FileInputStream ( args[ 0 ] );
OutputStream os = new FileOutputStream( args[ 1 ] );
byte[] buffer = new byte[4096]; // Puffer für 4 KByte
int n;
// Anzahl Bytes die gelesen wurden
while( ( n = is.read( buffer, 0, buffer.length ) ) != -1 )
// Gelesene Bytes werden in das Array buffer geschrieben
// Das Array wird ab Index 0 gefüllt
// Es werden maximal buffer.length Bytes gelesen
// Wenn der Eingabestrom beendet ist, gibt read –1 zurück
os.write( buffer, 0, n );
// Schreibe n Bytes beginnend ab Index 0 aus dem Array
// in den Ausgabestrom
is.close();
os.close();
}
}
Aufruf:
java CopyFile c:\x\y\quelle.dat d:\a\b\ziel.dat
HRZ Einführungspraktikum Java
128
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
129
Weitere interessante Klassen zur Ein- und Ausgabe auf Byte-Ebene
 Im Paket java.util.zip existieren Ein- und Ausgabeströme zum Lesen und
Schreiben von ZIP- und GZIP-Strömen und -Dateien.
 Die Klassen DataInputStream und DataOutputStream ermöglichen es, einfache
Java-Datentypen in einen Ausgabestrom zu schreiben bzw. wieder daraus zu lesen.
 Die Klasse RandomAccessFile ermöglicht statt einer sequentiellen Verarbeitung den
wahlfreien Zugriff auf bestimmte Positionen einer Datei.
Reader- und Writer-Klassen
 Da die Stream-Klassen auf der Basis von einzelnen Bytes arbeiten, sind sie nicht überall
direkt dazu verwendbar, Zeichen und Strings zu lesen bzw. zu schreiben, da Zeichen ja
Java-intern als UniCode-Zeichen in 16 Bit abgelegt sind, in einer Datei in der Regel aber
als 8-Bit-Zeichen stehen.
 Daher hat man ab JDK 1.1 die Klassen für Byteströme um sogenannte Reader- und
Writer-Klassen ergänzt, die aus einem Bytestrom einen Strom von UniCode-Zeichen
machen und umgekehrt. Beim Lesen einer Datei wandelt ein Reader z. B. die 8-BitDarstellung der jeweiligen Codepage in die entsprechende 16-Bit-Darstellung des
UniCode um. Dabei kann optional auch angegeben werden, in welcher Codepage die
Daten codiert sind.
 OuputStreamWriter:
Wandelt Character-Streams in Byte-Streams um
 FileWriter:
Schreibt zeichenweise in eine Datei, Codepage kann z. B. auch angegeben werden.
 PrintWriter:
Gibt alle Basis-Datentypen als Zeichenkette aus, z. B. System.out
 BufferedWriter:
Puffert Ausgabeströme
 StringWriter:
Schreibt Daten in einen StringBuffer
 InputStreamReader:
Wandelt einen Byte-Stream in einen Character-Stream um
 FileReader:
Liest aus einer Datei
 PushbackReader:
Erlaubt es, gelesene Zeichen wieder in den Strom zurückzuschieben
 BufferedReader:
Puffert Leseoperationen und liest komplette Zeilen
 LineNumberReader:
BufferedReader, der zusätzlich Zeilen mitzählt
 StringReader:
liest aus einem String
 Datenströme und Reader / Writer werden bei der Erzeugung mit new() oft ineinander
verschachtelt (siehe unten) so daß der eine Strom jeweils auf den Funktionen eines
darunterliegenden Stromes aufbaut.
HRZ Einführungspraktikum Java
129
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
130
Beispiel 1:
 Zeilenweises Ausgeben einer reinen Textdatei:
import java.io.*;
public class ReaderTest
{
public static void main( String[] args )
{
try
{
BufferedReader br = new BufferedReader(
new FileReader( "c:\\autoexec.bat" ) );
String line;
while( ( line = br.readLine() ) != null )
System.out.println( line );
}
catch( Exception ex ){ System.out.println( "Fehler!" ); }
}
}
Beispiel 2:
 Ein paar Textzeilen in eine Datei schreiben:
PrintWriter datei =
new PrintWriter( new FileWriter( "index.html" ) );
datei.println( "<HTML><HEAD><TITLE>Ein Test</TITLE></HEAD>" );
datei.println( "<BODY> Hallo Welt! </BODY></HTML>"
);
datei.close();
Beispiel 3:
 Lesen von der Standard-Eingabe:
BufferedReader konsole =
new BufferedReader( new InputStreamReader( System.in ) );
System.out.print( "Wie viele Waschmaschinen wollen Sie?" );
int anzahl = Integer.parseInt( konsole.readLine() );
System.out.println( "Menge: " + anzahl + " Stück" );
System.out.print( "Und wohin soll ich liefern?" );
String anschrift = konsole.readLine();
...
HRZ Einführungspraktikum Java
130
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
131
2. Datei- und Verzeichnisinformationen
 Die Klasse File repräsentiert Informationen über eine Datei (nicht die Datei selbst).
Klassenvariablen
String vTrenner = File.separator;
// Verzeichnistrenner ( Unix: "/", Windows: "\" ) hier
String pTrenner = File.pathSeparator;
// Pfadtrenner für Pfadlisten ( ":" bzw. ";" ) hier
File-Instanz erzeugen
File f = new File( dir, dateiname );
File f = new File( pfadname
);
// "c:\temp\test.java"
Informationen abfragen
boolean b;
b = f.canRead();
b = f.canWrite();
b = f.exists();
b = f.isAbsolute();
b = f.isDirectory();
b = f.isFile();
//
//
//
//
//
//
Lesender Zugriff möglich?
Schreibender Zugriff möglich?
Gibt es diese Datei / Verzeichnis?
Ist die Pfadangabe absolut?
Handelt es sich um ein Verzeichnis?
oder um eine Datei?
String s;
s = f.getAbsolutePath();
s = f.getName();
s = f.getParent();
s = f.getPath();
//
//
//
//
long l;
l = f.lastModified();
l = f.length();
// Letzte Änderung in ms seit 1.1.70
// Länge in Bytes
Absoluter Pfad der Datei
Datei- bzw. Verzeichnisname
Pfad des Elternverzeichnisses
Pfad der Datei
Löschen und umbenennen
boolean ok = f.delete();
boolean ok = f.renameTo( new File( "Neu.txt" ) );
Arbeiten mit Verzeichnissen
String aktuelles = System.getProperty( "user.dir" );
// Aktuelles Arbeitsverzeichnis dieser Java Application
String[] list = f.list(); // Verzeichnisinhalt
String[] list = f.list( FilenameFilter );
// siehe Schnittstelle FilenameFilter in API-Docs!!
boolean ok = f.mkdir();
// Erzeugt dieses Verzeichnis
boolean ok = f.mkdirs(); // Erzeugt rekursiv Verzeichnis(se)
HRZ Einführungspraktikum Java
131
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
132
3. Netzwerkkommunikation mit Java
 Java bietet grundlegende Funktionen zur Arbeit in Netzen auf TCP/IP- und UDP-Basis,
mit denen jedes darauf basierende höhere Protokoll implementiert werden kann
(FTP, TELNET, HTTP, POP3, SMTP, NNTP, SNMP, ...).
 Es lassen sich Client- und Serversockets für TCP,
Client- und Server-Datagramm-Sockets für UDP einrichten.
 Eine Klasse URL nimmt in ihren Instanzen URLs auf, die Klasse InetAddress nimmt
in ihren Instanzen eine Hostadresse auf.
 Näheres in spezieller Literatur und in der API-Dokumentation!
3.1 Einfache Netzoperationen aus Applets heraus:
 this.getAppletContext().showDocument( eineURLInstanz );
// weist den Browser an, diese URL anzufordern.
// Es gibt auch die Möglichkeit, ein target anzugeben...
 Instanzen vom Typ URL besitzen eine Methode openStream(). Diese liefert einen
InputStream zurück, der dann wie jeder andere weiterverarbeitet werden kann:
try
{
URL url = new URL("http://www.xy.com/irgendwas.txt" ) ;
BufferedReader data = new BufferedReader(
new InputStreamReader( url.openStream() ) );
String line;
while ( ( line = data.readLine() ) != null )
System.out.println( line );
data.close();
}
catch( Exception ex )
{ System.out.println( "Ein Fehler ist aufgetreten." ); }
3.2 Kommunikation zwischen Applets:
 Applets der gleichen Seite können ihre public-Methoden untereinander aufrufen:
Applet uhr = this.getAppletContext().getApplet( "Uhr" );
uhr.stop();
 Der Name eines Applets kann im <APPLET>-Tag z. B. mit NAME="Uhr" definiert
werden. Die Methode getApplets() liefert alternativ eine komplette Enumeration
der Applets der Seite:
Enumeration e = this.getAppletContext().getApplets();
while ( e.hasMoreElements() )
{
Applet applet = (Applet)e.nextElement();
applet.doSomething();
}
HRZ Einführungspraktikum Java
132
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
133
4. Java Database Connectivity (JDBC)
 Verfügbar als Zusatzpaket für JDK 1.0, im Sprachumfang enthalten ab JDK 1.1
 Java-API, um auf SQL-Ebene von Java aus auf beliebige relationale Datenbanken
zuzugreifen. Die Schnittstelle ist dabei unabhängig von der Plattform und der Datenbank,
der Java-Code muß bei einem Wechsel also nicht geändert werden.
 JDBC ist in Anlehnung an die Datenbank-Schnittstelle ODBC entwickelt worden.
Eine JDBC-to-ODBC-Bridge-Treiber wird mit den JDBC-Klassen von Sun mitgeliefert.
 Klassen für Select-Abfragen, Cursors, Connections etc. sind verfügbar,
die SQL-Datentypen werden einheitlich auf Java-Datentypen abgebildet.
 Nahezu alle Datenbanksysteme (Oracle, DB2, Access, ...) bieten inzwischen mächtige
JDBC-Treiber. Es existieren verschiedene Treiber-Architekturen, im Idealfall ist der
JDBC-Treiber selbst in Java geschrieben, so daß auf dem Client keine Installation von
Treibern nötig ist, sondern der Download der Java-Klassen z. B. durch ein Applet
ausreicht.
Beispiel:
import java.sql.*;
public class Test
{
public static void main( String[] args )
throws Exception
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// JDBC-Treiber für ODBC-Verbindungen registrieren
Connection c = DriverManager.getConnection(
"jdbc:odbc:Bank;UID=Meier;PWD=MySecret" );
// Verbindungsaufbau zur ODBC-zugänglichen Datenbank
// "Bank", User "Meier" mit Passwort "MySecret"
Statement s = c.createStatement();
ResultSet r = s.executeQuery(
"SELECT kontoNr, betrag FROM konten" );
// SQL-Select-Abfrage ausführen
while ( r.next() )
// Für jeden Datensatz...
{
int betrag = r.getInt( "betrag" );
// Hole int-Wert über Namen der Spalte
int nr = r.getInt( 0 );
// Hole int aus Spalte mit Index 0 (KontoNr)
System.out.println( kontoNr + " / " + betrag );
}
r.close();
c.close();
}
}
HRZ Einführungspraktikum Java
133
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
134
5. Swing




Verfügbar als Zusatzpaket für JDK 1.1, im Sprachumfang enthalten ab JDK 1.2
Mächtige Klassenbibliothek zur Erstellung graphischer Oberflächen mit Java
Realisiert als Aufsatz auf das AWT, Alternative zu den AWT-Komponenten
Verwendet keine native peers zur Darstellung, daher ist es einfacher, Oberflächen zu
erzeugen, die auf jedem System gleich aussehen.
 Einige Stichwörter aus dem Leistungsumfang:
 Pluggable Look and Feel: Unix, Windows, Java, Mac, zur Laufzeit änderbar
 Drag and Drop zwischen Java-Elementen
 Unterstützung der Zwischenablage
 Grafische, animierte und roll-over-Buttons
 Tool Tips ('gelbe Kästchen')
 Fortschrittsbalken
 Tree Controls, auch mit selbstdefinierten Icons
 HTML Viewer –Komponente
 Komponenten für Tabellendarstellungen
 Toolbars
Beispiele:
Table
Listbox
Toolbar
Tree Control
HRZ Einführungspraktikum Java
134
VII. Ein- und Ausgabe, Netze, Dateien und Fortgeschrittenes
135
6. Java Servlets
 Java Servlets sind Java-Anwendungen, die im Prozess eines Web-Servers laufen, ähnlich
wie Applets in einem Browser laufen. Ein Servlet-fähiger Web-Server besitzt dazu eine
Java Virtual Machine, um Java Bytecode auszuführen und bietet eine standardisierte
Servlet API, gegen die man Servlets programmieren kann.
 Nahezu alle gängigen Web-Server (Apache, Netscape, Domino, Microsoft) unterstützen
inzwischen Servlets, oft sind zusätzlich Servlet Plug-Ins von Drittanbietern verfügbar.
 Vergleichbar mit CGI kann man einen HTTP Request an ein Servlet weiterleiten, das
dann z. B. Daten aus einem HTML-Formular entgegennimmt und verarbeitet und dann als
Antwort eine HTML-Seite erzeugt.
 Servlets können, abgesehen davon, daß sie keine graphische Oberfläche besitzen, den
vollen Sprachumfang von Java nutzen, z. B. via JDBC eine Datenbank ansprechen.
 Servlets sind plattformunabhängig, man kann also das Servlet, einmal geschrieben,
unverändert in einem anderen Web-Server auf einer anderen Plattform laufen lassen.
 Servlets sind schneller als CGI. Wenn ein Request bearbeitet werden soll, wird bei CGI
ein neuer Prozess gestartet. Dieser Kontextwechsel zwischen den Prozessen kostet Zeit.
Servlets laufen und bleiben nach dem Start im Web-Server-Prozess, der Wechsel ist nicht
nötig, stattdessen wird für jeden Request einfach ein neuer Thread gestartet, der ihn
bearbeitet. Dies geschieht automatisch und muß nicht programmiert werden.
 Die Java Servlet API bietet volle Unterstützung für das Bearbeiten von Cookies.
 Servlets besitzen ein integriertes Session Management, um Objekte in einer Session zu
speichern. Wenn mehrere Requests vom gleichen Client bearbeitet werden, lassen sich so
zwischen den einzelnen Requests Zustände erhalten, z. B. Login-Informationen. Dies wird
dynamisch und automatisch entweder über Cookies oder URL Rewriting realisiert.
 Servlets können über eine URL von Browsern aufgerufen werden, in HTML-Seiten vergleichbar mit Server Side Includes eingebunden werden, oder sich gegenseitig aufrufen.
Beispiel: Aufruf über http://www.bank.de/servlet/KontoServlet?kontoNr=12345
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class KontoServlet extends HttpServlet
{
public void doGet( HttpServletRequest req,
HttpServletResponse res )
throws ServletException, IOException
{
ServletOutputStream out = res.getOutputStream();
res.setContentType("text/html");
int nr = Integer.parseInt(req.getParameter( "kontoNr" ));
out.println( "<HEAD><TITLE>Ihr Konto:</TITLE></HEAD>" );
out.println( "<BODY>" );
out.println( "Ihr Kontostand:" );
out.println( Konto.gibKonto( nr ).gibKontoStand() );
out.println("</BODY>");
out.close();
}
}
HRZ Einführungspraktikum Java
135
Herunterladen