21.07.2014 Aufrufe

Java-Einführung

Java-Einführung

Java-Einführung

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Kursunterlage<br />

Hubert Partl<br />

partl@mail.boku.ac.at<br />

Zentraler Informatikdienst<br />

Universitat fur Bodenkultur Wien<br />

Version Februar 2001


Vorwort<br />

Die vorliegende <strong>Java</strong>-Einfuhrung beschreibt nur kurz die wichtigsten Eigenschaften<br />

von <strong>Java</strong>, die fur die meisten Anwendungen benotigt werden. Fur daruber hinaus<br />

gehende spezielle Features und Anwendungen sowie fur ausfuhrlichere Informationen<br />

wird auf die Referenzen und auf die Online-Dokumentation verwiesen.<br />

Die vorliegende Fassung beschreibt <strong>Java</strong> ab der Version JDK 1.1.<br />

Die <strong>Java</strong>-Einfuhrung besteht aus zwei Teilen:<br />

der eigentlichen Kursunterlage mit Beispielen und Ubungsaufgaben, und<br />

Musterlosungen zu den Ubungsaufgaben.<br />

Wenn Sie <strong>Java</strong> erfolgreich lernen wollen, empfehle ich Ihnen dringend, die Musterlosungen<br />

erst dann auszudrucken und anzusehen, wenn Sie bereits alle Ubungsbeispiele<br />

selbstandig fertig programmiert haben, also erst am Ende des Kurses.<br />

Diese Kursunterlage enthalt mehr Informationen und mehr Ubungsbeispiele, als innerhalb<br />

eines 5-tagigen Kurses durchgearbeitet werden konnen. Der Kursleiter mu<br />

auswahlen, welche Teile und Kapitel er besprechen will und welche Ubungsaufgaben<br />

er den Teilnehmern stellen will. Die ubrigen Kapitel und Beispiele dienen dann zum<br />

Nachschlagen fur spater, wenn die Teilnehmer das Gelernte praktisch anwenden<br />

wollen.<br />

Wenn Ihnen meine <strong>Java</strong>-Einfuhrung gefallt, sagen Sie es weiter. Wenn Sie darin<br />

Fehler entdecken oder Verbesserungsvorschlage haben, sagen Sie es bitte mir per<br />

E-Mail an partl@mail.boku.ac.at - ich freue mich immer uber solche Hilfe.<br />

Ich danke Gudio Kruger, Stefan Zeiger, Peter van der Linden, Roedy Green und allen<br />

anderen Internet-Surfern, die mir gute Tips gegeben und Tippfehler korrigiert haben,<br />

sowie den Teilnehmern an meinen <strong>Java</strong>-Schulungen, die mir interessante Fragen<br />

gestellt haben.<br />

Hubert Partl<br />

Wien, im Janner 1998<br />

P.S.: Diese "<strong>Java</strong>-Einfuhrung" ist auch uber das Internet verfugbar, unter dem URL<br />

http://www.boku.ac.at/javaeinf/<br />

Copyright Hubert Partl partl@mail.boku.ac.at<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 1


Inhaltsverzeichnis<br />

1 Was ist <strong>Java</strong>? 8<br />

1.1 Insel, Kaee oder Programmiersprache : : : : : : : : : : : : : : : : : 8<br />

1.2 Applikationen (application) : : : : : : : : : : : : : : : : : : : : : : : 9<br />

1.3 Applets : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 9<br />

1.4 <strong>Java</strong>Script ist nicht <strong>Java</strong> : : : : : : : : : : : : : : : : : : : : : : : : : 9<br />

2 Software und Online-Dokumentation 10<br />

2.1 <strong>Java</strong> Development Kit (JDK) : : : : : : : : : : : : : : : : : : : : : : 10<br />

2.2 Environment-Variable : : : : : : : : : : : : : : : : : : : : : : : : : : 11<br />

2.3 Filenamen : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 12<br />

2.4 <strong>Java</strong> Compiler (javac) : : : : : : : : : : : : : : : : : : : : : : : : : : 12<br />

2.5 <strong>Java</strong> Runtime System (java) : : : : : : : : : : : : : : : : : : : : : : : 13<br />

2.6 Web-Browser und Appletviewer : : : : : : : : : : : : : : : : : : : : : 13<br />

2.7 Online-Dokumentation (API) : : : : : : : : : : : : : : : : : : : : : : 14<br />

2.8 <strong>Java</strong>-Archive (jar) : : : : : : : : : : : : : : : : : : : : : : : : : : : : 15<br />

2.9 Software-Tools : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 15<br />

2.10 <strong>Java</strong> Beans : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 16<br />

2.11 Vorgangsweise : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 16<br />

2.12 Beispiel: Einfache HelloWorld-Applikation : : : : : : : : : : : : : : : 17<br />

2.13 Ubung: HelloWorld-Applikation : : : : : : : : : : : : : : : : : : : : : 17<br />

2.14 Ubung: Online-Dokumentation : : : : : : : : : : : : : : : : : : : : : 17<br />

2.15 Typische Anfanger-Fehler : : : : : : : : : : : : : : : : : : : : : : : : 18<br />

3 Syntax und Statements 19<br />

3.1 Grundbegrie der Programmierung : : : : : : : : : : : : : : : : : : : 19<br />

3.2 Namenskonventionen : : : : : : : : : : : : : : : : : : : : : : : : : : : 20<br />

3.3 Reservierte Worter : : : : : : : : : : : : : : : : : : : : : : : : : : : : 20<br />

3.4 Datentypen : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 20<br />

3.5 Konstante (Literals) : : : : : : : : : : : : : : : : : : : : : : : : : : : 21<br />

3.6 Deklarationen und Anfangswerte : : : : : : : : : : : : : : : : : : : : 21<br />

3.7 Referenzen (reference) auf Objekte oder Strings : : : : : : : : : : : : 22<br />

3.8 Garbage Collector : : : : : : : : : : : : : : : : : : : : : : : : : : : : 22<br />

3.9 Felder (array) : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 23<br />

3.10 Ausdrucke (expression) und Operatoren : : : : : : : : : : : : : : : : 25<br />

3.11 Text-Operationen (String) : : : : : : : : : : : : : : : : : : : : : : : : 26<br />

3.12 Funktionen (Math) : : : : : : : : : : : : : : : : : : : : : : : : : : : : 27<br />

3.13 Statements und Blocke : : : : : : : : : : : : : : : : : : : : : : : : : : 27<br />

3.14 Kommentare : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 27<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 2


3.15 if und else : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 27<br />

3.16 for : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 27<br />

3.17 while und do : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 28<br />

3.18 switch und case : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 28<br />

3.19 break und continue : : : : : : : : : : : : : : : : : : : : : : : : : : : : 28<br />

3.20 System.exit : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 28<br />

3.21 Beispiele fur einfache Programme : : : : : : : : : : : : : : : : : : : : 29<br />

3.22 Fehlersuche und Fehlerbehebung (Debugging) : : : : : : : : : : : : : 32<br />

3.23 Dokumentation von Programmen (javadoc) : : : : : : : : : : : : : : 34<br />

3.24 Ubung: einfaches Rechenbeispiel Quadratzahlen : : : : : : : : : : : : 35<br />

3.25 Ubung: einfaches Rechenbeispiel Sparbuch : : : : : : : : : : : : : : : 35<br />

4 Objekte und Klassen 36<br />

4.1 Objekt-Orientierung : : : : : : : : : : : : : : : : : : : : : : : : : : : 36<br />

4.2 Klassen (class) : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 37<br />

4.3 Beispiel: objekt-orientierte HelloWorld-Applikation : : : : : : : : : : 38<br />

4.4 Datenfelder (member eld) : : : : : : : : : : : : : : : : : : : : : : : 39<br />

4.5 Methoden (method) : : : : : : : : : : : : : : : : : : : : : : : : : : : 40<br />

4.6 Uberladen (overload) : : : : : : : : : : : : : : : : : : : : : : : : : : : 41<br />

4.7 statische Methoden (static) : : : : : : : : : : : : : : : : : : : : : : : 41<br />

4.8 main-Methode : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 42<br />

4.9 Konstruktoren (constructor) : : : : : : : : : : : : : : : : : : : : : : : 42<br />

4.10 Kapselung (Encapsulation, Data Hiding, <strong>Java</strong> Beans) : : : : : : : : : 44<br />

4.11 Beispiel: schlechte Datums-Klasse : : : : : : : : : : : : : : : : : : : : 45<br />

4.12 Beispiel: bessere Datums-Klasse : : : : : : : : : : : : : : : : : : : : : 46<br />

4.13 Ubung: einfache Kurs-Klasse : : : : : : : : : : : : : : : : : : : : : : 50<br />

4.14 Objekt-orientierte Analyse und Design : : : : : : : : : : : : : : : : : 50<br />

4.15 Beispiel: Analyse Schulungen : : : : : : : : : : : : : : : : : : : : : : 51<br />

4.16 Ubung: Analyse Bucherregal : : : : : : : : : : : : : : : : : : : : : : : 51<br />

4.17 Vererbung (Inheritance, Polymorphismus, override) : : : : : : : : : : 52<br />

4.18 Ubung: Person und Student : : : : : : : : : : : : : : : : : : : : : : : 53<br />

4.19 Mehrfache Vererbung, Interfaces, abstrakte Klassen : : : : : : : : : : 54<br />

4.20 Beispiel: Katzenmusik : : : : : : : : : : : : : : : : : : : : : : : : : : 55<br />

4.21 Innere Klassen (inner class) : : : : : : : : : : : : : : : : : : : : : : : 56<br />

4.22 Zugri auf Objekte von anderen Klassen : : : : : : : : : : : : : : : : 56<br />

4.23 Packages und import : : : : : : : : : : : : : : : : : : : : : : : : : : : 57<br />

5 Fehlerbehandlung (Exceptions) 58<br />

5.1 Fehler erkennen (throw, throws) : : : : : : : : : : : : : : : : : : : : : 58<br />

5.2 Fehler abfangen (try, catch) : : : : : : : : : : : : : : : : : : : : : : : 59<br />

5.3 Mathematische Fehler : : : : : : : : : : : : : : : : : : : : : : : : : : 60<br />

5.4 Ubung: erweitertes Rechenbeispiel Sparbuch : : : : : : : : : : : : : : 61<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 3


6 Graphical User Interfaces (GUI) 63<br />

6.1 Abstract Windowing Toolkit (AWT) : : : : : : : : : : : : : : : : : : 63<br />

6.2 AWT-Komponenten (Component) : : : : : : : : : : : : : : : : : : : 64<br />

6.3 Container : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 67<br />

6.4 Layout-Manager : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 68<br />

6.5 Ubung: Layout-Manager : : : : : : : : : : : : : : : : : : : : : : : : : 70<br />

6.6 Farben (Color) : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 70<br />

6.7 Schriften (Font) : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 71<br />

6.8 Groenangaben : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 72<br />

6.9 Zeichenobjekte (Canvas) : : : : : : : : : : : : : : : : : : : : : : : : : 73<br />

6.10 Graphiken (Graphics, paint) : : : : : : : : : : : : : : : : : : : : : : : 73<br />

6.11 mehrzeilige Texte : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 76<br />

6.12 Event-Handling : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 77<br />

6.13 Beispiel: typischer Aufbau einer einfachen GUI-Applikation : : : : : 79<br />

6.14 Beispiel: typischer Aufbau einer komplexen GUI-Applikation : : : : 81<br />

6.15 Ubung: einfache GUI-Applikation : : : : : : : : : : : : : : : : : : : : 84<br />

6.16 Swing-Komponenten (JComponent) : : : : : : : : : : : : : : : : : : 85<br />

7 Applets 89<br />

7.1 Sicherheit (security, sandbox, signed applets) : : : : : : : : : : : : : 89<br />

7.2 HTML-Tags : : : : : : : : : : 90<br />

7.3 Beispiel: einfaches HelloWorld Applet : : : : : : : : : : : : : : : : : 91<br />

7.4 Ubung: einfaches HelloWorld Applet : : : : : : : : : : : : : : : : : : 92<br />

7.5 Methoden init, start, stop : : : : : : : : : : : : : : : : : : : : : : : : 93<br />

7.6 Groenangabe : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 93<br />

7.7 Beenden des Applet : : : : : : : : : : : : : : : : : : : : : : : : : : : 94<br />

7.8 Beispiel: typischer Aufbau eines Applet mit Button-Aktionen : : : : 94<br />

7.9 Beispiel: typischer Aufbau eines Applet mit Maus-Aktionen : : : : : 95<br />

7.10 Beispiel: typischer Aufbau eines Applet mit Text-Eingaben : : : : : 96<br />

7.11 Ubung: einfaches Applet Thermostat : : : : : : : : : : : : : : : : : : 97<br />

7.12 Ubung: Applet einfache Verkehrsampel : : : : : : : : : : : : : : : : : 98<br />

7.13 Ubung: komplexes Applet Sparbuch : : : : : : : : : : : : : : : : : : 99<br />

7.14 Ubung: komplexes Applet: Baume im Garten : : : : : : : : : : : : : 99<br />

7.15 Vermeidung von Flimmern oder Flackern (buered image) : : : : : : 100<br />

7.16 Uniform Resource Locators (URL) : : : : : : : : : : : : : : : : : : : 101<br />

7.17 Bilder (Image, MediaTracker) : : : : : : : : : : : : : : : : : : : : : : 102<br />

7.18 Tone (sound, AudioClip) : : : : : : : : : : : : : : : : : : : : : : : : 103<br />

7.19 Parameter : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 104<br />

7.20 Web-Browser : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 105<br />

7.21 Ubung: Zwei Applets : : : : : : : : : : : : : : : : : : : : : : : : : : : 107<br />

7.22 Applet-Dokumentation : : : : : : : : : : : : : : : : : : : : : : : : : : 107<br />

7.23 Doppelnutzung als Applet und Applikation : : : : : : : : : : : : : : 108<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 4


8 Threads 110<br />

8.1 Multithreading, Thread, Runnable : : : : : : : : : : : : : : : : : : : 110<br />

8.2 Starten eines Thread (start) : : : : : : : : : : : : : : : : : : : : : : : 111<br />

8.3 Beenden oder Abbrechen eines Thread : : : : : : : : : : : : : : : : : 112<br />

8.4 Unterbrechungen (sleep) : : : : : : : : : : : : : : : : : : : : : : : : : 113<br />

8.5 Synchronisierung (join, wait, notify, synchronized) : : : : : : : : : : 114<br />

8.6 Beispiel: eine einfache Animation : : : : : : : : : : : : : : : : : : : : 115<br />

8.7 Ubung: einfaches Applet Blinklicht : : : : : : : : : : : : : : : : : : : 116<br />

8.8 Ubung: erweitertes Applet Verkehrsampel mit Blinklicht : : : : : : : 117<br />

9 Ein-Ausgabe (IO) 119<br />

9.1 Dateien (Files) und Directories : : : : : : : : : : : : : : : : : : : : : 119<br />

9.2 Datenstrome (stream) : : : : : : : : : : : : : : : : : : : : : : : : : : 121<br />

9.3 InputStream (Eingabe) : : : : : : : : : : : : : : : : : : : : : : : : : : 122<br />

9.4 Spezielle Input-Streams : : : : : : : : : : : : : : : : : : : : : : : : : 123<br />

9.5 Lesen einer Datei von einem Web-Server (URL) : : : : : : : : : : : : 124<br />

9.6 OutputStream (Ausgabe) : : : : : : : : : : : : : : : : : : : : : : : : 125<br />

9.7 Spezielle Output-Streams : : : : : : : : : : : : : : : : : : : : : : : : 126<br />

9.8 RandomAccessFile (Ein- und Ausgabe) : : : : : : : : : : : : : : : : 128<br />

9.9 Reader und Writer (Text-Files) : : : : : : : : : : : : : : : : : : : : : 129<br />

9.10 Reader : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 132<br />

9.11 Writer : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 133<br />

9.12 Ubung: zeilenweises Ausdrucken eines Files : : : : : : : : : : : : : : 135<br />

9.13 Ubung: zeichenweises Kopieren eines Files : : : : : : : : : : : : : : : 135<br />

9.14 Ubung: Lesen eines Files uber das Internet : : : : : : : : : : : : : : : 135<br />

10 Networking 136<br />

10.1 <strong>Java</strong> im Web-Server (CGI, Servlets) : : : : : : : : : : : : : : : : : : 136<br />

10.2 Internet-Protokoll, Server und Clients : : : : : : : : : : : : : : : : : 138<br />

10.3 Sockets : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 139<br />

10.4 Beispiel: typischer Aufbau eines Servers : : : : : : : : : : : : : : : : 141<br />

10.5 Beispiel: typischer Aufbau eines Client : : : : : : : : : : : : : : : : : 142<br />

10.6 Ubung: einfache Client-Server-Applikation : : : : : : : : : : : : : : : 143<br />

11 System-Funktionen und Utilities 144<br />

11.1 Datum und Uhrzeit (Date) : : : : : : : : : : : : : : : : : : : : : : : 144<br />

11.2 Date Version 1.0 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 145<br />

11.3 Date und Calendar Version 1.1 : : : : : : : : : : : : : : : : : : : : : 149<br />

11.4 Zeitmessung : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 151<br />

11.5 Ausdrucken (PrintJob, PrinterJob) : : : : : : : : : : : : : : : : : : : 152<br />

11.6 Ausfuhrung von Programmen (Runtime, exec) : : : : : : : : : : : : 154<br />

11.7 Verwendung von Unterprogrammen (native methods, JNI) : : : : : : 156<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 5


12 Datenbanken 158<br />

12.1 Relationale Datenbanken : : : : : : : : : : : : : : : : : : : : : : : : : 158<br />

12.2 Structured Query Language (SQL) : : : : : : : : : : : : : : : : : : : 161<br />

12.3 Datenbank-Zugrie in <strong>Java</strong> (JDBC) : : : : : : : : : : : : : : : : : : 163<br />

12.4 Driver : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 165<br />

12.5 Connection : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 166<br />

12.6 Statement : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 167<br />

12.7 ResultSet : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 168<br />

12.8 PreparedStatement : : : : : : : : : : : : : : : : : : : : : : : : : : : : 170<br />

12.9 DatabaseMetaData und ResultSetMetaData : : : : : : : : : : : : : : 171<br />

12.10Datenbank-Anwendungen uber das Internet : : : : : : : : : : : : : : 172<br />

12.11Ubung: eine kleine Datenbank : : : : : : : : : : : : : : : : : : : : : : 173<br />

13 Referenzen 176<br />

Beilage: Losungen der Ubungsaufgaben<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 6


Grundlagen<br />

Was ist <strong>Java</strong>?<br />

Software und Online-Dokumentation<br />

Syntax und Statements<br />

Objekte und Klassen<br />

Fehlerbehandlung (Exceptions)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 7


1. Was ist <strong>Java</strong>?<br />

1.1 Insel, Kaee oder Programmiersprache<br />

<strong>Java</strong> wurde von der Firma Sun entwickelt und erstmals am 23. Mai 1995 als neue,<br />

objekt-orientierte, einfache und plattformunabhangige Programmiersprache vorgestellt.<br />

Sun besitzt weiterhin das Schutzrecht auf den Namen <strong>Java</strong>, die Sprache ist<br />

aber fur alle Computersysteme verfugbar (im allgemeinen kostenlos) und ist seit<br />

1997 auf dem Weg, eine ozielle ISO-Norm zu werden.<br />

<strong>Java</strong> geht auf die Sprache Oak zuruck, die 1991 von Bill Joy, James Gosling und<br />

Mike Sheridan im Green-Projekt entwickelt wurde, mit dem Ziel, eine einfache und<br />

plattformunabhangige Programmiersprache zu schaen, mit der nicht nur normale<br />

Computer wie Unix-Workstations, PCs und Apple programmiert werden konnen,<br />

sondern auch die in Haushalts- oder Industriegeraten eingebauten Micro-Computer,<br />

wie z.B. in Waschmaschinen und Videorekordern, Autos und Verkehrsampeln, Kreditkarten<br />

und Sicherheitssystemen und vor allem auch in TV-Settop-Boxes fur "intelligente"<br />

Fernsehapparate.<br />

Allgemein anerkannt wurde <strong>Java</strong> aber erst seit 1996 in Verbindung mit Web-<br />

Browsern und Internet-Anwendungen sowie mit der Idee eines NC (Network Computer),<br />

der im Gegensatz zum PC (Personal Computer) nicht lokal installierte, maschinenspezische<br />

Software-Programme benotigt, sondern die Software in Form von<br />

<strong>Java</strong>-Applets uber das Netz (Intranet) von einem zentralen Server laden kann.<br />

Der Name wurde nicht direkt von der sudostasiatischen Insel <strong>Java</strong> ubernommen<br />

sondern von einer bei amerikanischen Programmierern popularen Bezeichnung fur<br />

Kaee.<br />

Die wichtigsten Eigenschaften von <strong>Java</strong> sind:<br />

plattformunabhangig<br />

Objekt-orientiert<br />

Syntax ahnlich wie bei C und C++<br />

umfangreiche Klassenbibliothek<br />

Sicherheit von Internet-Anwendungen<br />

Bei <strong>Java</strong>-Programmen mu zwischen zwei grundsatzlichen Arten unterschieden werden:<br />

Applikationen und Applets.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 8


1.2 Applikationen (application)<br />

1.3 Applets<br />

<strong>Java</strong>-Applikationen sind Computer-Programme mit dem vollen Funktionsumfang,<br />

wie er auch bei anderen Programmiersprachen gegeben ist. Applikationen konnen<br />

als lokale Programme auf dem Rechner des Benutzers laufen oder als Client-Server-<br />

Systeme uber das Internet bzw. uber ein Intranet oder als Server-Programme (Servlets,<br />

CGI-Programme) auf einem Web-Server.<br />

Technisch gesehen zeichnen sich <strong>Java</strong>-Applikationen dadurch aus, da sie eine statische<br />

Methode main enthalten.<br />

<strong>Java</strong>-Applets werden innerhalb einer Web-Page dargestellt und unter der Kontrolle<br />

eines Web-Browsers ausgefuhrt. Sie werden meist uber das Internet von einem Server<br />

geladen, und spezielle Sicherungen innerhalb des Web-Browsers ("Sandkasten",<br />

sandbox) sorgen dafur, da sie keine unerwunschten Wirkungen auf den Client-<br />

Rechner haben konnen. So konnen Applets z.B. im allgemeinen nicht auf lokale<br />

Files, Systemkomponenten oder Programme zugreifen und auch nicht auf Internet-<br />

Verbindungen auer zu dem einen Server, von dem sie geladen wurden.<br />

Technisch gesehen zeichnen sich <strong>Java</strong>-Applets dadurch aus, da sie Unterklassen der<br />

Klasse Applet sind.<br />

Die meisten in dieser Kursunterlage beschriebenen Regeln gelten gleichermaen fur<br />

Applikationen und Applets. Die Spezialitaten, die nur fur Applets gelten, sind in<br />

einem eigenen Kapitel uber Applets zusammengefat.<br />

1.4 <strong>Java</strong>Script ist nicht <strong>Java</strong><br />

<strong>Java</strong>Script ist eine Skript-Sprache, die in HTML eingebettet werden kann und<br />

bei manchen Web-Browsern (Netscape, Internet-Explorer) die Ausfuhrung von bestimmten<br />

Funktionen und Aktionen innerhalb des Web-Browsers bewirkt.<br />

Im Gegensatz zu <strong>Java</strong> ist <strong>Java</strong>Script<br />

keine selbstandige Programmiersprache,<br />

nicht von der Browser-Version unabhangig,<br />

nicht mit den notwendigen Sicherheitsmechanismen ausgestattet.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 9


2. Software und Online-Dokumentation<br />

2.1 <strong>Java</strong> Development Kit (JDK)<br />

Das <strong>Java</strong> Development Kit (JDK) umfat die fur die Erstellung und das Testen<br />

von <strong>Java</strong>-Applikationen und Applets notwendige Software, die Packages mit den zur<br />

Grundausstattung gehorenden <strong>Java</strong>-Klassen, und die Online-Dokumentation.<br />

Zur Software gehoren der <strong>Java</strong>-Compiler, das <strong>Java</strong> Runtime Environment (die <strong>Java</strong><br />

Virtual Machine) fur die Ausfuhrung von Applikationen, der Appletviewer fur die<br />

Ausfuhrung von Applets, ein <strong>Java</strong>-Debugger und verschiedene Hilfsprogramme.<br />

Die Online-Dokumentation umfat eine Beschreibung aller Sprachelemente und aller<br />

Klassen des Application Program Interface API.<br />

<strong>Java</strong> ist eine sehr junge Programmiersprache und daher noch immer in Entwicklung,<br />

d.h. es kommen immer wieder neue Versionen mit Erganzungen und Verbesserungen<br />

heraus:<br />

Die Urversion ist JDK 1.0 (1995).<br />

Im Jahr 1997 kam Version 1.1 heraus, das brachte sowohl Anderungen und<br />

neue Konzepte (bei den Methodennamen gema den Beans-Konventionen,<br />

beim Event-Handlung, bei den Text-Files) als auch Erweiterungen durch<br />

zusatzliche Packages (z.B. fur Datenbanken).<br />

Ende 1998 kam Version 1.2 mit umfangreichen Erweiterungen (unter anderem<br />

Swing).<br />

Anfang 2000 folgte Version 1.3 mit Fehlerkorrekturen und Performance-<br />

Verbesserungen.<br />

Fu Ende 2001 oder 2002 kann mit einer neuen Version 1.4 gerechnet werden,<br />

die voraussichtlich wieder groere Erweiterungen bringen wird.<br />

Seit Version 1.2 wird das JDK auch "<strong>Java</strong>-Plattform 2" genannt, und das "<strong>Java</strong> 2<br />

Software Development Kit (SDK)" bedeutet dann das jeweils aktuelle JDK 1.x.<br />

Die Browser-Unterstutzung fur <strong>Java</strong>-Applets hinkt dieser Entwicklung meistens um<br />

1 bis 2 Jahre nach:<br />

Altere Web-Browser unterstutzen (wenn uberhaupt) nur Version 1.0.<br />

Neuere Browser-Versionen unterstutzen wenigstens teilweise Version 1.1 (Netscape<br />

ab Version 4.04-J2 bzw. 4.06, Internet Explorer ab Version 4.0).<br />

Mit Hilfe des "<strong>Java</strong> Activator" (<strong>Java</strong> Plug-in) von der Firma Sun kann man<br />

auch altere Browser-Versionen auf die jeweils neueste <strong>Java</strong>-Version (1.1, 1.2, ...)<br />

aufrusten sowie den Microsoft Internet Explorer, der <strong>Java</strong> nicht vollstandig unterstutzt,<br />

zu einem 100-prozentig <strong>Java</strong>-fahigen Browser machen. Bei Netscape<br />

ab Version 6.0, iPlanet und Mozilla ist dies der Standardfall.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 10


Wenn Sie Applets fur die Verwendung durch einen groeren Benutzerkreis uber<br />

das Internet erstellen, mussen Sie diese Einschrankungen berucksichtigen. Der mit<br />

dem JDK mitgelieferte Appletviewer unterstutzt die jeweilige Version ohne Einschrankungen.<br />

Das JDK fur ein bestimmtes System erhalt man meist kostenlos (z.B. zum Download<br />

uber das Internet) vom jeweiligen Hersteller, also die Solaris-Version von Sun,<br />

die HP-Version von HP, die IBM-Version von IBM. Versionen fur Windows-PC,<br />

Macintosh und Linux kann man von Sun oder IBM bekommen.<br />

2.2 Environment-Variable<br />

Normalerweise genugt es, das Directory, in dem sich die <strong>Java</strong>-Software bendet,<br />

in die PATH-Variable einzufugen. Die anderen Variablen (CLASSPATH,<br />

JAVA HOME) werden nur in Spezialfallen oder innerhalb der Software benotigt<br />

und mussen normalerweise nicht gesetzt werden. Die folgenden Hinweise sind also<br />

in den meisten Fallen nicht notwendig.<br />

Die Variable CLASSPATH gibt an, in welchen Directories nach Klassen und Packages<br />

gesucht werden soll, getrennt durch Doppelpunkte (Unix) bzw. Strichpunkte<br />

(Windows). Im allgemeinen gibt man hier den Punkt (fur das jeweils aktuelle Directory)<br />

und das Start-Directory der im JDK enthaltenen Packages an. Bei neueren<br />

JDK-Versionen ist das jedoch der Standard und der CLASSPATH soll daher gar<br />

nicht gesetzt werden.<br />

Die Variable JAVA HOME gibt an, in welchem Directory die Komponenten des<br />

JDK zu nden sind. Die explizite Angabe ist meistens ebenfalls nicht notwendig.<br />

Damit man den <strong>Java</strong>-Compiler, das Runtime-System, den Appletviewer etc. einfach<br />

aufrufen kann, sollte das entsprechende bin-Directory in der PATH-Variablen<br />

enthalten sein.<br />

Beispiele fur die eventuelle Denition dieser Environment-Variablen (die Details<br />

hangen von der jeweiligen Software-Version und deren Konguration und Installation<br />

ab):<br />

Unix, C-Shell, im File .cshrc:<br />

setenv PATH ${PATH}:/opt/java/bin<br />

setenv CLASSPATH .:/opt/java/src<br />

setenv JAVA_HOME /opt/java<br />

Unix, Korn-Shell oder Bourne-Shell, im File .prole oder .java wrapper:<br />

export PATH=${PATH}:/opt/java/bin<br />

export CLASSPATH=.:/opt/java/src<br />

export JAVA_HOME=/opt/java<br />

MS-Windows, im File autoexec.bat:<br />

set PATH=%PATH%;C:\jdk1.1.5\bin<br />

set CLASSPATH=.;C:\jdk1.1.5\lib\classes.zip;<br />

set JAVA_HOME=C:\jdk1.1.5<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 11


2.3 Filenamen<br />

Jedes <strong>Java</strong>-Source-File darf nur eine public Klasse enthalten, und der Filename<br />

mu dann der Name dieser Klasse (mit der richtigen Gro-Kleinschreibung) mit der<br />

Extension .java sein, hat also die Form<br />

Xxxxx.java<br />

Wenn man das Source-File auf einem PC mit MS-Word, Wordpad oder Notepad<br />

erstellt, mu man darauf achten, da es mit dem Dateityp Text-File (nicht Word-<br />

File) erstellt wird und da nicht automatisch eine Extension .txt angehangt wird.<br />

Eventuell mu man also beim Speichern den Filenamen mit Quotes in der Form<br />

"Xxxxx.java"<br />

schreiben, damit man nicht einen Filenamen der Form Xxxxx.java.txt erhalt.<br />

Der <strong>Java</strong>-Compiler erzeugt fur jede Klasse ein eigenes File, das den Bytecode dieser<br />

Klasse enthalt. Der Filename ist dann der Name der Klasse mit der Extension .class,<br />

hat also die Form<br />

Xxxxx.class<br />

Man kann auch mehrere Klassen-Files in ein komprimiertes Archiv-File zusammenfassen,<br />

das dann weniger Ubertragungszeit uber das Internet benotigt. Solche <strong>Java</strong>-<br />

Archiv-Files haben Namen der Form<br />

xxx.jar<br />

2.4 <strong>Java</strong> Compiler (javac)<br />

Der Aufruf des <strong>Java</strong>-Compilers erfolgt im einfachsten Fall in der Form<br />

javac Xxxxx.java<br />

Der Name des Source-Files mu mit der Extension .java angegeben werden, und es<br />

konnen auch mehrere Source-Files angegeben werden:<br />

javac Xxxxx.java Yyyyy.java<br />

Falls die Klasse andere Klassen verwendet, die neu ubersetzt werden mussen, werden<br />

diese automatisch ebenfalls ubersetzt, ahnlich wie bei der Unix-Utility make.<br />

Der Compiler erzeugt fur jede Klasse ein File Xxxxx.class, das den Bytecode enthalt.<br />

Dieser Bytecode ist plattformunabhangig: Egal auf was fur einem System der <strong>Java</strong>-<br />

Compiler aufgerufen wurde, der Bytecode kann auch auf jedem anderen Computersystem<br />

ausgefuhrt werden, zumindest wenn es sich um "100% pure <strong>Java</strong>" handelt,<br />

was bei manchen Microsoft-Produkten leider nicht garantiert ist.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 12


2.5 <strong>Java</strong> Runtime System (java)<br />

Die Ausfuhrung des Bytecodes einer <strong>Java</strong>-Applikation erfolgt durch Aufruf der <strong>Java</strong><br />

Virtual Machine JVM (im <strong>Java</strong> Runtime Environment JRE) in der Form<br />

java Xxxxx<br />

oder<br />

java Xxxxx parameter parameter<br />

Der Bytecode der Klasse Xxxxx mu im File Xxxxx.class oder in einem Archiv-File<br />

(zip, jar) liegen, der Klassenname mu aber ohne die Extension .class angegeben<br />

werden.<br />

Altere Versionen der JVM waren noch reine Bytecode-Interpreter und daher relativ<br />

langsam. Neuere Versionen erzeugen mit Hilfe von Just-in-Time-Compilation<br />

(JIT) und Hotspot-Technologie (Analyse des Laufzeitverhaltens) eine weitgehende<br />

Optimierung und Beschleunigung der Ausfuhrungszeit.<br />

2.6 Web-Browser und Appletviewer<br />

Die Darstellung und Ausfuhrung eines <strong>Java</strong>-Applet erfolgt durch Aufrufen der entsprechenden<br />

Web-Page (HTML-File) mit einem <strong>Java</strong>-fahigen Web-Browser wie z.B.<br />

Netscape, Internet-Explorer oder Hot<strong>Java</strong>.<br />

Fur Tests und innerhalb von <strong>Java</strong>-Schulungen empehlt sich die Verwendung des<br />

mit dem JDK mitgelieferten Appletviewer. Dies ist ein einfacher Browser, der alle<br />

HTML-Tags auer und ignoriert und nur das im HTML-File<br />

angefuhrte Applet ohne den Rest der Web-Page anzeigt. Der Aufruf erfolgt in der<br />

Form<br />

appletviewer xxxx.html<br />

oder<br />

appletviewer URL<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 13


2.7 Online-Dokumentation (API)<br />

Die Online-Dokumentation wird als API (application programmers interface) bezeichnet<br />

und kann zusatzlich zum JDK am eigenen Rechner installiert oder auf<br />

einem Web-Server gespeichert werden. Sie liegt in der Form von Web-Pages (HTML-<br />

Files mit Hypertext-Links) vor und kann mit jedem beliebigen Web-Browser gelesen<br />

werden, z.B. mit Netscape. Man kann den jeweiligen lokalen Filenamen direkt als<br />

Aufrufparameter angeben, oder man kann sich zum File "durchklicken" und es dann<br />

in die Bookmarks eintragen und spater von dort wiederum aufrufen.<br />

Beispiele (die Details hangen von der Konguration und Installation ab):<br />

Unix:<br />

netscape /opt/java/docs/api/tree.html &<br />

Windows:<br />

netscape.exe C:njdk1.x.xndocsnapintree.html<br />

Die wichtigsten Files innerhalb dieser Dokumentation sind:<br />

Class Hierarchy fur die Suche nach einer bestimmten Klasse und deren<br />

Konstruktoren, Datenfeldern und Methoden.<br />

All Names (Index of Fields and Methods) fur die Suche nach Datenfeldern<br />

und Methoden, wenn man nicht wei, in welcher Klasse sie deniert<br />

sind.<br />

In jedem dieser Files kann man mit dem "Find-in-current" Befehl des Web-Browsers<br />

(je nach Browser im Edit-Menu oder dergleichen) nach Namen oder Substrings suchen.<br />

Das All-Names-File ist sehr gro, es ist daher meistens schneller, die Suche<br />

im Class-Hierarchy-File zu beginnen.<br />

Wenn Sie einen Klassennamen anklicken, erhalten Sie die komplette Beschreibung<br />

dieser Klasse und ihrer Konstruktoren, Datenfelder und Methoden sowie eine<br />

Angabe ihrer Oberklassen. Falls Sie eine Methode in der Dokumentation einer Unterklasse<br />

nicht nden, dann sehen Sie in ihren Oberklassen nach (siehe Vererbung).<br />

Wenn Sie den Namen einer Methode (oder eines Konstruktors oder Datenfeldes)<br />

anklicken, erhalten Sie sofort die Beschreibung dieser Methode (bzw. des Konstruktors<br />

oder Datenfeldes). Dabei mussen Sie aber beachten, da es mehrere gleichnamige<br />

Methoden und Konstruktoren sowohl innerhalb einer Klasse (siehe Overloading)<br />

als auch in verschiedenen Klassen (siehe Overriding) geben kann.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 14


2.8 <strong>Java</strong>-Archive (jar)<br />

2.9 Software-Tools<br />

Ein <strong>Java</strong>-Archiv enthalt Dateien und eventuell auch ganze Directory-Strukturen<br />

(siehe Packages) in demselben komprimierten Format, das auch von PKZIP und<br />

Win-Zip verwendet wird. Sie werden mit dem Programm jar (java archiver) verwaltet,<br />

der Aufruf erfolgt ahnlich wie beim Unix-Programm tar (tape archiver):<br />

Archiv-File erstellen (create):<br />

tar -cvf xxx.jar *.class<br />

Inhalt eines Archiv-Files anzeigen (table of contents):<br />

tar -tvf xxx.jar<br />

einzelen Dateien aus einem Archiv-File herausholen (extract):<br />

tar -xvf xxx.jar Yyyy.class<br />

Der Herausholen bzw. "Auspacken" von Archiv-Files ist meistens gar nicht notig:<br />

Der <strong>Java</strong>-Compiler und die <strong>Java</strong> Virtual Machine konnen die Class-Files direkt aus<br />

dem Archiv-File lesen und laden. Zu diesem Zweck mu der Filename des Archiv-<br />

Files im Classpath angegeben sein bzw. bei Applets im ARCHIVE-Paremeter des<br />

Applet-Tag im HTML-File.<br />

Von mehreren Firmen werden Editoren, GUI-Builder, Entwicklungsumgebungen<br />

(Integrated Development Environments IDE) und andere Hilfsmittel angeboten, mit<br />

denen man <strong>Java</strong>-Applikationen und Applets moglichst bequem und einfach erstellen<br />

kann. Beispiele sind Kawa, NetBeans, Forte, JBuilder, JDeveloper, SuperCede,<br />

Visual Age, Visual Cafe, Visual J++ und viele andere. Alle diese Hilfsmittel haben<br />

Vor- und Nachteile. Manche von ihnen enthalten auch "native Compiler", die den<br />

plattformunabhangigen <strong>Java</strong>-Bytecode in ein Binarprogramm in der lokalen Maschinensprache<br />

ubersetzen.<br />

Ubersichten uber die verfugbaren Software-Tools und deren Bezugsquellen nden<br />

Sie auf den in den Referenzen angefuhrten Web-Servern, Erfahrungsberichte in den<br />

einschlagigen Usenet-Newsgruppen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 15


2.10 <strong>Java</strong> Beans<br />

2.11 Vorgangsweise<br />

Unter <strong>Java</strong> Beans ("Kaeebohnen") vesteht man kleine <strong>Java</strong>-Programme (Klassen)<br />

mit genau festgelegten Konventionen fur die Schnittstellen, die eine Wiederverwendung<br />

in mehreren Anwendungen (Applikationen und Applets) ermoglichen, ahnlich<br />

wie bei Unterprogramm-Bibliotheken in anderen Programmiersprachen. Dies ist vor<br />

allem in Hinblick auf das Software-Engineering von komplexen Programmsystemen<br />

interessant. Dafur gibt es ein eigenes Beans Development Kit BDK, das man zusaetzlich<br />

zum JDK installieren kann, und ein Package java.beans, das ab Version 1.1<br />

im JDK enthalten ist,<br />

Beans werden auch von vielen der oben erwahnten Software-Tools (IDE) unterstuetzt.<br />

Auch die Klassenbibliothek des JDK ist seit Version 1.2 weitgehend nach<br />

den Beans-Konventionen geschrieben, und manche Software-Firmen verkaufen spezielle<br />

<strong>Java</strong>-Beans fur bestimmte Anwendungen.<br />

Es ist empfehlenswert, auch beim Schreiben eigener <strong>Java</strong>-Programme moglichst die<br />

Konventionen von <strong>Java</strong>-Beans einzuhalten, also z.B. da jede Klasse einen Default-<br />

Konstruktor mit leerer Parameterliste haben soll, da die Methoden fur das Setzen<br />

und Abfragen von Datenfeldern Namen der Form setXxxxx und getXxxxx bzw.<br />

isXxxxx haben sollen, oder da alle Klassen so "selbstandig" programmiert werden<br />

sollen, da sie unabhang davon funktionieren, wie andere Klassen programmiert<br />

wurden.<br />

Mehr uber diese Grundsatze und Empfehlungen nden Sie im Kapitel uber Objekte<br />

und Klassen. Fur genauere Informationen uber Beans und BeanInfos wird auf die<br />

Referenzen verwiesen.<br />

Vorgangsweise bei Programmen (Applikationen)<br />

notepad "Xxxxx.java"<br />

javac Xxxxx.java<br />

java Xxxxx<br />

Vorgangsweise bei Applets<br />

notepad "Xxxxx.java"<br />

notepad "Xxxxx.html"<br />

javac Xxxxx.java<br />

appletviewer Xxxxx.html<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 16


2.12 Beispiel: Einfache HelloWorld-Applikation<br />

Es ist ublich, einen ersten Eindruck fur eine neue Programmiersprache zu geben,<br />

indem man ein extrem einfaches Programm zeigt, das den freundlichen Text "Hello<br />

World!" auf die Standard-Ausgabe schreibt.<br />

So sieht dieses Minimal-Programm als <strong>Java</strong>-Applikation aus:<br />

public class HelloWorld {<br />

public static void main (String[] args) {<br />

}<br />

}<br />

System.out.println("Hello World!");<br />

Dieses <strong>Java</strong>-Source-Programm mu in einem File mit dem Namen HelloWorld.java<br />

liegen. Die Ubersetzung und Ausfuhrung erfolgt dann mit<br />

javac HelloWorld.java<br />

java HelloWorld<br />

Ein als Muster fur objekt-orientierte <strong>Java</strong>-Programme besser geeignetes Beispiel fur<br />

eine HelloWorld-Applikation nden Sie im Kapitel uber Objekte und Klassen.<br />

Ein analoges Beispiel fur ein minimales HelloWorld-Applet nden Sie im Kapitel<br />

uber Applets.<br />

2.13 Ubung: HelloWorld-Applikation<br />

Schreiben Sie die oben angefuhrte HelloWorld-Applikation (oder eine Variante davon<br />

mit einem anderen Text) in ein <strong>Java</strong>-Source-File und ubersetzen Sie es und fuhren<br />

Sie es aus.<br />

2.14 Ubung: Online-Dokumentation<br />

Suchen Sie in der Online-Dokumentation (API) nach der Beschreibung der Methode<br />

println und des Objekts System.out.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 17


2.15 Typische Anfanger-Fehler<br />

Newbie: Ich habe das HelloWorld-Programm aus meinem <strong>Java</strong>-Buch abgeschrieben,<br />

aber es funktioniert nicht. :-(<br />

Oldie: Das ist schon richtig :-) so, das HelloWorld-Beispiel dient dazu, da Du die<br />

typischen Anfanger-Fehler kennenlernst und in Zukunft vermeiden kannst. Der erste<br />

Fehler war schon: Wenn Du uns nicht den genauen Wortlaut der Fehlermeldung, die<br />

Version Deiner <strong>Java</strong>-Software (JDK, IDE) und die relevanten Teile Deines Source-<br />

Programms dazusagst, konnen wir den Fehler nicht sehen und Dir nicht helfen. In<br />

diesem Fall kann ich nur raten. Du hast wahrscheinlich einen der folgenden typischen<br />

Newbie-Fehler gemacht:<br />

Du hast das Programm nicht genau genug abgeschrieben (Tippfehler, Gro-<br />

Kleinschreibung, Sonderzeichen, Leerstellen), lies doch die Fehlermeldungen<br />

und Korrekturhinweise, die der Compiler Dir gibt.<br />

Du hast das Programm nicht unter dem richtigen Filenamen abgespeichert.<br />

Wenn die Klasse HelloWorld heit, mu das File HelloWorld.java heien, nicht<br />

helloworld.java und auch nicht HelloWorld.java.txt, im letzteren Fall versuch<br />

es mit<br />

notepad "HelloWorld.java"<br />

Du hast beim Compiler nicht den kompletten Filenamen mit der Extension<br />

angegeben (wieder mit der richtigen Gro-Kleinschreibung):<br />

javac HelloWorld.java<br />

Du hast bei der Ausfuhrung nicht den Klassennamen ohne die Extension angegeben<br />

(wieder mit der richtigen Gro-Kleinschreibung):<br />

java HelloWorld<br />

In der Umgebungsvariable PATH ist das Directory, in dem sich die JDK-<br />

Software bendet, nicht neben den anderen Software-Directories enthalten,<br />

versuch<br />

set PATH=%PATH%;C:njdk1.2nbin<br />

oder wie immer das auf Deinem Rechner heien mu.<br />

Die Umgebungsvariable CLASSPATH ist (auf einen falschen Wert) gesetzt.<br />

Diese Variable sollte uberhaupt nicht gesetzt sein, nur in seltenen Spezialfallen<br />

und dann so, da sie sowohl die Stellen enthalt, wo die <strong>Java</strong>-<br />

Klassenbibliotheken liegen, als auch den Punkt fur das jeweils aktuelle Directory.<br />

Du hast den Compiler nicht in dem Directory bzw. Folder aufgerufen, in dem<br />

Du das <strong>Java</strong>-File gespeichert hast.<br />

Du hast ein Applet als Applikation aufgerufen, oder umgekehrt.<br />

Applikatonen, die eine main-Methode enthalten, mut Du mit<br />

java Classname<br />

aufrufen.<br />

Applets, die ein "extends Applet" oder "extends JApplet" enthalten, mut<br />

Du innerhalb eines geeigneten HTML-Files mit<br />

appletviewer xxxxx.html<br />

oder mit Netscape oder Internet-Explorer aufrufen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 18


3. Syntax und Statements<br />

Wie sage ich dem Computer, was er tun soll?<br />

Die Syntax und die Grundregeln der Sprache <strong>Java</strong> sind weitgehend identisch mit<br />

denen von C und C++. Es fehlen jedoch Sprachelemente, die leicht zu Programmfehlern<br />

fuhren konnen, wie Pointer-Arithmetik, Operator-Overloading und Goto.<br />

3.1 Grundbegrie der Programmierung<br />

Programm-Elemente<br />

Fur diejenigen, die noch keine Erfahrung mit Programmiersprachen haben, hier eine<br />

kurze Zusammenstellung der wichtigsten Elemente, die in Computer-Programmen<br />

vorkommen, und der wichtigsten Konzepte fur die Programmierung. In den folgenden<br />

Abschnitten lernen Sie dann, wie Sie diese Elemente in der Programmiersprache<br />

<strong>Java</strong> formulieren konnen.<br />

Variable = Datenfelder<br />

Konstante = Datenwerte<br />

Dateien (Files) = Ein- und Ausgabe von Daten<br />

Anweisungen (Statements) = Aktionen<br />

{ eine nach der anderen ;<br />

{ Abzweigungen (if, switch)<br />

{ Schleifen (for, while, do)<br />

strukturierte Programmierung:<br />

{ Blocke von Statements fg<br />

{ Unterprogramme (Methoden)<br />

{ Hauptprogramm (main)<br />

Konzepte bei der Programmierung<br />

strukturierte Programmierung: moglichst kleine Einheiten<br />

objekt-orientierte Programmierung: Daten & Aktionen<br />

top-down: zuerst das Grundgerust, dann die Details<br />

bottom-up: zuerst die Einzelteile, dann zusammenbauen<br />

model-view-controller (bei Graphical User Interfaces): zuerst die Daten,<br />

dann die Darstellung der Daten, dann die Steuerung ( Anderung der Daten)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 19


3.2 Namenskonventionen<br />

Es wird dringend empfohlen, die folgenden Konventionen bei der Wahl von Namen<br />

strikt einzuhalten und ausfuhrliche, gut verstandliche Namen zu verwenden:<br />

Namen von Klassen und Interfaces beginnen mit einem Grobuchstaben und<br />

bestehen aus Gro- und Kleinbuchstaben und Ziern. Beispiel: HelloWorld, Button2.<br />

Namen von Konstanten beginnen mit einem Grobuchstaben und bestehen nur aus<br />

Grobuchstaben, Ziern und Underlines. Beispiel: MAX SPEED.<br />

Alle anderen Namen (Datenfelder, Methoden, Objekte, Packages etc.) beginnen<br />

mit einem Kleinbuchstaben und bestehen aus Gro- und Kleinbuchstaben und<br />

Ziern. Beispiele: openFileButton, button2, addActionListener, setSize, getSize.<br />

Vom System intern generierte Namen konnen auch Dollarzeichen enthalten.<br />

Gro- und Kleinbuchstaben haben in jedem Fall verschiedene Bedeutung (casesensitive).<br />

3.3 Reservierte Worter<br />

3.4 Datentypen<br />

Die folgenden Namen sind reserviert und durfen nicht neu deklariert werden:<br />

abstract, boolean, break, byte, case, catch, char, class, continue, default, do, double,<br />

else, extends, false, nal, nally, oat, for, generic, goto, if, implements, import,<br />

instanceof, int, interface, long, native, new, null, package, private, protected, public,<br />

return, short, static, super, switch, synchronized, this, throw, throws, transient, true,<br />

try, void, volatile, while.<br />

Die Datentypen und ihre Eigenschaften (Lange, Genauigkeit) hangen nicht vom<br />

jeweiligen Computersystem ab sondern sind in <strong>Java</strong> einheitlich festgelegt. Es wird<br />

zwischen primitiven Datentypen und Objekt-Typen (Klassen) unterschieden.<br />

Primitive Datentypen:<br />

ganze Zahlen: byte, short, int, long<br />

Gleitkomma-Zahlen: float, double<br />

Logischer Typ (true oder false): boolean<br />

Zeichen (Unicode, Zahlenwert ohne Vorzeichen): char<br />

Objekt-Typen:<br />

Zeichenketten (Unicode): String<br />

sowie alle als Klassen denierten Typen<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 20


3.5 Konstante (Literals)<br />

Normale ganze Zahlen haben den Typ int und werden dezimal interpretiert. Den<br />

Typ long kann man durch Anhangen von L erzeugen. Oktale Zahlen beginnen mit<br />

0 (Null), hexadezimale mit 0x (Null und x).<br />

Normale Zahlen mit Dezimalpunkt (oder mit D fur den Exponent) haben den Typ<br />

double. Den Typ oat kann man durch Anhangen von F oder durch die Angabe von<br />

Efur den Exponent erzeugen.<br />

Logische Konstanten sind die Worter true und false.<br />

char-Konstanten werden zwischen einfachen Apostrohpen geschrieben, Beispiel: 'A'.<br />

String-Konstanten werden zwischen Double-Quotes geschrieben, Beispiel: "Hubert<br />

Partl". Double-Quotes innerhalb des Strings mussem mit einem Backslash maskiert<br />

werden. Sonderzeichen konnen mit Backslash und u und dem Unicode-Wert angegeben<br />

werden, also z.B. 'nu20ac' fur das Euro-Zeichen.<br />

Beispiele:<br />

byte b; b=123;<br />

short i; i=-1234;<br />

int i; i=-1234;<br />

long i; i=-1234L;<br />

float x; x=-123.45F; x=1.0E-23;<br />

double x; x=-123.45; x=1.0D-23;<br />

boolean b; b=true; b=false;<br />

char c; c='A';<br />

String s; s="Abc"; s=null;<br />

3.6 Deklarationen und Anfangswerte<br />

Deklaration eines Datenfeldes:<br />

typ name;<br />

Deklaration von mehreren Datenfeldern desselben Typs:<br />

typ name1, name2, name3;<br />

Zuweisung eines Wertes:<br />

name = wert;<br />

Zuweisung eines Wertes mit Typumwandlung (casting):<br />

name = (typ) wert;<br />

Deklaration mit Zuweisung eines Anfangswertes:<br />

typ name = wert;<br />

Achtung! Die Deklaration gilt immer nur fur den Bereich (Klasse, Methode, Block<br />

innerhalb einer Methode), innerhalb dessen die Deklaration steht. Es kann verwirrend<br />

sein, wenn man innerhalb eines Blockes denselben Namen, der bereits fur eine<br />

globale Variable gewahlt wurde, fur eine gleichnamige lokale Variable verwendet.<br />

Wenn man vor die Typangabe das Wort final setzt, handelt es sich um eine Konstante,<br />

d.h. der Wert dieses Datenfeldes kann nicht nachtraglich verandert werden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 21


3.7 Referenzen (reference) auf Objekte oder Strings<br />

Deklaration einer Variablen, die eine Referenz auf Objekte einer bestimmten Klasse<br />

enthalten kann:<br />

ClassName name;<br />

ClassName name = null;<br />

Anlegen eines Objekts (einer Instanz) dieser Klasse und Zuweisung der Referenz<br />

auf dieses Objekt an die deklarierte Variable:<br />

name = new ClassName();<br />

wobei ClassName() fur einen Konstruktor (constructor) der Klasse steht.<br />

Deklaration, Anlegen und Zuweisen in einem:<br />

ClassName name = new ClassName();<br />

Deklaration und Anlegen von Strings:<br />

String s;<br />

String s = null;<br />

s = "Hubert Partl";<br />

String myName = "Hubert Partl";<br />

3.8 Garbage Collector<br />

Objekte werden mit den Operator new und dem Konstruktor explizit angelegt und<br />

dabei der Speicherplatz fur das Objekt reserviert und mit den Anfangswerten belegt.<br />

Sobald es keine Referenz mehr auf das Objekt gibt (z.B. durch Zuweisen von null<br />

auf die einzige Referenz-Variable), wird der vom Objekt belegte Speicherplatz durch<br />

den im Hintergrund laufenden Garbage-Collector automatisch zuruckgegeben und<br />

fur neuerliche Verwendung frei gemacht.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 22


3.9 Felder (array)<br />

Deklaration einer Variablen, die eine Referenz auf ein Feld enthalten kann:<br />

typ[] name;<br />

Anlegen eines Feldes von n Elementen dieses Typs und Zuweisung der Referenz<br />

auf dieses Feld an die Referenz-Variable:<br />

name = new typ [n];<br />

Deklaration und Anlegen in einem:<br />

typ[] name = new typ [n];<br />

Beispiel:<br />

double[] monatsUmsatz = new double[12];<br />

...<br />

Eine Array-Referenz kann nacheinander Felder verschiedener Lange (aber nur gleichen<br />

Typs) enthalten. Beispiel:<br />

double[] tagesUmsatz;<br />

...<br />

tagesUmsatz = new double[31];<br />

...<br />

tagesUmsatz = new double[28];<br />

...<br />

Zuweisen von Werten zu den Feldelementen:<br />

for (int i=0; i


Feld von Objekten<br />

Classname[] name = new Classname [n];<br />

for (int i=0; i


3.10 Ausdrucke (expression) und Operatoren<br />

Objekt-Operatoren: new .<br />

Mathematische Operatoren: + - * / %<br />

Mathematische Zuweisungen: ++ -- = *= /= %= += -=<br />

Logische Operatoren: < > = == != instanceof && ||<br />

Bit-Operatoren: > >>> & |<br />

Bit-Zuweisungen: = >>>= &= |=<br />

String-Operatoren:<br />

+ equals<br />

Achtung! Bei Referenzen auf Objekte oder Strings vergleichen die Operatoren ==<br />

und != nur, ob die Referenz dieselbe ist, nicht, ob der Inhalt des Strings oder des<br />

Objekts gleich ist. Dafur mu die equals-Methode des Objekts verwendet werden.<br />

Beispiel:<br />

String vorName;<br />

...<br />

if ( vorName.equals("Hubert") )<br />

...<br />

Typ-Umwandlungen (Casting)<br />

In manchen Fallen kann der Compiler Typen automatisch umwandeln, z.B. bei der<br />

Zuweisung von int auf long oder double:<br />

int i = ...;<br />

double d = i + 1;<br />

In vielen Fallen mu man dem Compiler aber mitteilen, in welchen Datentyp ein<br />

Wert umgewandelt werden soll. Dies wird als Casting bezeichnet, dazu wird der<br />

neue Typ zwischen Klammern angegeben:<br />

typ1 name1 = ...;<br />

typ2 name2 = (typ2) name1;<br />

Dies ist inbesondere dann wichtig, wenn man sicherstellen will, da eine Multiplikation<br />

mit der vollen Genauigkeit von long oder double erfolgt statt mit der geringeren<br />

Genauigkeit von int oder oat, oder da eine Division mit Bruchteilen (oat oder<br />

double) statt nur ganzzahlig mit Abschneiden des Restes erfolgt. Beispiel:<br />

int i = ... ;<br />

double d = ( (double) i ) / 100.0 ;<br />

Fur die Umwandlung von oat oder double auf int oder long gibt es die Methoden<br />

Math.oor, Math.ceil, Math.round, je nachdem, ob man abrunden, aufrunden oder<br />

kommerziell runden will.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 25


3.11 Text-Operationen (String)<br />

Die Lange eines Strings erhalt man mit der Methode<br />

length()<br />

Beispiel:<br />

String name="Hubert Partl";<br />

int len=name.length();<br />

Fur das Zusammenfugen von mehreren Strings zu einem langeren String gibt es den<br />

Operator +. Beispiel:<br />

String name = vorName + " " + zuName;<br />

Fur die Abfrage auf Gleichheit gibt es die Methode equals (siehe oben). Beispiel:<br />

if (vorName.equals("Hubert") ...<br />

Auerdem enthalt die Klasse String zahlreiche weitere Methoden fur das Erzeugen<br />

von Substrings oder von veranderten Strings (z.B. Zeichenersetzung, Umwandlung<br />

auf Gro- oder Kleinbuchstaben), sowie fur die Abfrage von Zeichen und Substrings<br />

innerhalb eines Strings und fur die alphabetische Reihenfolge von 2 Strings. Die<br />

Details entnehmen Sie bitte der Online-Dokumentation der Klasse String.<br />

Fur komplexere Anwendungen, bei denen ein Text-String in Einzelteile (z.B. Worter)<br />

zerlegt werden soll, gibt es eine eigene Klasse StringTokenizer.<br />

Fur die Umwandlung von Strings, die Ziern enthalten, in entsprechende Zahlenwerte<br />

gibt es eigene statische Methoden wie z.B.<br />

int Integer.parseInt(String)<br />

long Long.parseLong(String)<br />

float Float.valueOf(String).floatValue()<br />

double Double.valueOf(String).doubleValue()<br />

Ab JDK 1.2 wird das einheitlicher, dann gibt es auch<br />

float Float.parseFloat(String)<br />

double Double.parseDouble(String)<br />

Wie Sie die dabei eventuell auftretenden Fehler abfangen mussen, ist im Kapitel<br />

uber Exceptions beschrieben.<br />

Fur die umgekehrte Umwandlung von Zahlen in Strings kann man die Methode<br />

String s = String.valueOf(zahl);<br />

oder auch den folgenden Trick verwenden:<br />

String s = "" + zahl;<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 26


3.12 Funktionen (Math)<br />

Mathematische Funktionen konnen mit Hilfe der statischen Methoden in der Klasse<br />

Math aufgerufen werden. Beispiel:<br />

x = Math.sqrt(y);<br />

Die Details nden Sie in der Online-Dokumentation (API). Mehr uber Methoden<br />

und statische Methoden nden Sie im Kapitel uber Objekte und Klassen.<br />

3.13 Statements und Blocke<br />

Statements werden mit ; (Strichpunkt, Semicolon) beendet.<br />

Blocke von Statements werden zwischen f und g (geschwungene Klammern, braces)<br />

eingeschlossen und konnen leer sein oder ein oder mehrere Statements enthalten, die<br />

jeweils mit ; beendet werden.<br />

3.14 Kommentare<br />

Alles, was zwischen /* und */ oder zwischen // und dem Zeilenende steht, wird<br />

vom <strong>Java</strong>-Compiler ignoriert und gilt als Kommentar.<br />

Beispiele:<br />

... // Kommentar bis Zeilenende<br />

... /* Kommentar */ ...<br />

Mit /** in der ersten Zeile, * am Beginn aller weiteren Zeilen und */ am Ende<br />

kann man Dokumentations-Kommentar schreiben, der dann mit Hilfsprogrammen<br />

extrahiert und ausgedruckt werden kann (siehe javadoc).<br />

3.15 if und else<br />

if ( logischer Ausdruck ) {<br />

Statements;<br />

}<br />

if ( logischer Ausdruck ) {<br />

Statements;<br />

}<br />

else {<br />

Statements;<br />

}<br />

3.16 for<br />

for ( int name=Anfangswert ; logischer Ausdruck ; Wertaenderung ) {<br />

Statements;<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 27


3.17 while und do<br />

while ( logischer Ausdruck ) {<br />

Statements;<br />

}<br />

do {<br />

Statements;<br />

} while ( logischer Ausdruck );<br />

3.18 switch und case<br />

switch ( ganzzahliger Ausdruck ) {<br />

case wert1:<br />

Statements;<br />

break;<br />

case wert2:<br />

Statements;<br />

break;<br />

...<br />

default:<br />

Statements;<br />

}<br />

Achtung! Falls die auf eine case-Angabe folgenden Statements nicht mit break; enden<br />

oder dort uberhaupt keine Statements stehen, werden auch die bei der folgenden<br />

case-Angabe stehenden Statements ausgefuhrt.<br />

3.19 break und continue<br />

Mit continue; kann man den aktuellen Schleifendurchgang vorzeitig beenden und<br />

den nachsten Schleifendurchgang beginnen.<br />

Mit break; kann man eine Schleife oder einen case-Block verlassen und zum Statement<br />

nach Ende der Schleife bzw. des switch-Blockes springen.<br />

Mit labelname: kann man einen Label vor ein for-, while- oder do-Statement setzen<br />

und dann mit continue labelname; bzw. break labelname; diese (auere) Schleife<br />

vorzeitig beenden.<br />

Es gibt in <strong>Java</strong> kein goto-Statement zum Sprung an beliebige Stellen.<br />

3.20 System.exit<br />

Mit System.exit(0); oder System.exit(n); kann man die Applikation vorzeitig<br />

beenden. Bei Erreichen des Endes der main-Methode wird das Programm automatisch<br />

beendet.<br />

Bei erfolgreicher Beendigung gibt man als Exit-Code 0 an, bei einer nicht erfolgreichen<br />

Beendigung eine positive ganze Zahl als Fehler-Code, im einfachsten Fall<br />

den Wert 1.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 28


3.21 Beispiele fur einfache Programme<br />

Wertzuweisungen<br />

public class ProgExpr {<br />

public static void main (String[] args) {<br />

int guthaben = 1000;<br />

System.out.println("Guthaben = " + guthaben);<br />

int einzahlung = 500;<br />

System.out.println("Einzahlung = " + einzahlung);<br />

guthaben = guthaben + einzahlung;<br />

System.out.println("Guthaben = " + guthaben);<br />

}<br />

}<br />

if<br />

for<br />

while<br />

public class ProgIf {<br />

public static void main (String[] args) {<br />

int guthaben = 2000000;<br />

System.out.println("Guthaben = " + guthaben);<br />

if ( guthaben >= 1000000 ) {<br />

System.out.println("Gratuliere, Du bist Millionaer!");<br />

}<br />

}<br />

}<br />

public class ProgFor {<br />

public static void main (String[] args) {<br />

int guthaben = 1000;<br />

int einzahlung = 500;<br />

System.out.println("Guthaben = " + guthaben);<br />

System.out.println("Einzahlung = " + einzahlung<br />

+ " pro Monat");<br />

for ( int monat=1; monat


}<br />

System.out.println ("Sparziel = " + sparziel);<br />

while ( guthaben < sparziel ) {<br />

guthaben = guthaben + einzahlung;<br />

System.out.println ("neues Guthaben = " + guthaben);<br />

}<br />

System.out.println( "Sparziel erreicht.");<br />

}<br />

switch<br />

public class ProgSwitch {<br />

public static void main (String[] args) {<br />

int note = 2;<br />

switch (note) {<br />

case 1:<br />

System.out.println("sehr gut");<br />

break;<br />

case 2:<br />

System.out.println("gut");<br />

break;<br />

case 3:<br />

System.out.println("befriedigend");<br />

break;<br />

case 4:<br />

System.out.println("genuegend");<br />

break;<br />

case 5:<br />

System.out.println("nicht genuegend");<br />

break;<br />

}<br />

}<br />

}<br />

switch (note) {<br />

case 1:<br />

System.out.print("mit Auszeichnung ");<br />

case 2:<br />

case 3:<br />

case 4:<br />

System.out.println("bestanden");<br />

break;<br />

case 5:<br />

System.out.println("nicht bestanden");<br />

break;<br />

}<br />

Blocke<br />

public class ProgBlock {<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 30


}<br />

Ein- und Ausgabe<br />

public static void main (String[] args) {<br />

int note;<br />

String beurteilung;<br />

System.out.println ("Notentabelle:");<br />

for ( note = 1; note


}<br />

}<br />

alter = Integer.parseInt ( zeile.trim() );<br />

System.out.println ("Du bist " + alter + " Jahre alt.");<br />

} catch (Exception e) {<br />

System.out.println("falsche Eingabe - " + e);<br />

}<br />

3.22 Fehlersuche und Fehlerbehebung (Debugging)<br />

Computer sind unglaublich dumme Gerate,<br />

die unglaublich intelligente Sachen konnen.<br />

Programmierer sind unglaublich intelligente Leute,<br />

die unglaublich dumme Sachen produzieren.<br />

("Die Presse", 30.8.1999)<br />

Programmfehler (auf englisch bugs = Wanzen, Ungeziefer genannt) gehoren zum<br />

taglichen Brot jedes Programmierers. Nur wer nichts arbeitet, macht keine Fehler.<br />

Der gute Programmierer ist nicht der, der keine Fehler macht, sondern der, der seine<br />

Fehler rasch ndet und behebt.<br />

Es gibt eigene Software-Tools, die bei der Fehlersuche helfen konnen. In den meisten<br />

Fallen genugt es aber, an allen wichtigen Stellen im Programm mit System.out.println<br />

oder System.err.println Informationen uber das Erreichen dieser<br />

Programmstelle und uber den Inhalt von wichtigen Variablen auszugeben. Damit<br />

kann man dann meistens sehr rasch nden, wo, wann und warum ein Programmfehler<br />

aufgetreten ist und was man tun mu, im ihn zu vermeiden. Beispielskizze:<br />

...<br />

System.out.println("* Beginn der Schleife");<br />

System.out.println("n = " + n);<br />

for (int i=0; i


mit TEST = false komplett weggelassen werden und weder Speicherplatz noch Abfragezeit<br />

kosten. Beispielskizze:<br />

public class Classname {<br />

private static final boolean TEST = false;<br />

...<br />

public ... methodName () {<br />

...<br />

if (TEST) {<br />

System.err.println( ... test information ... );<br />

}<br />

...<br />

}<br />

}<br />

Wenn man ein Paket von mehreren Klassen testen will, kann es gunstiger sein, alle<br />

Denitionen in einer eigenen Klasse (Dened) festzulegen und dann in allen Klassen<br />

in der Form Dened.TEST zu verwenden. Beispielskizze:<br />

public class Defined {<br />

public static final boolean TEST = false;<br />

public static final boolean XXXX = true;<br />

...<br />

}<br />

public class Classname {<br />

...<br />

if (Defined.TEST) {<br />

...<br />

}<br />

...<br />

}<br />

Auerdem ist es fur das Verstehen und die (eventuell erst Jahre spater erfolgende)<br />

Wartung der Programme wichtig, mit Kommentaren innerhalb der Programme<br />

moglichst ausfuhrliche Hinweise auf den Zweck und die Funktionsweise des Programmes<br />

und der einzelnen Programmabschnitte sowie Erklarungen zu allen programmtechnischen<br />

Tricks anzugeben.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 33


3.23 Dokumentation von Programmen (javadoc)<br />

Mit dem Hilfsprogramm javadoc, das Teil des JDK ist, kann eine Dokumentation<br />

der <strong>Java</strong>-Programme im HTML-Format erzeugt werden, so wie die Online-<br />

Dokumentation (API) der Klassenbibliothek.<br />

Der Aufruf von<br />

javadoc Xxxx.java<br />

fur einzelne Source-Programme oder<br />

javadoc *.java<br />

fur alle <strong>Java</strong>-Programme im aktuellen Directory erzeugt fur jedes Source-Programm<br />

ein Dokumentations-File Xxxx.html sowie einen Package-Index packages.html, einen<br />

Klassen-Index tree.html und einen Namens-Index AllNames.html. Vorsicht, bereits<br />

existierende gleichnamige Dateien werden dabei uberschrieben.<br />

<strong>Java</strong>doc extrahiert automatisch alle public und protected Deklarationen von Klassen,<br />

Datenfeldern, Konstruktoren und Methoden. Zusatzliche Informationen kann<br />

man in Form von speziellen Kommentaren hinzufugen, die jeweils in<br />

/** ... */<br />

eingeschlossen werden, vor der jeweiligen Deklaration stehen und einfachen HTML-<br />

Text enthalten.<br />

Beispiel:<br />

/**<br />

* ein einfaches Hello-World-Programm.<br />

* <br />

* Im Gegensatz zum kurzen, rein statischen "HelloWorld"<br />

* ist dieses Programm ein Musterbeispiel<br />

* f&uuml;r eine objekt-orientierte <strong>Java</strong>-Applikation.<br />

*<br />

* @author Hubert Partl<br />

* @version 99.9<br />

* @since JDK 1.0<br />

* @see HelloWorld<br />

*/<br />

public class HelloDoc {<br />

/** der Text, der gedruckt werden soll.<br />

*/<br />

public String messageText = "Hello World!";<br />

/** druckt den Text messageText auf System.out aus.<br />

* @see #messageText<br />

*/<br />

public void printText() {<br />

System.out.println (messageText);<br />

}<br />

/** Test des HelloDoc-Objekts.<br />

*/<br />

public static void main (String[] args) {<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 34


}<br />

}<br />

HelloDoc h = new HelloDoc();<br />

h.printText();<br />

Die von javadoc erstellte Dokumentation nden Sie im File HelloDoc.html.<br />

3.24 Ubung: einfaches Rechenbeispiel Quadratzahlen<br />

Schreiben Sie eine einfache Applikation, in der Sie die Quadratzahlen von ein paar<br />

ganzen Zahlen berechnen und ausgeben:<br />

1*1=1<br />

2*2=4<br />

3*3=9<br />

usw. bis<br />

20 * 20 = 400<br />

3.25 Ubung: einfaches Rechenbeispiel Sparbuch<br />

Schreiben Sie eine Applikation, die fur einen bestimmten Geldbetrag und einen<br />

bestimmten Zinssatz ausgibt, wie sich dieser Wert Jahr fur Jahr erhoht (fur 10<br />

Jahre, jeweils Jahr und Wert).<br />

Anmerkung: Der Wert erhoht sich jedes Jahr um den Faktor<br />

(100.0 + zinssatz) / 100.0<br />

Erweiterte Versionen dieses Beispiels als Applikation mit Fehlerbehandlung und als<br />

Applet mit graphischem User-Interface folgen in den Kapiteln uber Fehlerbehandlungen<br />

und Applets.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 35


4. Objekte und Klassen<br />

4.1 Objekt-Orientierung<br />

Objekt = ( Daten & Aktionen )<br />

Bei der konventionellen Programmierung erfolgt die Denition der Datenstrukturen<br />

und der mit den Daten ausgefuhrten Prozeduren (Aktionen) unabhangig voneinander.<br />

Das Wissen um die Bedeutung der Daten und die zwischen ihnen bestehenden<br />

Beziehungen ist nicht einfach bei den Daten sondern mehrfach in allen Programmen,<br />

die auf diese Daten zugreifen, gespeichert.<br />

Bei der objekt-orientierten Programmierung (OOP) werden Objekte ganzheitlich<br />

beschrieben, d.h. die Festlegung der Datenstrukturen und der mit den Daten ausgefuhrten<br />

Aktionen erfolgt in einem.<br />

Die wichtigsten Vorteile der objekt-orientierten Programmierung sind:<br />

Aufspaltung von komplexen Software-Systemen in kleine, einfache, in sich geschlossene<br />

Einzelteile,<br />

einfache und klar verstandliche Schnittstellen zwischen den einzelnen Komponenten,<br />

weitgehende Vermeidung von Programmierfehlern beim Zusammenspiel zwischen<br />

den Komponenten,<br />

geringer Programmieraufwand durch die Wiederverwendung von Elementen<br />

(Vererbung).<br />

Je kleiner und einfacher die Objekte und Klassen und die Schnittstellen zwischen<br />

ihnen gewahlt werden (Kapselung, Vererbung), desto besser werden diese Ziele erreicht.<br />

Mehr daruber folgt spater im Kapitel uber Objekt-orientierte Analyse und<br />

Design.<br />

prozeduraler Programmaufbau (Beispiel COBOL)<br />

DATA DIVISION.<br />

01 DDD1.<br />

... Datenblock 1 ...<br />

01 DDD2.<br />

... Datenblock 2 ...<br />

...<br />

PROCEDURE DIVISON.<br />

AAA1 SECTION.<br />

... Aktionen Teil 1 ...<br />

AAA2 SECTION.<br />

... Aktionen Teil 2 ...<br />

...<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 36


prozeduraler Programmaufbau (Beispiel C)<br />

struct ddd1 {<br />

... Datenblock 1 ...<br />

}<br />

struct ddd2 {<br />

... Datenblock 2 ...<br />

}<br />

...<br />

aaa1() {<br />

... Aktionen Teil 1 ...<br />

}<br />

aaa2() {<br />

... Aktionen Teil 2 ...<br />

}<br />

...<br />

objekt-orientierter Programmaufbau (Beispiel <strong>Java</strong>)<br />

public class Ccc1 {<br />

... Daten von Objekt-Typ 1 ...<br />

... Aktionen von Objekt-Typ 1 ...<br />

}<br />

public class Ccc2 {<br />

... Daten von Objekt-Typ 2 ...<br />

... Aktionen von Objekt-Typ 2 ...<br />

}<br />

...<br />

4.2 Klassen (class)<br />

Als Klasse (class) bezeichnet man die Denition einer Idee, eines Konzepts, einer<br />

Art von Objekten.<br />

Als Objekt (object) bzw. Instanz (instance) bezeichnet man eine konkrete<br />

Auspragung eines Objekts, also ein Stuck aus der Menge der Objekte dieser Klasse.<br />

Beispiele: Hubert Partl und Monika Kleiber sind Objekte der Klasse Mitarbeiter.<br />

Die Universitat fur Bodenkultur ist ein Objekt der Klasse Universitat.<br />

Je einfacher die Klassen gewahlt werden, desto besser. Komplexe Objekte konnen<br />

aus einfacheren Objekten zusammengesetzt werden (z.B. ein Bucherregal enthalt<br />

Bucher, ein Buch enthalt Seiten, ein Atlas enthalt Landkarten). Spezielle komplizierte<br />

Eigenschaften konnen auf grundlegende einfache Eigenschaften zuruckgefuhrt<br />

werden (Vererbung, z.B. ein Atlas ist eine spezielle Art von Buch).<br />

Denition von Klassen - Aufbau von <strong>Java</strong>-Programmen<br />

<strong>Java</strong>-Programme sind grundsatzlich Denitionen von Klassen. Sie haben typisch<br />

den folgenden Aufbau:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 37


public class ClassName {<br />

// Definition von Datenfeldern<br />

// Definition von Konstruktoren<br />

// Definition von Methoden<br />

}<br />

Die Reihenfolge der Denitionen innerhalb der Klasse ist grundsatzlich egal, aber<br />

ich empfehle, immer eine Konvention wie z.B. die hier angefuhrte Reihenfolge einzuhalten.<br />

Verwendung von Klassen - Anlegen von Objekten<br />

Objekte werden in <strong>Java</strong>-Programmen mit dem Operator new und einem Konstruktor<br />

der Klasse angelegt. Beispiel:<br />

House myNewHome = new House();<br />

Innerhalb der Klasse kann man das aktuelle Objekt dieser Klasse mit dem symbolischen<br />

Namen this ansprechen.<br />

4.3 Beispiel: objekt-orientierte HelloWorld-Applikation<br />

public class HelloText {<br />

public String messageText = "Hello World!";<br />

// or: private ...<br />

public void printText() {<br />

System.out.println (messageText);<br />

}<br />

}<br />

public static void main (String[] args) {<br />

HelloText h = new HelloText();<br />

h.printText();<br />

}<br />

Im Gegensatz zum statischen Hello-World-Programm lat sich das objekt-orientierte<br />

Programm leicht erweitern. Beispiel:<br />

public class MultiText {<br />

public static void main (String[] args) {<br />

HelloText engl = new HelloText();<br />

HelloText germ = new HelloText();<br />

germ.messageText = "Hallo, liebe Leute!";<br />

HelloText cat = new HelloText();<br />

cat.messageText = "Meow!";<br />

engl.printText();<br />

germ.printText();<br />

engl.printText();<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 38


}<br />

}<br />

cat.printText();<br />

engl.printText();<br />

4.4 Datenfelder (member eld)<br />

Datenfelder der Klasse werden typisch in der folgenden Form deklariert:<br />

public typ name;<br />

public typ name = anfangswert;<br />

Nachdem ein Objekt dieser Klasse angelegt wurde, konnen seine Datenfelder in der<br />

Form<br />

object.name<br />

angesprochen werden. Wenn private statt public angegeben wurde, konnen sie<br />

jedoch von auen nicht direkt angesprochen werden (siehe Kapselung).<br />

Datenfelder der Klasse sind eine Art von "globalen Variablen" fur alle Methoden<br />

der Klasse und fur eventuelle innere Klassen.<br />

Innerhalb der Klasse kann man die Datenfelder einfach mit<br />

name<br />

ansprechen, oder in der Form<br />

this.name<br />

wenn eine Unterscheidung von gleichnamigen lokalen Variablen oder Parametern<br />

notwendig ist.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 39


4.5 Methoden (method)<br />

Methoden entsprechen den Funktionen oder Prozeduren in konventionellen Programmiersprachen.<br />

Die Deklaration erfolgt in der folgenden Form:<br />

Methode mit Ruckgabewert:<br />

public typ name () {<br />

Statements;<br />

return wert;<br />

}<br />

Methode ohne Ruckgabewert:<br />

public void name () {<br />

Statements;<br />

}<br />

Methode mit Parametern:<br />

public typ name (typ name, typ name, typ name) {<br />

Statements;<br />

return wert;<br />

}<br />

Mit return; bzw. return wert; innerhalb der Statements kann man die Methode<br />

vorzeitig verlassen (beenden).<br />

Nachdem ein Objekt der Klasse angelegt wurde, konnen seine Methoden in einer<br />

der folgenden Formen ausgefuhrt werden:<br />

x = object.name();<br />

object.name();<br />

x = object.name (a, b, c);<br />

object.name (a, b, c);<br />

Man spricht in diesem Fall vom Aufruf der Methode fur das Objekt oder vom Senden<br />

einer Message an das Objekt. Wenn private statt public angegeben wurde, kann<br />

die Methode von auen nicht direkt angesprochen werden (siehe Kapselung).<br />

Innerhalb der Klasse kann man die Methoden mit<br />

name (parmeterliste)<br />

oder<br />

this.name (parmeterliste)<br />

aufrufen.<br />

Lokale Variable, die nur innerhalb einer Methode deklariert sind, konnen von auen<br />

nicht angesprochen werden. Bei der Deklaration von lokalen Variablen darf daher<br />

(im Gegensatz zu Datenfeldern der Klasse) weder public noch private angegeben<br />

werden.<br />

Die Parameter werden grundsatzlich als Wert ("by value"), nicht als Name ("by<br />

reference") ubergeben. Primitive Datentypen, die innerhalb der aufgerufenen Methode<br />

verandert werden, behalten also in der aufrufenden Methode ihren alten Wert.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 40


Bei Objekten und Strings wird aber nur die Referenz als Wert ubergeben, nicht<br />

das Objekt selbst. Wenn das Objekt innerhalb der aufgerufenen Methode mit Hilfe<br />

dieser Referenz verandert wird, dann wirkt diese Anderung direkt auf das Objekt,<br />

also praktisch wie bei einer Ubergabe als Name.<br />

4.6 Uberladen (overload)<br />

Man kann auch mehrere Methoden denieren, die denselben Namen, aber verschiedene<br />

Parameterlisten haben. Dies wird als Uberladen (overloading) von Methoden<br />

auf Grund ihrer verschiedenen "Signatures" bezeichnet.<br />

Man sollte das aber nur dann tun, wenn diese Methoden ahnliche Aktionen<br />

ausfuhren, die sich nur durch den Typ oder die Anzahl der Parameter unterscheiden.<br />

So sind z.B. verschiedene Varianten der Methode println deniert, die je nach dem<br />

Typ des Parameters dessen Wert in einen lesbaren String umwandeln und dann<br />

diesen ausdrucken.<br />

4.7 statische Methoden (static)<br />

Wenn man vor dem Typ einer Methode das Wort static angibt, dann kann diese<br />

Methode aufgerufen werden, ohne da vorher ein Objekt der Klasse erzeugt werden<br />

mu. Der Aufruf erfolgt dann in der Form<br />

ClassName.name();<br />

Statische Methoden konnen freilich nicht auf (nicht-statische) Datenfelder oder<br />

nicht-statische Methoden der Klasse oder auf "this" zugreifen. Innerhalb von statischen<br />

Methoden konnen aber Objekte mit new angelegt und dann deren Datenfelder<br />

und Methoden angesprochen werden.<br />

Die beiden wichtigsten Anwendungsfalle fur statische Methoden sind<br />

die main-Methode, mit der die Ausfuhrung einer <strong>Java</strong>-Applikation beginnt,<br />

und<br />

mathematische Funktionen, die nicht mit Objekten sondern mit primitiven<br />

Datentypen arbeiten.<br />

Beispielskizze fur die Denition und Verwendung einer mathematischen Funktion:<br />

public class Classname {<br />

public static int diff (int a, int b) {<br />

int c;<br />

c = a - b;<br />

return c;<br />

}<br />

...<br />

}<br />

Der Aufruf erfolgt dann in der Form<br />

z = Classname.diff (x, y);<br />

Beispiele fur statische Variable und statische Methoden sind System.out, System.exit(0),<br />

Label.CENTER, Math.sin(x) usw.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 41


4.8 main-Methode<br />

Jede <strong>Java</strong>-Applikation mu eine statische Methode mit der folgenden Signature enthalten:<br />

public static void main (String[] args)<br />

Diese main-Methode wird beim Starten der Applikation mit dem Befehl java aufgerufen<br />

und kann ein oder mehrere Objekte der Klasse oder auch von anderen Klassen<br />

anlegen und verwenden. Der Parameter args enthalt die beim Aufruf eventuell angegebenen<br />

Parameter, mit args.length erhalt man deren Anzahl.<br />

4.9 Konstruktoren (constructor)<br />

Konstruktoren dienen zum Anlegen von Objekten der Klasse mit den new-Operator.<br />

Sie legen den fur das Objekt benotigten Speicherplatz an und initialisieren das<br />

Objekt, d.h. sie setzen es in einen gultigen Anfangszustand.<br />

Laut Tov Are Jacobsen erfullt der Konstruktor die Funktion eines Baumeisters, der<br />

ein Objekt mit den im Plan festgelegten Eigenschaften errichtet:<br />

When you write a class you describe the behaviour of potential objects.<br />

Much like designing a house on paper: you can't live in it unless you<br />

construct it rst.<br />

And to do that you say "I wantanew house, so I'll call the constructor":<br />

House myNewHome;<br />

myNewHome = new House();<br />

(Tov Are Jacobsen, comp.lang.java.help, 1998)<br />

Im einfachsten Fall enthalt die Denition der Klasse keine explizite Denition von<br />

Konstruktoren. Dann wird vom <strong>Java</strong>-Compiler ein Default-Konstruktor mit leerer<br />

Parameterliste erzeugt, der in der Form<br />

ClassName object = new ClassName();<br />

aufgerufen werden kann und nur den Speicherplatz anlegt und alle Datenfelder auf<br />

ihre Anfangswerte setzt.<br />

Wenn man will, da im Konstruktor weitere Aktionen erfolgen sollen (z.B. durch<br />

Aufruf von Methoden), so mu man den Konstruktor selbst denieren. Dies erfolgt<br />

in der Form<br />

public ClassName() {<br />

Statements;<br />

}<br />

Man kann auch einen oder mehrere Konstruktoren mit verschiedenen Parameterlisten<br />

denieren (Overloading). In diesem Fall wird vom Compiler kein Default-<br />

Konstruktor automatisch erzeugt: Entweder man deniert gar keinen Konstruktor<br />

oder man deniert alle explizit. Beispiel:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 42


public class BookShelf {<br />

public Book[] book;<br />

public BookShelf (int maxBooks) {<br />

book = new Book[maxBooks];<br />

for (int i=0; i


4.10 Kapselung (Encapsulation, Data Hiding, <strong>Java</strong> Beans)<br />

Statt der Angabe von public in den obigen Beispielen sind bei Klassen, Datenfeldern<br />

und Methoden jeweils vier verschiedene Angaben moglich:<br />

public<br />

das Element kann uberall angesprochen werden (oentlich).<br />

protected<br />

das Element kann nur in Klassen innerhalb desselben Package oder in Subklassen<br />

(siehe Vererbung) angesprochen werden, aber nicht von fremden Klassen<br />

(geschutzt).<br />

(keine Angabe)<br />

das Element kann nur in Klassen innerhalb desselben Package angesprochen<br />

werden, aber nicht von fremden Klassen (default).<br />

private<br />

das Element kann nur innerhalb dieser Klasse angesprochen werden (privat).<br />

public protected default private<br />

selbe Klasse ja ja ja ja<br />

selbes Package ja ja ja nein<br />

Unterklasse (extends) ja ja nein nein<br />

uberall ja nein nein nein<br />

Es wird dringend empfohlen, bei jeder Klasse genau zu uberlegen, welche Datenfelder<br />

und Methoden "von auen" direkt angesprochen werden mussen und welche nur<br />

innerhalb der Klasse oder des Package benotigt werden. Alles, was nicht fur die<br />

Verwendung von auen sondern nur fur die Programmierung im Inneren notwendig<br />

ist, sollte im Inneren "verborgen" werden. Dies wird als Encapsulation oder Data<br />

Hiding bezeichnet und hat vor allem die folgenden Vorteile:<br />

einfache und klare Schnittstelle fur die Verwendung dieser Klasse bzw. ihrer<br />

Objekte,<br />

Sicherung, da die Datenfelder stets gultige Werte haben,<br />

weitgehende Unabhangigkeit der internen Programmierung dieser Klasse von<br />

der Programmierung anderer Klassen,<br />

weitgehende Vermeidung von Programmierfehlern beim Zusammenspiel zwischen<br />

den verschiedenen Klassen und Programmen.<br />

Um ungultige Datenwerte in den Datenfeldern zu vermeiden, ist es empfehlenswert,<br />

alle Datenfelder als private oder protected zu denieren und eigene public Methoden<br />

fur das Setzen und Abfragen der Werte vorzusehen, die schon bei der Speicherung<br />

der Daten alle Fehler verhindern.<br />

Per Konvention ("<strong>Java</strong>-Beans") sollen diese Methoden Namen der Form setXxxx<br />

und getXxxx haben und nach folgendem Schema deniert werden:<br />

public class ClassName {<br />

private typ xxxx = anfangswert;<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 44


}<br />

public void setXxxx (typ xxxx) {<br />

// Gueltigkeit des Wertes kontrollieren<br />

this.xxxx = xxxx;<br />

}<br />

public typ getXxxx() {<br />

return xxxx;<br />

}<br />

Bei boolean Datenfeldern soll die Methode isXxxxx statt getXxxxx genannt werden.<br />

Bei Arrays (Feldern) sollen solche Methoden sowohl fur das ganze Feld als auch (mit<br />

einem int-Parameter fur den Index) fur die einzelnen Feldelemente vorhanden sein.<br />

Mehr uber die Programmierung der Fehlerbehandlung nden Sie im Kapitel uber<br />

Exceptions.<br />

4.11 Beispiel: schlechte Datums-Klasse<br />

Eine sehr ungunstige Moglichkeit, eine Klasse fur Datum-Objekte zu denieren,<br />

bestunde darin, einfach nur die 3 int-Felder als public zu denieren und dann alles<br />

Weitere den Anwendungsprogrammierern zu uberlassen:<br />

public class Date1 { // very bad, don't do this!<br />

public int year;<br />

public int month;<br />

public int day;<br />

In der main-Methode konnen dann Objekte dieser Klasse angelegt und verwendet<br />

werden. Dabei kann es passieren, da ungultige Werte erzeugt werden (frei nach<br />

Erich Kastner):<br />

public static void main (String[] args) {<br />

Date1 today = new Date1();<br />

today.day = 35;<br />

today.month = 5;<br />

today.year = 1997;<br />

Auerdem konnen verschiedene Programmierer verschiedene Ansichten daruber haben,<br />

in welcher Reihenfolge Tag und Monat angezeigt werden sollen, und damit die<br />

Benutzer verwirren:<br />

System.out.println ("Today is " +<br />

today.day + ". " +<br />

today.month + ". " +<br />

today.year);<br />

System.out.println ("Today is " +<br />

today.month + ". " +<br />

today.day + ". " +<br />

today.year);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 45


Auch bei der Berechnung von Zeitraumen konnen manche Details ubersehen werden,<br />

z.B. da 1996 ein Schaltjahr war, 2021 aber keines ist:<br />

Date1 marriage = new Date1();<br />

marriage.day = 29;<br />

marriage.month = 2;<br />

marriage.year = 1996;<br />

System.out.println ("Married on " +<br />

marriage.day + ". " +<br />

marriage.month + ". " +<br />

marriage.year);<br />

Date1 silverMarriage = new Date1();<br />

silverMarriage.day = marriage.day;<br />

silverMarriage.month = marriage.month;<br />

silverMarriage.year = marriage.year + 25;<br />

System.out.println ("Silver marriage on " +<br />

silverMarriage.day + ". " +<br />

silverMarriage.month + ". " +<br />

silverMarriage.year);<br />

Schlielich gestaltet sich auch die Programmierung von Vergleichen recht aufwendig:<br />

if ( silverMarriage.day == today.day &&<br />

silverMarriage.month == today.month &&<br />

silverMarriage.year == today.year )<br />

System.out.println ("Congratulations!");<br />

}<br />

}<br />

4.12 Beispiel: bessere Datums-Klasse<br />

Besser im Sinne der Kapselung ware es, die 3 Datenfelder als private zu denieren,<br />

damit sie nicht auf falsche Werte gesetzt werden konnen, und public Methoden und<br />

Konstruktoren vorzusehen, mit denen diese Werte gesetzt, verandert und verwendet<br />

werden:<br />

public class Date2 { // better, but incomplete<br />

private int year;<br />

private int month;<br />

private int day;<br />

Hier drei Konstruktoren (overloading), mit denen das Datum auf einen gultigen<br />

Anfangswert gesetzt wird. Diese Konstruktoren verwenden die unten erlauterte Methode<br />

setDate2, die die Gultigkeit der Werte sicherstellt.<br />

public Date2() {<br />

setDate2();<br />

}<br />

}<br />

public Date2 (int year, int month, int day) {<br />

setDate2 (year, month, day);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 46


}<br />

public Date2 (Date2 other) {<br />

setDate2 (other);<br />

Hier nun die drei Varianten (overloading) der public Methode setDate2:<br />

Die Variante mit leerer Parameterliste setzt das Datum auf das heutige Datum<br />

(durch Aufruf einer geeigneten Systemfunktion, hier nur skizziert, aber nicht gezeigt):<br />

public void setDate2() {<br />

// set to today's date via system function<br />

}<br />

Die zweite Variante erlaubt die Angabe des Datums mit 3 Parametern fur Jahr,<br />

Monat und Tag und uberpruft, ob diese Zahlen tatsachlich ein gultiges Datum darstellen<br />

(mit Berucksichtigung von eventuellen Schaltjahren, hier nicht gezeigt). Was<br />

hier auch noch fehlt, ist die Reaktion auf solche Fehler (siehe das Kapitel uber<br />

Exceptions).<br />

public void setDate2 (int year, int month, int day) {<br />

// check for valid ranges of day and month for this year<br />

this.day = day;<br />

this.month = month;<br />

this.year = year;<br />

}<br />

Die dritte Variante setzt das Datum auf das gleiche wie ein bereits erstelltes Objekt<br />

desselben Typs. Hier ist keine neuerliche Fehlerbehandlung notwendig, da dieses<br />

Objekt ohnedies nur ein gultiges Datum enthalten kann.<br />

public void setDate2 (Date2 other) {<br />

this.day = other.day;<br />

this.month = other.month;<br />

this.year = other.year;<br />

}<br />

Fur den Zugri auf die privaten Datenfelder werden eigene public get-Methoden<br />

geschrieben:<br />

public int getDay() {<br />

return day;<br />

}<br />

public int getMonth() {<br />

return month;<br />

}<br />

public int getYear() {<br />

return year;<br />

}<br />

Anmerkung: Bei der in <strong>Java</strong> 1.0 eingebauten Date-Klasse gibt es zwei getrennte Methoden<br />

getDate und getDay fur den Tag innerhalb des Monats und den Wochentag.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 47


Auerdem kann man auch weitere Methoden vorsehen, z.B. um den Monat als Wort<br />

statt als Nummer zu erhalten. Hier die englische Variante, bei der deutschsprachigen<br />

mute man auch noch den Unterschied zwischen "Januar" in Deutschland und<br />

"Janner" in Osterreich berucksichtigen:<br />

public String getMonthName() {<br />

String s = null;<br />

switch (month) {<br />

case 1: s = "January"; break;<br />

case 2: s = "February"; break;<br />

case 3: s = "March"; break;<br />

case 4: s = "April"; break;<br />

case 5: s = "May"; break;<br />

case 6: s = "June"; break;<br />

case 7: s = "July"; break;<br />

case 8: s = "August"; break;<br />

case 9: s = "September"; break;<br />

case 10: s = "October"; break;<br />

case 11: s = "November"; break;<br />

case 12: s = "December"; break;<br />

}<br />

return s;<br />

}<br />

Hier noch 3 Methoden zur Berechnung von Zeitintervallen in die Zukunft oder (bei<br />

negativem Argument) in die Vergangenheit, wobei die komplizierten Details von<br />

Monats- und Jahresgrenzen und Schaltjahren hier nicht gezeigt werden. Gerade weil<br />

diese Berechnung kompliziert ist, ist es wichtig, sie innerhalb der Klasse zu programmieren<br />

und es nicht jedem einzelnen Anwender zu uberlassen, sich das jedesmal neu<br />

zu uberlegen.<br />

public void addDays (int days) {<br />

// compute new date with correct day, month, and year<br />

}<br />

public void addMonths (int months) {<br />

// compute new date with correct day, month, and year<br />

}<br />

public void addYears (int years) {<br />

this.year += years;<br />

// correct day and month, if leap year problem<br />

}<br />

Alle Klassen mussen die beiden Methoden equals (fur die Abfrage auf Gleichheit<br />

von 2 Objekten dieses Typs) und toString (fur die menschenlesbare Darstellung des<br />

Objekts als Textstring) enthalten:<br />

public boolean equals (Object other) {<br />

if (other instanceof Date2 &&<br />

( (Date2) other).day == this.day &&<br />

( (Date2) other).month == this.month &&<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 48


}<br />

( (Date2) other).year == this.year)<br />

return true;<br />

else<br />

return false;<br />

public String toString() {<br />

String s = day + " " +<br />

getMonthName() + " " +<br />

year;<br />

return s;<br />

}<br />

Anmerkung: Die Angabe von this. ist hier nicht notwendig, macht aber die Bedeutung<br />

in diesem Beispiel klarer verstandlich.<br />

Die Verwendung dieser Klasse ist nun sehr viel einfacher, und gleichzeitig sind alle<br />

Fehlermoglichkeiten und Miverstandnisse ausgeschlossen:<br />

public static void main (String[] args) {<br />

Date2 today = new Date2();<br />

System.out.println ("Today is " + today );<br />

Anmerkung: Die Angabe von today.toString() ist innerhalb der println-Methode<br />

bzw. der String-Concatenation nicht notig, die wird bei der Typ-Umwandlung automatisch<br />

aufgerufen.<br />

Date2 yesterday = new Date2 (today);<br />

yesterday.addDays(-1);<br />

System.out.println ("Yesterday was " + yesterday );<br />

Date2 marriage = new Date2 (1996, 2, 29);<br />

System.out.println ("Married on " + marriage );<br />

Date2 silverMarriage = new Date2 (marriage);<br />

silverMarriage.addYears(25);<br />

System.out.println ("Silver marriage on " +<br />

silverMarriage );<br />

if ( silverMarriage.equals(today) )<br />

System.out.println ("Congratulations!");<br />

}<br />

}<br />

In Wirklichkeit ist es naturlich nicht notwendig, eine eigene Klasse fur Datumsangaben<br />

zu schreiben, die ist bereits im API vorhanden und ist noch um einige<br />

Stufen komplexer als das hier gezeigte Beispiel: Die Klasse Date enthalt nicht nur<br />

das Datum sondern auch die Uhrzeit, und man kann in Verbindung mit entsprechenden<br />

weiteren Klassen auch die verschiedenen Kalender, Zeitzonen, Datumsformate<br />

und Sprachen berucksichtigen (siehe das Kapitel uber Datum und Uhrzeit).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 49


4.13 Ubung: einfache Kurs-Klasse<br />

Schreiben Sie eine einfache Klasse "Kurs" mit den folgenden Datenfeldern:<br />

Kurs-Titel (String)<br />

kostenlos (boolean)<br />

Namen der Teilnehmer (Array von Strings)<br />

Anzahl der angemeldeten Teilnehmer<br />

und mit allen benotigten set- und get-Methoden, nach den Konventionen fur Beans,<br />

sowie einer Methode addTeilnehmer zum Anmelden eines Teilnehmers.<br />

Fugen Sie eine main-Methode an, in der Sie diese Methoden kurz testen, indem Sie<br />

zwei oder drei Kurs-Objekte anlegen, ein paar Teilnehmer anmelden und dann die<br />

gespeicherten Informationen auf den Bildschirm ausgeben.<br />

4.14 Objekt-orientierte Analyse und Design<br />

Die objekt-orientierte Programmierung besteht aus folgenden Schritten:<br />

Objekt-orientierte Analyse (OOA)<br />

Objekt-orientiertes Design (OOD)<br />

Objekt-orientierte Programmierung (OOP)<br />

Die Analyse erfolgt zunachst unabhangig von der verwendeten Programmiersprache<br />

und soll die logisch richtige Sicht des Problems und damit die Grundlage fur das<br />

Design liefern.<br />

Das Design, also das Konzept fur die Programmierung, berucksichtigt dann die<br />

Eigenschaften der Programmiersprache (z.B. Einfach- oder Mehrfachvererbung)<br />

und die verfugbaren Klassenbibliotheken (z.B. Schnittstellen zu Graphischen User-<br />

Interfaces oder zu Datenbanken).<br />

Um komplexe Systeme fur die objekt-orientierte Programmierung in den Gri zu<br />

bekommen, mussen sie also analysiert werden, aus welchen Objekten sie bestehen<br />

und welche Beziehungen zwischen den Objekten bestehen, welche Eigenschaften die<br />

Objekte haben und welche Aktionen mit ihnen ablaufen.<br />

Die wichtigsten Design-Regeln fur das Zerlegen von komplexen Systemen in einzelne<br />

Objekte sind:<br />

Die Objekte sollen moglichst einfach sein, d.h. ein kompliziertes Objekt soll<br />

in mehrere einfache Objekte zerlegt werden.<br />

Die Objekte sollen moglichst abgeschlossen sein, d.h. jedes Objekte soll<br />

moglichst wenig uber die anderen Objekte wissen mussen.<br />

Die Analyse und das Design ergeben sich am einfachsten, indem man versucht, das<br />

System bzw. die Aufgabenstellung mit einfachen deutschen Satzen zu beschreiben:<br />

Hauptworter (Nomen) bedeuten Objekte oder primitive Datenfelder.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 50


Eigenschaftsworter (Adjektiv) bedeuten Datenfelder oder get-Methoden.<br />

Zeitworter (Verb) bedeuten Methoden.<br />

Satze der Form "A hat ein B" bedeuten Datenfelder (Eigenschaften).<br />

Satze der Form "A ist ein B" bedeuten Oberklassen (Vererbung).<br />

4.15 Beispiel: Analyse Schulungen<br />

Aufgabenstellung: Analyse und Design des Systems "Schulungsunternehmen, Schulungen,<br />

Teilnehmer und Trainer".<br />

Losungs-Skizze:<br />

1. Objekte und Aktionen:<br />

Ein Schulungsunternehmen bietet Schulungen an.<br />

Eine Schulung ndet an Schulungsterminen statt.<br />

Ein Schulungsunternehmen veroentlicht eine Liste der Schulungstermine.<br />

Ein Teilnehmer meldet sich zu einem Schulungstermin an und bezahlt die<br />

Schulungsgebuhr.<br />

Ein Trainer halt einen Schulungstermin ab und bekommt dafur ein Honorar.<br />

2. Eigenschaften der Objekte:<br />

Eine Schulung hat Titel, Inhalt, Lange, Preis.<br />

Ein Schulungstermin hat Schulung, Termin, Ort, Trainer, maximale Teilnehmerzahl,<br />

tatsachliche Teilnehmerzahl, angemeldete Teilnehmer.<br />

Ein Teilnehmer ist eine Person.<br />

Eine Person hat Name, Adresse, Telefon, Konto ...<br />

Ein Trainer ist eine Person und hat einen Tagessatz.<br />

Ein Schulungsunternehmen ist wie eine Person und hat Schulungen und<br />

Schulungstermine.<br />

4.16 Ubung: Analyse Bucherregal<br />

Uberlegen Sie, aus welchen Objekten das System "Bucherregal mit Buchern" besteht<br />

und welche Datenfelder und Methoden die Klasse Bucherregal enthalten mu.<br />

Es geht dabei nur um die Analyse und das Design des Systems, nicht um die konkrete<br />

Programmierung. Schreiben Sie das Ergebnis daher bitte nur in der Form von<br />

Stichworten oder graphischen Skizzen auf einem Blatt Papier auf, nicht als <strong>Java</strong>-<br />

Programm.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 51


4.17 Vererbung (Inheritance, Polymorphismus, override)<br />

Eine der wichtigsten Eigenschaften von objekt-orientierten Systemen stellt die sogenannte<br />

"Vererbung" von Oberklassen (Superklassen) auf Unterklassen (Subklassen)<br />

dar. Dies stellt eine wesentliche Vereinfachung der Programmierung dar und ist immer<br />

dann moglich, wenn eine Beziehung der Form "A ist ein B" besteht.<br />

Beispiele: Ein Auto ist ein Fahrzeug (hier ist Fahrzeug der Oberbegri, also die<br />

Superklasse, und Auto ist die spezielle Subklasse). Ein Bilderbuch ist ein Buch. Ein<br />

Mitarbeiter ist eine Person...<br />

Keine Vererbung ist in den folgenden Fallen gegeben: Ein Bucherregal enthalt<br />

Bucher. Ein Bilderbuch enthalt Bilder. Ein Mitarbeiter liest ein Buch.<br />

Der Vorteil der Vererbung besteht darin, da man dieselben Konzepte nicht mehrfach<br />

programmieren mu, sondern auf einfache Grundbegrie zuruckfuhren und wiederverwenden<br />

kann.<br />

Dazu wird zunachst die Oberklasse, die den allgemeinen Grundbegri moglichst<br />

einfach beschreibt, mit den fur alle Falle gemeinsam geltenden Datenfeldern und<br />

Methoden deniert.<br />

Dann gibt man bei der Denition der Unterklasse mit extends an, da es sich um<br />

einen Spezialfall der Oberklasse handelt, und braucht jetzt nur die Datenfelder und<br />

Methoden zu denieren, die zusatzlich zu denen der Oberklasse notwendig sind. Alle<br />

anderen Denitionen werden automatisch von der Oberklasse ubernommen.<br />

Beispiel:<br />

public class Person {<br />

public String name;<br />

public Date geburtsDatum;<br />

...<br />

}<br />

public class Beamter extends Person {<br />

public int dienstKlasse;<br />

public Date eintrittsDatum;<br />

...<br />

}<br />

Dann enthalten Objekte vom Typ Person die beiden Felder name und geburts-<br />

Datum, und Objekte vom Typ Beamter enthalten die vier Felder name, geburts-<br />

Datum, dienstKlasse und eintrittsDatum. Das analoge gilt fur die hier nicht gezeigten<br />

Methoden.<br />

Man kann auch Methoden, die bereits in der Oberklasse deniert sind, in der Unterklasse<br />

neu denieren und damit die alte Bedeutung fur Objekte des neuen Typs<br />

uberschreiben (override). Dabei braucht man eventuell nur die Teile neu zu schreiben,<br />

die zur entsprechenden Methode der Oberklasse hinzukommen, und kann fur<br />

den gleichbleibenden Teil die Methode der Oberklasse mit super.name() aufrufen.<br />

Wenn eine Methode in der Oberklasse als final deklariert ist, kann sie von Unterklassen<br />

nicht uberschrieben werden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 52


Konstruktoren werden nicht automatisch von der Oberklasse ubernommen sondern<br />

mussen neu deniert werden, wenn man mehr als den Default-Konstruktor mit der<br />

leeren Parameterliste braucht. Allerdings braucht man in diesen Konstruktoren nur<br />

diejenigen Aktionen zu denieren, die gegenuber der Oberklasse neu sind, und kann<br />

vorher - als erstes Statement - mit super(); oder super(parameterliste); den<br />

Konstruktor der Oberklasse aufrufen. Wenn man das nicht tut, wird vom Compiler<br />

automatisch der Default-Konstruktor super(); an den Anfang hinzugefugt.<br />

Referenzen auf ein Objekt der Unterklasse konnen sowohl in Variablen vom Typ<br />

der Unterklasse als auch vom Typ der Oberklasse abgespeichert werden. Das gilt<br />

auch bei der Verwendung in Parameterlisten. Erlaubt sind also z.B. die folgenden<br />

Zuweisungen:<br />

Person mutter;<br />

Person vater;<br />

mutter = new Person();<br />

vater = new Beamter();<br />

Allerdings konnen in diesem Fall auch fur das Objekt vater nur die Datenfelder<br />

und Methoden aufgerufen werden, die fur Personen deniert sind, andernfalls erhalt<br />

man einen Compiler-Fehler. Man kann aber mit instanceof abfragen, um welchen<br />

Typ (Ober- oder Unterklasse) es sich zur Laufzeit handelt, und dann mit Casting<br />

die Typumwandlung durchfuhren. Beispiel:<br />

public void printName (Person p) {<br />

System.out.print(p.name);<br />

if (p instanceof Beamter) {<br />

System.out.print(", " + ((Beamter)p).dienstKlasse );<br />

}<br />

System.out.println();<br />

}<br />

Solche Konstruktionen sind aber nur sehr selten notwendig, denn nach den Prinzipien<br />

der objekt-orientierten Programmierung sollten die Oberklassen von den Unterklassen<br />

unabhangig sein und alles, was eine Unterklasse betrit, sollte nur in dieser<br />

Unterklasse programmiert werden, z.B. durch Uberschreiben der entsprechenden<br />

Methoden.<br />

4.18 Ubung: Person und Student<br />

Schreiben Sie 3 Klassen:<br />

1. eine einfache Klasse "Person" mit den Datenfeldern und Methoden vorname,<br />

zuname, getVorname, setVorname, getZuname, setZuname, und einer Methode<br />

toString, die einen String liefert, der den Vor- und Zunamen anzeigt.<br />

2. eine einfache Klasse "Student" mit den zusatzlichen Datenfeldern und Methoden<br />

uni, getUni, setUni, und einer entsprechend erweiterten Methode toString,<br />

die Vorname, Zuname und Universitat anzeigt.<br />

3. eine Klasse mit einer main-Methode, in der ein paar Objekte von Person und<br />

Student angelegt werden und deren Inhalt mit Hilfe der toString-Methode auf<br />

den Bildschirm ausgegeben wird.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 53


4.19 Mehrfache Vererbung, Interfaces, abstrakte Klassen<br />

Interfaces<br />

Abstrakte Klassen<br />

Unter mehrfacher Vererbung versteht man die Moglichkeit, da eine Klasse Unterklasse<br />

von zwei verschiedenen Oberklassen ist, also z.B. ein Dreirad ist ein Fahrzeug<br />

und ein Kinderspielzeug.<br />

<strong>Java</strong> unterstutzt keine mehrfache Vererbung, in extends kann nur eine Oberklasse<br />

angegeben werden. Eine mehrfache Angabe ist aber bei Interfaces moglich.<br />

Interfaces sind etwas ahnliches wie Klassen, die aber nur das Konzept fur die Unterklassen<br />

skizzieren, das dann von diesen "implementiert" werden mu. Interfaces<br />

enthalten keine Datenfelder und nur die "Signaturen" von Methoden, statt der De-<br />

nition des Methoden-Inhalts zwischen f und g enthalten sie nur einen Strichpunkt.<br />

Die Denition eines Interface folgt dem folgenden Schema:<br />

public interface InterfaceName {<br />

public typ name1 (parameterliste) ;<br />

public void name2 (parameterliste) ;<br />

}<br />

Die Subklasse, die dieses Interface implementiert, mu dann alle darin skizzierten<br />

Methoden enthalten, mit genau derselben Signature (Typ, Name und Parameterliste)<br />

und einem konkreten Block von Statements oder zumindest einem leeren Block.<br />

Beispiel:<br />

public class ClassName implements InterfaceName {<br />

...<br />

public typ name1 (parameterliste) {<br />

Statements;<br />

}<br />

public void name2 (parameterliste) {<br />

}<br />

}<br />

Nach dem Wort implements konnen auch mehrere Interfaces angefuhrt werden<br />

(durch Komma getrennt), dann mu die Klasse alle in diesen Interfaces denierten<br />

Methoden implementieren. Zusatzlich kann auch noch mit extends eine Oberklasse<br />

angegeben werden. Beispiel:<br />

public class SubClass extends SuperClass<br />

implements Interface1, Interface2<br />

Abstrakte Klassen (abstract class) stellen eine Mischung aus Superklassen und Interfaces<br />

dar: ein Teil der Methoden ist in der abstrakten Klasse konkret deniert wie<br />

bei Superklassen, und von einem anderen Teil ist nur die Signature der Methoden<br />

skizziert, wie bei Interfaces. Die Denition beginnt mit<br />

public abstract class SuperClassName<br />

und die Vererbung in der Subklasse wie gewohnt mit<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 54


public class SubClassName extends SuperClassName<br />

Die Subklasse mu dann konkrete Implementierungen von allen in der Superklasse<br />

nur skizzierten Methoden enthalten und kann die dort konkret denierten Methoden<br />

entweder ubernehmen (Vererbung) oder uberschreiben (override).<br />

4.20 Beispiel: Katzenmusik<br />

Eine kleine Ubungsaufgabe zum Vestandnis fur die Anwendung von Interfaces.<br />

Das folgende einfache Programm soll funktionieren:<br />

public class Katzenmusik {<br />

public static void main (String[] args) {<br />

LautesTier tier1 = new Katze();<br />

LautesTier tier2 = new Hund();<br />

for (int i=1; i


4.21 Innere Klassen (inner class)<br />

Ab JDK 1.1. kann man Klassen auch innerhalb von anderen Klassen denieren,<br />

sie konnen dann nur innerhalb dieser Klasse verwendet werden, haben aber (im<br />

Gegensatz zu separat denierten Klassen) Zugri auf alle in der aueren Klasse<br />

denierten Datenfelder und Methoden.<br />

4.22 Zugri auf Objekte von anderen Klassen<br />

Wie kann man ein Objekt, das in einer Klasse angelegt wurde, auch in einer anderen<br />

Klasse ansprechen?<br />

Dazu mu man die Referenz auf das Objekt vom Objekt der einen Klasse an das<br />

Objekt der anderen Klasse ubergeben, entweder mit Hilfe einer Methode oder mit<br />

Hilfe eines Konstruktors.<br />

Ubergabe von A an B mit einer Methode:<br />

public class A {<br />

...<br />

B b = new B();<br />

b.setA(this); // tell b "I am your A"<br />

...<br />

}<br />

public class B {<br />

private A a = null; // reference to object of class A<br />

public void setA (A a) {<br />

this.a=a;<br />

}<br />

...<br />

a.xxx(); // method of object of class A<br />

...<br />

}<br />

Ubergabe von A an B mit einem Konstruktor:<br />

public class A {<br />

...<br />

B b = new B(this); // tell b "I am your A"<br />

...<br />

}<br />

public class B {<br />

private A a = null; // reference to object of class A<br />

public B() {<br />

this(null);<br />

}<br />

public B (A a) {<br />

this.a=a;<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 56


}<br />

...<br />

a.xxx(); // method of object of class A<br />

...<br />

4.23 Packages und import<br />

Unter einem Package versteht man eine Menge von zusammengehorenden Klassen,<br />

ahnlich wie bei einer Programmbibliothek. Package ist im wesentlichen identisch mit<br />

Directory: Alle Klassen, die im selben Directory liegen, gehoren zu diesem Package.<br />

In <strong>Java</strong> werden Packages einheitlich und plattformunabhangig mit Punkten zwischen<br />

den Directory-Namen geschrieben, egal, ob auf der jeweiligen Plattform<br />

Schragstriche / oder Backslashes n oder sonst etwas als File-Separator verwendet<br />

wird.<br />

Wenn man in einer <strong>Java</strong>-Klasse andere Klassen oder Interfaces ansprechen will, mu<br />

man diese im allgemeinen "importieren". Dazu gibt man am Beginn des Source-Files<br />

mit import den Namen der Klasse (meist mit ihrem Package-Namen) an, oder man<br />

importiert gleich alle Klassen eines Package, indem man einen Stern * angibt:<br />

import aaa.bbb.Xxxx ;<br />

import aaa.bbb.* ;<br />

Im ersten Fall wird die Klasse Xxxx aus dem Package aaa.bbb verfugbar gemacht,<br />

im zweiten Fall alle Klassen aus dem Package aaa.bbb. Bitte, vergessen Sie nicht<br />

den Strichpunkt, der das import-Statement beenden mu.<br />

Die Angabe der Packages (Directories) erfolgt immer relativ zu den Directories, die<br />

in der Environment-Variablen CLASSPATH angefuhrt sind.<br />

Wenn der Punkt . fur das jeweilige Directory in CLASSPATH enthalten ist, dann<br />

braucht man fur Klassen, die im selben Directory liegen, kein import-Statement<br />

anzugeben, sondern alle Klassen, die im selben Directory liegen, stehen automatisch<br />

zur Verfugung.<br />

Das zur Grundausstattung von <strong>Java</strong> gehorende Package java.lang und das "eigene"<br />

Package (eigenes Directory oder package-Angabe) werden vom Compiler automatisch<br />

gefunden und mussen nicht explizit importiert werden, wohl aber alle anderen<br />

wie z.B. java.util, java.text, java.awt, java.awt.event etc.<br />

Selbstverstandlich kann man Klassen und deren Datenfelder und Methoden nur dann<br />

ansprechen, wenn man die Erlaubnis dazu hat (siehe Kapselung).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 57


5. Fehlerbehandlung (Exceptions)<br />

normaler Programmablauf<br />

Ausnahmen (Fehlersituationen, Exceptions)<br />

<strong>Java</strong> bietet eine sehr bequeme Moglichkeit, etwaige Fehlersituationen zu erkennen<br />

und dann entsprechend zu reagieren, ohne gleich das ganze Programm abzubrechen.<br />

Dabei werden die Fehler von einer aufgerufenen Methode erkannt und "geworfen"<br />

(throw) und mussen dann von der aufrufenden Methode "aufgefangen" oder "abgefangen"<br />

(catch) werden.<br />

Es gibt mehrere Arten von Fehlerbedingungen, die entweder abgefangen werden<br />

mussen oder abgefangen werden konnen:<br />

Exception und RuntimeException fur Benutzungsfehler,<br />

Error fur Softwarefehler,<br />

Throwable als Oberbegri fur Exception und Error.<br />

Im folgenden werden Exceptions beschrieben, die abgefangen werden mussen.<br />

5.1 Fehler erkennen (throw, throws)<br />

Wenn eine aufgerufene Methode eine Fehlersituation erkennt, dann generiert sie ein<br />

Objekt, das den aufgetretenen Fehler beschreibt (exception) und "wirft" diese Exception<br />

mit throw. Dies passiert meist innerhalb eines if-Blockes irgendwo innerhalb<br />

der Methode.<br />

Damit sofort klar ist, welche Fehlersituationen in einer Methode auftreten konnen<br />

und daher von den aufrufenden Methoden abgefangen werden mussen, mu man<br />

schon bei der Deklaration der Methode mit throws angeben, welche Exceptions in<br />

ihr eventuell geworfen werden (eventuell mehrere, durch Komma getrennt). Falls<br />

man dies vergit, wird man vom Compiler mit einer Fehlermeldung daran erinnert,<br />

welche Exceptions man in throws angeben mu.<br />

Beispiel:<br />

public void xxxMethod (parameterliste)<br />

throws XxxxException {<br />

...<br />

if (...)<br />

throw new XxxxException();<br />

...<br />

}<br />

Man kann<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 58


entweder eine der vordenierten Exceptions verwenden (wie z.B. ArrayIndex-<br />

OutOfBoundsException, IOException, IllegalArgumentException oder No-<br />

SuchElementException, siehe die Klassen-Hierarchie der Klasse Exception)<br />

oder eine eigene Exception denieren, die diese spezielle Fehlersituation beschreibt.<br />

Mit<br />

public class XxxxException extends YyyyException { }<br />

deniert man eine neue Exception, die den neuen Namen XxxxException und die<br />

gleichen Datenfelder und Methoden wie die bereits denierte Exception YyyyException<br />

hat. Diese Oberklasse sollte moglichst passend gewahlt werden, damit die<br />

neue Exception richtig in die Hierarchie der Ober- und Unterklassen eingeordnet<br />

wird. Beispiele:<br />

public class SalaryTooLowException<br />

extends IllegalArgumentException { }<br />

public class StudentNotFoundException<br />

extends NoSuchElementException { }<br />

public class LVANumberFormatException<br />

extends DataFormatException { }<br />

5.2 Fehler abfangen (try, catch)<br />

Die aufrufende Methode hat nun zwei Moglichkeiten:<br />

Entweder sie "wirft" die Fehlersituation weiter an die Methode, von der sie<br />

aufgerufen wird, indem Sie die Exceptions mit throws anfuhrt,<br />

oder sie fangt den Fehler ab und reagiert selbst. Zu diesem Zweck mussen alle<br />

Statements, die eine Fehlersituation bewirken konnen, in einem try-Block stehen,<br />

und anschlieend mit einem oder mehreren catch-Blocken die moglichen<br />

Fehler abgefangen werden.<br />

Beispiel:<br />

try {<br />

Statements;<br />

xxxObject.xxxMethod();<br />

Statements;<br />

} catch (XxxxException e) {<br />

System.out.println("*** error: " + e);<br />

}<br />

Der try-Block kann ein oder mehrere Statements enthalten, und es konnen auch<br />

mehrere catch-Blocke fur verschiedene Fehlersituationen angegeben werden.<br />

Wann immer eines der Statements irgendeinen Fehler "wirft", werden die restlichen<br />

Statements des try-Blocks nicht ausgefuhrt und es wird der (erste) catch-Block<br />

ausgefuhrt, der den aufgetretenen Fehler auangt. Dann wird die Verarbeitung mit<br />

den Statements nach dem letzten catch-Block fortgesetzt oder der Fehler, falls er<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 59


nicht abgefangen wurde, an die aufrufende Methode weitergeworfen. (Falls man<br />

einen nally-Block angibt, wird dieser jedenfalls auch noch ausgefuhrt.)<br />

Wenn man mehrere catch-Blocke angibt, ist die Reihenfolge wichtig, man mu zuerst<br />

die spezielleren Exceptions (Unterklassen) und dann die allgemeineren Exceptions<br />

(Oberklassen) angeben.<br />

Im Catch-Block kann man die folgenden Methoden der Exception verwenden:<br />

String toString()<br />

fur eine kurze Angabe, welcher Fehler aufgetreten ist<br />

String getMessage()<br />

fur einen erklarenden Text<br />

printStackTrace()<br />

printStackTrace(filename)<br />

fur das Ausdrucken der Information, welcher Fehler wo in welchem Programm<br />

aufgetreten ist.<br />

Was man im Catch-Block ausfuhrt, hangt von der jeweiligen Anwendung ab. Meistens<br />

wird man<br />

eine Fehlermeldung an den Benutzer ausgeben<br />

und dann<br />

entweder den Fehler selbstandig korrigieren und die Verarbeitung mit dem<br />

korrigierten Datenwert fortsetzen<br />

oder die Verarbeitung abbrechen.<br />

Wenn man vergit, da eine bestimmte Anweisung "gefahrlich" ist und eine Fehlersituation<br />

bewirken kann, dann sagt einem der Compiler meistens mit einer Fehlermeldung,<br />

da man sie in einen try-Block einbauen soll, und gibt auch gleich an,<br />

welche Exception man im catch-Block abfangen soll. Man mu dann entweder diesen<br />

catch-Block anfugen oder - wenn man sich mit den Details nicht beschaftigen will -<br />

die folgende Oberklasse fur alle moglichen Fehler:<br />

catch (Exception e) {<br />

System.out.println(e);<br />

}<br />

oder eventuell sogar<br />

catch (Throwable e) { }<br />

5.3 Mathematische Fehler<br />

Division durch Null und andere "verbotene" mathematische Berechnungen bewirken<br />

nur bei ganzzahligen Typen wie int, long etc. eine entsprechende Exception.<br />

Bei oat- und double-Zahlen bewirken Division durch Null, Logarithmus einer negativen<br />

Zahl und ahnliche "falsche" Operationen hingegen keine Exception sondern<br />

liefern als Ergebnis die speziellen Werte "unendlich" (innite) bzw. "unbestimmt"<br />

(keine Zahl, not a number). Fur die Abfrage dieser Werte und Bedingungen gibt es<br />

eigene Konstanten und Methoden in den Klassen Float und Double.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 60


5.4 Ubung: erweitertes Rechenbeispiel Sparbuch<br />

Schreiben Sie eine Applikation, die wie beim einfachen Sparbuch-Beispiel im Kapitel<br />

Syntax und Statements die Wertentwicklung eines Geldbetrages uber 10 Jahre<br />

ausgibt, aber mit folgenden Erweiterungen:<br />

Geldbetrag und Zinssatz werden nicht in der main-Methode festgelegt sondern<br />

vom Benutzer beim Aufruf in der Parameterliste ubergeben.<br />

Die Zahlenausgabe soll mit der Klasse DecimalFormat in ein "schones" Format<br />

gebracht werden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 61


User-Interfaces<br />

Graphical User Interfaces (GUI)<br />

Applets<br />

Threads<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 62


6. Graphical User Interfaces (GUI)<br />

Fenster, Texte und Bilder, Tastatur und Maus<br />

Ablauf vom Benutzer gesteuert, nicht vom Programm<br />

Bei Programmen mit graphischen Benutzungsoberachen (GUI) kommt es auf das<br />

Zusammenspiel von 3 Bereichen an:<br />

Model = die Datenstruktur<br />

View = die graphische Darstellung (Mensch-Maschine-Interface, Renderer)<br />

Controller = die Verarbeitung der Daten (Ausfuhrung von Aktionen)<br />

In sehr einfachen Fallen konnen alle diese Aspekte innerhalb desselben Programms<br />

(derselben Klasse) behandelt werden.<br />

Fur komplexere Anwendungen wird aber empfohlen, diese 3 Bereiche getrennt zu<br />

programmieren und damit die Vorteile der objekt-orientierten Programmierung auszunutzen<br />

(siehe das Kapitel uber Objekte und Klassen). Professionelle Software-<br />

Hersteller setzen fur die Programmierung der drei Bereiche oft sogar verschiedene<br />

Personen ein, die jeweils Spezialisten fur ihren Bereich sind.<br />

6.1 Abstract Windowing Toolkit (AWT)<br />

Das Abstract Windowing Toolkit (AWT) ist ein Package, das Klassen fur die Zusammenstellung<br />

und Verwendung von graphischen Benutzungsoberachen (GUI)<br />

enthalt. Solche GUIs bestehen aus Fenstern, Menus, Eingabefeldern, Buttons und<br />

dergleichen, und die Steuerung durch den Benutzer erfolgt meistens mit Tastatur<br />

(Keyboard) und Maus oder mit ahnlichen Hardware-Komponenten wie z.B. Trackballs,<br />

Touchscreen oder Spracheingabe.<br />

Das Wort abstrakt (abstract) im Namen AWT deutet darauf hin, da in diesen<br />

Klassen nur die plattformunabhangigen wesentlichen Eigenschaften der Komponenten<br />

deniert sind und fur die konkrete Darstellung dann die am jeweiligen Rechner<br />

vorhandenen Systemkomponenten ("Peers") mit den auf diesem Rechner ublichen<br />

Layouts, Aussehen und Funktionalitaten ("look and feel") verwendet werden. Ein<br />

im <strong>Java</strong>-Programm mit AWT denierter Button wird also auf einem PC wie normale<br />

Windows-Buttons, auf einem Macintosh wie normale Apple-Buttons und unter Unix<br />

wie normale Motif- oder CDE-Buttons aussehen, und das gleiche gilt fur Fenster,<br />

Scrollbars, Menus etc.<br />

Dies hat fur den Benutzer den Vorteil, da er auf seinem Computersystem immer dieselben,<br />

gewohnten GUI-Komponenten vorndet, unabhangig von der Applikation.<br />

Es hat aber den Nachteil, da die gleiche Applikation auf verschiedenen Computersystemen<br />

dadurch in den Details verschieden aussieht und da im Fall von Applets<br />

keine genaue Anpassung der Groen, Farben, Schriftarten und Graphik-Elemente<br />

an die umgebende Web-Page moglich ist.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 63


Deshalb unterstutzen neuere <strong>Java</strong>-Versionen (Swing, JDK 1.2) zusatzlich zu den<br />

Peer-Komponenten auch sogenannte "leichte" (light weight) Komponenten, die komplett<br />

in <strong>Java</strong> geschrieben sind und bei denen die Layout-Details genauer deniert<br />

werden konnen. Damit kann man Applets und Applikationen so gestalten, da jede<br />

Anwendung plattformubergreifend ihr eigenes Look-and-Feel hat.<br />

Beide Methoden haben ihre Vor- und Nachteile.<br />

Die Swing-Komponenten sind Teil der sogenannten <strong>Java</strong> Foundation Classes (JFC).<br />

Sie konnen beim JDK 1.1 zusatzlich installiert werden und sind ab JDK 1.2 Teil des<br />

JDK. Sie werden von den meisten Web-Browsern noch nicht unterstutzt.<br />

Fur AWT Version 1.1 mussen die Packages java.awt und java.awt.event importiert<br />

werden, fur Swing zusatzlich das Package javax.swing.<br />

6.2 AWT-Komponenten (Component)<br />

Frame<br />

Panel<br />

Canvas<br />

Label<br />

Die folgenden Komponenten stehen in allen AWT-Versionen zur Verfugung. Sie sind<br />

Peer-Komponenten, d.h. das Aussehen und die Funktionalitat entsprechen immer<br />

dem jeweiligen Rechnersystem.<br />

ein Fenster mit Rahmen, das also vom Benutzer vergroert, verkleinert, verschoben,<br />

geschlossen werden kann (hat nichts mit dem gleichnamigen HTML-Tag zu tun).<br />

Konstruktor:<br />

new Frame(String)<br />

ein Bereich innerhalb eines Fensters oder eines anderen Panels, ohne eigenen Rahmen.<br />

Dies dient vor allem dazu, ein Fenster oder Applet in mehrere Bereiche zu unterteilen,<br />

in denen dann weitere Komponenten mit verschiedenen Layout-Managern<br />

angeordnet werden. Konstruktor:<br />

new Panel()<br />

oder new Panel(LayoutManager)<br />

eine Flache, die fur graphische Ein- und Ausgabe verwendet werden kann. Der Inhalt<br />

und die Groe mussen vom Programmierer deniert werden, zu diesem Zweck wird<br />

meist eine Subklasse von Canvas deniert, in der die entsprechenden Methoden<br />

uberschrieben werden, insbesondere die paint-Methode (siehe unten). Konstruktor:<br />

new Canvas()<br />

ein einfaches Feld fur die Darstellung eines einzeiligen Textes. Konstruktor:<br />

new Label(String)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 64


Button<br />

ein Knopf mit Text, der vom Benutzer mit der Maus gedruckt oder angeklickt werden<br />

kann. Es wird dringend empfohlen, Buttons nur dann zu verwenden, wenn das<br />

Anklicken tatsachlich etwas bewirkt, und fur Texte, die man nicht anklicken soll,<br />

stattdessen Labels zu verwenden. Auerdem wird empfohlen, Buttons immer in ihrer<br />

naturlichen Groe anzulegen (also z.B. mit dem Flow-Layout-Manager) und nicht<br />

groer werden zu lassen, damit sie vom Benutzer immer sofort als typische Buttons<br />

erkannt werden. Konstruktor:<br />

new Button(String)<br />

Checkbox<br />

ein Schalter mit Beschriftung, der ein- oder ausgeschaltet werden kann. Checkboxes<br />

konnen auch in einer CheckboxGroup zusammengefat werden, dann bewirkt das<br />

Einschalten einer Checkbox automatisch das Ausschalten der anderen (radio button).<br />

Konstruktoren:<br />

new Checkbox (String, boolean)<br />

new CheckboxGroup()<br />

new Checkbox (String, boolean, CheckboxGroup)<br />

Choice, List<br />

Listen von Texten, von denen einer bzw. mehrere ausgewahlt werden konnen. Konstruktoren:<br />

new Choice()<br />

new List(int)<br />

TextField<br />

ein einzeiliges Feld fur Tastatur-Eingaben. Konstruktor:<br />

new TextField (columns)<br />

oder new TextField (String, columns)<br />

TextArea<br />

ein mehrzeiliges Feld fur Tastatur-Eingaben. Konstruktor:<br />

new TextArea (rows, columns)<br />

oder new TextArea (String, rows, columns)<br />

Dialog<br />

ein kleines Fenster mit einem Text, das eventuell auf eine Aktion des Benutzers<br />

wartet (z.B. eine Fehlermeldung, die erst dann verschwindet, wenn der Benutzer sie<br />

anklickt). Konstruktor:<br />

new Dialog (Frame, String, true)<br />

FileDialog<br />

ein Menu zum Auswahlen einer Datei. Konstruktoren:<br />

new FileDialog (Frame, String, FileDialog.LOAD)<br />

new FileDialog (Frame, String, FileDialog.SAVE)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 65


MenuBar, Menu, MenuItem, CheckboxMenuItem, PopupMenu<br />

ScrollBar<br />

ScrollPane<br />

Methoden<br />

Komponenten zum Anlegen einer Menu-Leiste in einem Frame und von Haupt-<br />

Menus, Unter-Menus, Help-Menus oder Popup-Menus sowie von Menu-Items, die<br />

ausgewahlt werden konnen. Konstruktoren:<br />

new MenuBar()<br />

new Menu(String)<br />

new MenuItem(String)<br />

new MenuItem (String, MenuShortcut)<br />

new MenuShortcut(keycode)<br />

new MenuShortcut (keycode, shift)<br />

new CheckboxMenuItem (String, boolean)<br />

new PopupMenu(String)<br />

ein horizontaler oder vertikaler Scrollbar. Konstruktoren:<br />

new ScrollBar (Scrollbar.HORIZONTAL)<br />

new ScrollBar (Scrollbar.VERTICAL)<br />

new ScrollBar (orientation, value, size, min, max)<br />

ein Rahmen mit Scrollbars zu einem zu groen Panel oder Canvas. Konstruktor:<br />

new ScrollPane()<br />

oder new ScrollPane (ScrollPane.policy)<br />

Alle Komponenten haben die folgenden Methoden:<br />

setForeground, setBackground (siehe Farben)<br />

setFont (siehe Schriften)<br />

setSize, getSize, getPreferredSize, getMinimumSize (siehe Groe)<br />

addXxxxListener (siehe Event-Handling)<br />

setVisible(true) und setVisible(false) fur die Sichtbarkeit<br />

dispose() fur das endgultige Beenden<br />

paint, update und repaint fur die Darstellung auf dem Bildschirm des Benutzers<br />

(siehe Graphiken)<br />

Fur die einzelnen Komponenten gibt es meist noch weitere, spezielle Methoden, wie<br />

z.B.<br />

getText() und setText(String) bei den Komponenten, die einen Text enthalten,<br />

getFile() fur den im FileDialog ausgewahlten Filenamen,<br />

getTitle() und setTitle(String) fur den Text im Titlebar eines Frame,<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 66


Andere Komponenten:<br />

6.3 Container<br />

setEnabled(boolean) oder setEditable(boolean) fur das Aktivieren und<br />

Deaktivieren eines Button oder Eingabefeldes,<br />

und andere. Die Details nden Sie in der Online-Dokumentation (API).<br />

Frames, Panels, Menus und dergleichen sind Container, d.h. sie konnen andere Komponenten<br />

enthalten (eventuell auch mehrfach geschachtelt), und enthalten zu diesem<br />

Zweck weitere Methoden, siehe das Kapitel uber Container.<br />

Falls Sie mit dem Layout oder der Funktionsweise der im AWT bzw. in Swing vorgesehenen<br />

Komponenten nicht zufrieden sind, konnen Sie mit Hilfe eines Canvas<br />

beliebige eigene Komponenten denieren, z.B. spezielle Buttons, die ein Bild statt<br />

der Beschriftung enthalten oder die ihr Aussehen oder ihre Beschriftung verandern,<br />

wenn sie von der Maus erreicht, gedruckt oder angeklickt werden oder wenn bestimmte<br />

andere Aktionen erfolgreich oder nicht erfolgreich abgelaufen sind.<br />

Frames, Panels, ScrollPanes, Menus und dergleichen sind Container, d.h. sie konnen<br />

andere Komponenten enthalten (eventuell auch mehrfach geschachtelt), die dann<br />

in einer bestimmten Anordnung innerhalb des Containers dargestellt werden. Zu<br />

diesem Zweck enthalten Container - zusatzlich zu den oben angefuhrten, fur alle<br />

Komponenten gultigen Methoden - die folgenden Methoden:<br />

setLayout (LayoutManager) fur den Layout-Manager<br />

add (Component) oder add (Component, Zusatzangabe) fur das Hinzufugen<br />

einer Komponente in den Container<br />

remove (Component) und removeAll() fur das Entfernen einer Komponente<br />

bzw. von allen Komponenten aus dem Container<br />

validate() fur das Sichtbarmachen des neuen Zustands mit dem Layout-<br />

Manager<br />

Ein typisches Beispiel fur die Anwendung dieser Methoden nden Sie weiter unten.<br />

Hier nur eine kurze Skizze:<br />

Frame f = new Frame("Titlebar");<br />

f.setLayout( new FlowLayout() );<br />

Button b = new Button("Press me!");<br />

f.add(b);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 67


6.4 Layout-Manager<br />

FlowLayout<br />

BorderLayout<br />

Der Layout-Manager dient dazu, die einzelnen Komponenten innerhalb eines Containers<br />

anzuordnen und die Groe des Containers zu bestimmen. Er wird mit<br />

setLayout ( new LayoutManagerName() )<br />

vereinbart. Wenn man mit keinem der vordenierten Layout-Manager zufrieden ist,<br />

kann man<br />

setLayout(null)<br />

angeben und mu dann alle Komponenten selbst mit setLocation, setSize, SetBounds<br />

innerhalb des Containers positionieren.<br />

Die wichtigsten und einfachsten Layout-Manager sind:<br />

setLayout ( new FlowLayout() )<br />

Die Elemente werden zeilenweise nebeneinander angeordnet, der Reihe nach von<br />

links nach rechts; falls die Breite nicht ausreicht, dann in mehreren Zeilen. Standardmaig<br />

werden die Zeilen zentriert, man kann aber im Konstruktor auch mit<br />

einem Parameter angeben, da sie links- oder rechtsbundig ausgerichtet werden sollen,<br />

z.B. mit<br />

setLayout ( new FlowLayout(FlowLayout.LEFT) )<br />

setLayout ( new BorderLayout() )<br />

Der Container wird in 4 Randbereiche und einen Bereich fur den restlichen Platz<br />

in der Mitte eingeteilt, kann also hochstens 5 Elemente aufnehmen. Diese Elemente<br />

sind meistens Panels, die dann ihrerseits einzelne Komponenten enthalten und diese<br />

mit geeigneten Layout-Managern anordnen.<br />

Im add-Befehl mu mit einem zusatzlichen Parameter angegeben werden, welchen<br />

der 5 Bereiche die Komponente ausfullen soll:<br />

add (Component, "North")<br />

setzt die Komponente an den oberen Rand des Containers, mit minimaler<br />

Hohe und der vollen Container-Breite.<br />

add (Component, "South")<br />

setzt die Komponente an den unteren Rand des Containers, mit minimaler<br />

Hohe und der vollen Container-Breite.<br />

add (Component, "West")<br />

setzt die Komponente an den linken Rand des Containers, mit minimaler<br />

Breite und der vollen im Container zur Verfugung stehenden Hohe.<br />

add (Component, "East")<br />

setzt die Komponente an den rechten Rand des Containers, mit minimaler<br />

Breite und der vollen im Container zur Verfugung stehenden Hohe.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 68


add (Component, "Center")<br />

setzt die Komponente in den zwischen den anderen Komponenten verbleibenden<br />

Platz in der Mitte des Containers, mit der vollen dort zur Verfugung<br />

stehenden Hohe und Breite.<br />

Man mu nicht immer alle 5 Bereiche verwenden, oft wird das Border-Layout nur<br />

dazu verwendet, 2 oder 3 Komponenten neben- oder ubereinander anzuordnen.<br />

GridLayout<br />

setLayout ( new GridLayout (n, m) )<br />

Der Container wird in n mal m gleich groe Bereiche in n Zeilen und m Spalten<br />

aufgeteilt, und die Komponenten werden in der Reihenfolge der add-Befehle Zeile<br />

fur Zeile in dieses Gitter eingefugt und alle auf die gleiche Groe vergroert.<br />

Damit kann man z.B. eine Zeile oder eine Spalte von gleich groen Buttons erzeugen.<br />

Ab JDK 1.1 gibt es auch ein GridBagLayout, mit dem man komplexere Gitter-<br />

Strukturen denieren kann.<br />

Ab JDK 1.2 gibt es auch ein BoxLayout, mit dem man verschieden groe Komponenten<br />

in Zeilen, Spalten oder Gitter-Strukturen anordnen kann. Dazu mu man<br />

deren Groen jeweils mit getPreferredSize angeben.<br />

CardLayout<br />

CardLayout cards = new CardLayout();<br />

container.setLayout (cards);<br />

Es wird jeweils nur eine der Komponenten im Container angezeigt, alle anderen<br />

Komponenten sind unsichtbar, wie beim Aufschlagen von Spielkarten oder bei einem<br />

Dia-Vortrag.<br />

Mit add (Component, String) wird mit dem String-Parameter ein Name fur die<br />

Komponente vereinbart. Die Reihenfolge der add-Befehle ist relevant.<br />

Mit cards.show(container, String) wird die Komponente mit dem angegebenen<br />

Namen angezeigt.<br />

Mit cards.next(container) wird die jeweils nachste Komponente (in der Reihenfolge<br />

der add-Befehle) angezeigt.<br />

Mit cards.first(container) und cards.last(container) wird die erste<br />

bzw. letzte Komponente angezeigt.<br />

Dynamische Layout- Anderungen<br />

Wenn sich die Groe des Containers andert, ordnet der Layout-Manager die darin<br />

enthaltenen Komponenten automatisch neu an.<br />

Wenn sich die Groe einer Komponente andert, kann man nach dem folgenden<br />

Schema erreichen, da der Layout-Manager die Komponenten im Container richtig<br />

anordnet und anzeigt:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 69


component.invalidate();<br />

// change component<br />

container.validate();<br />

Dabei kann man den Container entweder direkt angeben oder mit component.getParent()<br />

erhalten. Das validate() im Container bewirkt auch ein validate() fur die Komponente<br />

und ein doLayout() fur den Container.<br />

6.5 Ubung: Layout-Manager<br />

6.6 Farben (Color)<br />

Erstellen Sie ein einfaches GUI (1 Frame mit 2 Buttons, 1 Label, 1 TextField) und<br />

probieren Sie 3 verschiedene Layout-Manager aus; vorerst ohne Event-Handling,<br />

Abbruch mit Ctrl-C im Befehlsfenster.<br />

Die Vordergrundfarbe (fur Texte und Linien) und Hintergrundfarbe von Komponenten<br />

konnen mit den folgenden Methoden festgelegt werden:<br />

setForeground (Color.xxx);<br />

setBackground (Color.xxx);<br />

Diese Methoden mussen immer paarweise aufgerufen werden, d.h. man mu immer<br />

beide Farben festlegen, man kann sich nicht darauf verlassen, da der Benutzer eine<br />

bestimmte Hintergrundfarbe wie wei oder hellgrau eingestellt hat. Wenn man z.B.<br />

nur den Vordergrund auf blau setzt, ein Benutzer aber aus irgendwelchen Grunden<br />

fur seinen Bildschirm weie Schrift auf blauem Grund eingestellt hat, dann bekommt<br />

er blau auf blau.<br />

Die Farbe kann auf 3 Arten angegeben werden:<br />

entweder mit einem der vordenierten Color-Objekte wie z.B. Color.black<br />

oder Color.white,<br />

oder mit einem selbst erzeugten Objekt wie z.B. new Color(255,151,0) fur<br />

orange, wobei die 3 Zahlen den Rot-, Grun- und Blau-Anteil zwischen 0 und<br />

255 angeben,<br />

oder mit einem selbst erzeugten Objekt wie z.B. Color.decode("#FF9900")<br />

mit einem String-Parameter, der die Farbe wie in HTML deniert.<br />

Die Farben von Flachen, Linien und Schriften in Graphics-Objekten werden nicht<br />

mit setForeground und setBackground sondern mit setColor angegeben (siehe unten).<br />

Nach dem folgenden Schema konnen Sie die Farben im Applet auf die Farben der<br />

Web-Page abstimmen: Der HTML-Angabe<br />

<br />

entsprechen zum Beispiel die <strong>Java</strong>-Angaben<br />

Color backColor = new Color (0xFF, 0xCC, 0x99);<br />

Color textColor = new Color (0x00, 0x66, 0x33);<br />

setBackground (backColor);<br />

setForeground (textColor);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 70


6.7 Schriften (Font)<br />

oder analog mit den dezimalen Angaben 0, 51, 102, 153, 204, 255, oder gleich mit<br />

den String-Angaben:<br />

Color backColor = Color.decode ("#FFCC99");<br />

Color textColor = Color.decode (#006633);<br />

setBackground (backColor);<br />

setForeground (textColor);<br />

Ab JDK 1.1 kann man mit statischen Feldern der Klasse SystemColor auf die vom<br />

Benutzer jeweils auf seinem Rechner eingestellten Standardfarben zugreifen und die<br />

Farben im Applet auf die Farben in den anderen Bildschirmfenstern abstimmen.<br />

Beispiele:<br />

fur Frame, Panel, Applet, Label:<br />

setBackground (SystemColor.window);<br />

setForeground (SystemColor.windowText);<br />

fur TextField, TextArea:<br />

setBackground (SystemColor.text);<br />

setForeground (SystemColor.textText);<br />

fur Button u.dgl.:<br />

setBackground (SystemColor.control);<br />

setForeground (SystemColor.controlText);<br />

und analog fur Menus, Scrollbars und andere Komponenten sowie fur spezielle Farbgebungen<br />

(highlight, inactive u.dgl.).<br />

Die Schriftart und Schriftgroe von Komponenten kann mit der folgenden Methode<br />

festgelegt werden:<br />

Font f = new Font (Fontname, Fonttyp, Fontsize);<br />

setFont (f);<br />

Fontnamen sind "Serif", "SansSerif" und "Monospaced" (in <strong>Java</strong> 1.0: "TimesRoman",<br />

"Helvetica" und "Courier").<br />

Fonttypen sind Font.PLAIN (normal), Font.BOLD (fett), Font.ITALIC (kursiv)<br />

oder die Summe Font.BOLD+Font.ITALIC.<br />

Die Fontgroe wird als ganze Zahl in Points (nicht in Pixels) angegeben, eine typische<br />

Fontgroe ist 12.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 71


6.8 Groenangaben<br />

Bei den meisten Komponenten ergibt sich ihre richtige Groe aus ihrem Inhalt (Textstring<br />

bei einem Label oder Button, Summe der Komponenten bei einem Container)<br />

und mu daher vom Programmierer nicht explizit angegeben werden.<br />

Bei einem Fenster (Frame oder Dialog) mu die Groe explizit angegeben werden:<br />

entweder mit setSize( breite, hohe );<br />

oder mit pack();<br />

Dies bedeutet, da das Fenster mit Hilfe des Layout-Managers so klein wie<br />

moglich gemacht wird, da gerade noch alle Komponenten darin Platz haben.<br />

Bei einem Zeichenobjekt (Canvas) mu die Groe ebenfalls explizit angegeben<br />

werden, und zwar mit Hilfe der folgenden Methoden, die vom Layout-Manager abgefragt<br />

werden, um den benotigten Platz festzustellen:<br />

getMinimumSize()<br />

getPreferredSize()<br />

getMaximumSize()<br />

Es gibt auch weitere Spezialfalle, in denen man dem Layout-Manager mit solchen<br />

expliziten Groenangaben helfen kann, die richtige Groe zu nden. Es hangt vom<br />

jeweils verwendeten Layout-Manager ab, ob und wie er diese Groenangaben verwendet<br />

und umsetzt.<br />

Bei allen Komponenten und Containern kann man jederzeit mit<br />

getSize()<br />

abfragen, wie gro die Komponente tatsachlich ist. Diese Methode liefert ein Objekt<br />

vom Typ Dimension, das die beiden Datenfelder width und height enthalt (Breite<br />

und Hohe in Pixeln).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 72


6.9 Zeichenobjekte (Canvas)<br />

Die Klasse Canvas beschreibt eine leere Zeichenache der Groe null mal null Pixels.<br />

Fur konkrete Zeichenobjekte mu man deshalb jeweils eine Subklasse der Klasse<br />

Canvas denieren und in ihr die folgenden Methoden uberschreiben:<br />

getMinimumSize etc. fur die Groe<br />

(wird vom Layout-Manager abgefragt, um die Groe und Position innerhalb<br />

des Containers festzustellen),<br />

paint fur den graphischen Inhalt<br />

(wird vom Window-System aufgerufen, um das Objekt am Bildschirm sichtbar<br />

zu machen).<br />

Beispielskizze:<br />

public class Xxxxx extends Canvas {<br />

}<br />

public Dimension getMinimumSize() {<br />

return new Dimension (300, 200);<br />

}<br />

public Dimension getPreferredSize() {<br />

return getMinimumSize();<br />

}<br />

public void paint (Graphics g) {<br />

g.setColor (...);<br />

g.draw... (...);<br />

g.fill... (...);<br />

}<br />

6.10 Graphiken (Graphics, paint)<br />

Bei fast allen Komponenten ist das Aussehen bereits festgelegt, die paint-Methode<br />

soll daher nicht uberschrieben und die repaint-Methode nicht aufgerufen werden.<br />

Nur bei Komponenten des Typs Canvas mu explizit mit der paint-Methode angegeben<br />

werden, welche graphischen Elemente dargestellt werden sollen. Zu diesem<br />

Zweck wird eine Subklasse der Klasse Canvas deniert und in ihr die paint-Methode<br />

uberschrieben.<br />

Die paint-Methode arbeitet mit einem Objekt des Typs Graphics und hat den folgenden<br />

Aufbau:<br />

public void paint (Graphics g) {<br />

g.setColor (...);<br />

g.draw... (...);<br />

g.fill... (...);<br />

}<br />

Die wichtigsten Methoden des Graphics-Objekts sind:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 73


Farbe und Schrift:<br />

Linien:<br />

Flachen:<br />

Texte (String):<br />

Bevor man Linien zeichnet, Flachen fullt oder Strings ausgibt, mu man die Farbe<br />

und eventuell auch die Schriftart fur die unmittelbar folgenden Graphik-Befehle<br />

festlegen.<br />

Die Festlegung der Farbe erfolgt hier also nicht mit setForeground und setBackground<br />

sondern Schritt fur Schritt mit<br />

setColor ( Color );<br />

Die Festlegung der Schriftart erfolgt wie gewohnt mit<br />

setFont ( Font );<br />

drawLine (x1, y1, x2, y2);<br />

zeichnet eine gerade Linie vom ersten Punkt zum zweiten Punkt. Wenn die beiden<br />

Punkte identisch sind, wird nur ein Punkt gezeichnet (1 Pixel). Die Linienbreite<br />

ist immer 1 Pixel. Breitere Linien kann man erzeugen, indem man mehrere parallele<br />

Linien, jeweils um 1 Pixel verschoben, nebeneinander zeichnet, oder mit llPolygon<br />

(siehe unten).<br />

Mit den folgenden Methoden werden Linienzuge oder Kurven gezeichnet. Die Parameterliste<br />

gibt meistens zuerst den linken oberen Eckpunkt und dann die Breite<br />

und Hohe der Figur bzw. des sie umschreibenden Rechtecks an (Genauer: Das Rechteck<br />

hat eine Breite von (width+1) Pixels und eine Hohe von (height+1) Pixels).<br />

Kreise erhalt man als Spezialfall von Ellipsen mit gleicher Breite und Hohe.<br />

drawRect (x1, y1, width, height);<br />

drawPolygon (x[], y[], n);<br />

drawPolyLine (x[], y[], n);<br />

drawOval (x1, y1, width, height);<br />

drawArc (x1, y1, width, height, startangle, angle);<br />

Mit den folgenden Methoden werden Flachen farbig gefullt. Die ll-Methoden haben<br />

stets die gleichen Parameter wie die entsprechenden draw-Methoden.<br />

fillRect (x1, y1, width, height);<br />

fillPolygon (x[], y[], n);<br />

fillOval (x1, y1, width, height);<br />

fillArc (x1, y1, width, height, startangle, angle);<br />

drawString (String, x1, y1);<br />

stellt einen einzeiligen Textstring dar. Ein automatischer Zeilenumbruch ist hier<br />

nicht moglich.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 74


Bilder (Image)<br />

drawImage (Image, x1, y1, this);<br />

Programmtechnische Details:<br />

Die Koordinaten werden in Bildpunkten (Pixels) angegeben. Der Ursprung (0,0)<br />

des Koordinatensystems liegt links oben, die x-Achse geht von links nach rechts, die<br />

y-Achse von oben nach unten (also umgekehrt wie in der Mathematik).<br />

Winkelangaben erfolgen hier in Grad (im Gegensatz zu den mathematischen Funktionen<br />

in der Klasse Math, wo sie in Radiant erfolgen). Winkel werden von "Osten"<br />

aus gegen den Uhrzeigersinn gezahlt.<br />

Die Reihenfolge der Aufrufe der einzelnen Methoden fur das Graphics-Objekt ist<br />

wichtig: Spatere Aufrufe uberschreiben die von fruheren Aufrufen eventuell bereits<br />

gesetzten Bildelemente (Pixels), d.h. die Reihenfolge der Befehle beginnt mit dem<br />

Hintergrund und endet mit dem Vordergrund.<br />

Die paint-Methode wird in verschiedenen Situationen aufgerufen:<br />

1. explizit beim Aufruf der Methode repaint() sowie bei setVisible(true)<br />

2. automatisch immer dann, wenn sich die Sichtbarkeit des Fensters am Bildschirm<br />

des Benutzers andert, also z.B. wenn der Benutzer das Fenster verschiebt,<br />

vergroert oder verkleinert, oder wenn das Fenster ganz oder teilweise<br />

durch ein anderes Fenster verdeckt wird bzw. wieder zum Vorschein kommt.<br />

Da man den zweiten Fall vom Programm aus nicht kontrollieren kann, ist es wichtig,<br />

da die gesamte Graphik-Ausgabe innerhalb der paint-Methode deniert ist und<br />

nicht in irgendwelchen anderen Methoden, die nur explizit aufgerufen werden.<br />

Wenn sich die dargestellte Graphik in Abhangigkeit von bestimmten Aktionen<br />

verandern soll, dann empehlt sich folgende Vorgangsweise: Man legt globale Datenfelder<br />

an, die die verschiedenen Situationen beschreiben und die von der paint-<br />

Methode abgefragt werden. Wenn sich das ausgegebene Bild andern soll, dann<br />

verandert man diese Datenfelder und ruft repaint() auf, soda die paint-Methode<br />

den neuen Zustand der Ausgabe erzeugt.<br />

<strong>Java</strong>-2D und 3D (ab JDK 1.2)<br />

Ab JDK 1.2 gibt es das sogenannte <strong>Java</strong>-2D-API, also eine Gruppe von Packages und<br />

Klassen, mit denen 2-dimensionale graphische Objekte genauer und bequemer konstruiert<br />

werden: die Klasse Graphics2DObject und eine Reihe von weiteren Klassen<br />

in den Packages java.awt.color, java.awt.geom und java.awt.image. Damit konnen<br />

z.B. Linien mit beliebiger Strichstarke gezeichnet sowie geometrische Figuren um<br />

beliebige Winkel gedreht werden.<br />

Fur die Zukunft wird auch an einer <strong>Java</strong>-3D-API fur die Darstellung von 3-<br />

dimensionalen Objekten gearbeitet. Genauere Informationen daruber ndet man<br />

auf dem <strong>Java</strong>-Web-Server (siehe die Referenzen).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 75


Zeichnen in einem Container<br />

Die Klasse Container ist eine Unterklasse von Component, man kann daher die Container<br />

(wie z.B. Frame oder Applet), wenn man will, wie eine einzelne Komponente<br />

behandeln, so wie einen Canvas. Man kann also<br />

entweder mit add einzelne Komponenten zum Container hinzufugen<br />

oder den Inhalt des kompletten Container mit paint selbst festlegen,<br />

aber man sollte diese beiden Moglichkeiten nicht gleichzeitig verwenden, weil sonst<br />

die eine die andere stort.<br />

Wenn man Graphiken und Standard-Komponenten in einem Container haben will,<br />

ist es am besten, wenn man fur die Graphiken eigene Canvas-Komponenten erzeugt,<br />

die die entsprechende paint-Methode enthalten, und dann alle diese Komponenten<br />

mit add zum Container hinzufugt.<br />

Wenn man doch beides kombinieren will, z.B um mit der paint-Methode den Hintegrund<br />

des Containers hinter den Komponenten festzulegen, dann mu man in der<br />

paint-Methode nach dem Zeichnen der Hintergrund-Graphik mit<br />

super.paint(g)<br />

fur das richtige Zeichnen der Komponenten sorgen.<br />

6.11 mehrzeilige Texte<br />

Mit Label und TextField und mit der Graphics-Methode drawString kann jeweils<br />

immer nur eine Textzeile ausgegeben werden. Wenn man will, da ein langerer Text<br />

automatisch je nach dem verfugbaren Platz in mehrere Zeilen umgebrochen wird,<br />

kann man eine TextArea ohne horizontalen Scrollbar verwenden. Beispiel:<br />

TextArea t1 = new TextArea( longString, 5, 20,<br />

TextArea.SCROLLBARS_VERTICAL_ONLY );<br />

Bei JTextArea (Swing) kann man dafur eine eigene Methode setWrap(boolean) verwenden,<br />

unabhangig vom Scrollbar. In Swing bzw. JDK 1.2 gibt es auch noch weitergehende<br />

Moglichkeiten, z.B. fur die formatierte Darstellung von Texten, HTMLoder<br />

RTF-Dokumenten in einer JEditorPane oder JTextPane. Beispiel:<br />

JEditorPane pane = new JEditorPane();<br />

String somehtml = "<br />

Hello<br />

<br />

Hello!<br />

Some <strong>Java</strong>-generated long text<br />

<br />

";<br />

pane.setContentPane("text/html");<br />

pane.setText(somehtml);<br />

add(pane);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 76


6.12 Event-Handling<br />

Listener-Interfaces<br />

Graphische User-Interfaces bieten mehrere Moglichkeiten fur Eingaben und sonstige<br />

steuernde Aktivitaten des Benutzers: Er kann eine oder mehrere Tasten auf<br />

der Tastatur drucken, die Maus bewegen, eine Maustaste drucken oder loslassen<br />

oder klicken, und er kann Kombinationen davon ausfuhren. Das Programm kann<br />

nicht vorhersagen, was er wann tun wird, sondern mu darauf warten, welche der<br />

moglichen Aktivitaten er in welchen Komponenten des GUI durchfuhrt, und dann<br />

jeweils darauf reagieren. Diese Reaktion auf vom Benutzer ausgeloste Ereignisse wird<br />

als Event-Handling bezeichnet.<br />

Mit JDK 1.1 wurde eine komplett neue Version des Event-Handling eingefuhrt. Dazu<br />

mu das Package java.awt.event importiert werden. Die alte Version 1.0 des Event-<br />

Handling ist weiterhin im Package java.awt verfugbar und wird vom Compiler nur<br />

mit der Warnung "deprecated" versehen (kein Fehler).<br />

Hier wird die Version 1.1 beschrieben.<br />

Fur die verschiedenen Arten von Ereignissen (Events) sind Interfaces mit Namen<br />

der Form XxxxListener vorgesehen. Zu jeder Komponente, die auf solche Events<br />

reagieren soll (z.B. Mausklicks auf einen Button oder innerhalb eines Canvas), mu<br />

mit addXxxxListener ein Listener-Objekt vereinbart werden, das die Methoden des<br />

jeweiligen Interfaces implementiert und damit die gewunschten Aktionen ausfuhrt.<br />

Beispiel:<br />

...<br />

Button b = new Button("B");<br />

ActionListener ali = new MyListener();<br />

b.addActionListener(ali);<br />

...<br />

public class MyListener implements ActionListener {<br />

public void actionPerformed (ActionEvent e) {<br />

...<br />

}<br />

}<br />

Es gibt zwei Arten von Listenern bzw. Events:<br />

logische Listener, die einfach die durchgefuhrte Aktion beschreiben (z.B. der<br />

ActionListener, der angibt, da ein Button ausgelost oder ein Textfeld ausgefullt<br />

wurde), und<br />

physische Listener, die genau beschreiben, was der Benutzer mit welchem Eingabegerat<br />

getan hat (z.B. der MouseListener, der angibt, an welcher Position<br />

die Maustaste langsam gedruckt oder schnell geklickt wurde).<br />

Die folgenden Interfaces stehen zur Verfugung und besitzen die folgenden Methoden,<br />

die implementiert werden mussen:<br />

ActionListener: actionPerformed<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 77


ItemListener: itemStateChanged<br />

TextListener: textValueChanged<br />

AdjustmentListener: adjustmentValueChanged<br />

MouseListener: mousePressed, mouseReleased, mouseEntered, mouse-<br />

Exited, mouseClicked<br />

MouseMotionListener: mouseDragged, mouseMoved<br />

KeyListener: keyPressed, keyReleased, keyTyped<br />

WindowListener: windowClosing, windowClosed, windowOpened, window-<br />

Iconied, windowDeiconied, windowActivated, windowDeactivated<br />

ComponentListener: componentMoved, componentResized, component-<br />

Hidden, componentShown<br />

ContainerListener: componentAdded, componentRemoved<br />

FocusListener: focusGained, focusLost<br />

Event-Klassen<br />

Die Methoden haben jeweils einen Parameter vom Typ XxxxEvent (also Action-<br />

Event, ItemEvent, MouseEvent etc., nur beim MouseMotionListener wird ebenfalls<br />

der MouseEvent verwendet), und diese Objekte haben Methoden, mit denen man<br />

abfragen kann, welcher Button angeklickt wurde, welcher Text in ein Textfeld eingegeben<br />

wurde, an welcher Position die Maustaste gedruckt oder losgelassen wurde,<br />

welche Taste auf der Tastatur gedruckt wurde etc.<br />

Alle Events haben die folgende Methode:<br />

Object getSource()<br />

fur die Komponente, in der das Ereignis ausgelost wurde.<br />

Die wichtigsten weiteren Methoden in den einzelnen Event-Arten sind:<br />

im ActionEvent: getActionCommand() fur den Namen der angeklickten<br />

Komponente (des Button)<br />

im ItemEvent: getItem() fur die Komponente (das ausgewahlte Item)<br />

im TextEvent: getSource() fur die Komponente (das Texteingabefeld)<br />

im AdjustmentEvent: getAdjustable() fur die Komponente (den Scrollbar)<br />

und getValue() fur den eingestellten Wert<br />

im MouseEvent: getX() und getY() fur die Position der Maus, getClick-<br />

Count() fur die Unterscheidung von Einfach- und Doppelklick, isShiftDown(),<br />

isCtrlDown(), isAltDown() fur gleichzeitig festgehaltene Tasten<br />

im KeyEvent: getKeyChar(), getKeyCode(), getKeyText() fur die gedruckte<br />

Taste, isShiftDown(), isCtrlDown(), isAltDown() fur gleichzeitig festgehaltene<br />

Tasten<br />

im WindowEvent: getWindow() fur die Komponente (das Fenster)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 78


im ComponentEvent: getComponent() fur die Komponente<br />

im ContainerEvent: getContainer() fur den Container, getChild() fur die<br />

hinzugefugte oder entfernte Komponente<br />

im FocusEvent: getComponent() fur die Komponente<br />

Wenn diese Methoden "nur" ein Objekt (die Komponente, die das Ereignis ausgelost<br />

hat) liefern, dann kann man in diesem Objekt die genaueren Informationen nden,<br />

z.B. welcher Text im Texteingabefeld steht. Fur die Details wird auf die Online-<br />

Dokumentation (API) verwiesen. Beispiel:<br />

String s = null;<br />

if (e.getSource() instanceof TextField) }<br />

s = ( (TextField)(e.getSource()) ).getText();<br />

}<br />

6.13 Beispiel: typischer Aufbau einer einfachen GUI-Applikation<br />

Bei sehr einfachen GUI-Applikationen kann man alles in einer Klasse denieren, wie<br />

hier skizziert. Bei komplexeren GUI-Applikationen ist es aber besser, die Anwendung<br />

nach den Grundsatzen der objekt-orientierten Programmierung in mehrere kleinere<br />

Klassen aufzuteilen (siehe den nachfolgenden Abschnitt).<br />

import java.awt.* ;<br />

import java.awt.event.* ;<br />

public class TestFrame extends Frame<br />

implements ActionListener, WindowListener {<br />

private Button b1;<br />

// ... more Components ...<br />

public TestFrame (String s) {<br />

super(s);<br />

}<br />

public void init() {<br />

setLayout (new FlowLayout() );<br />

b1 = new Button("Press me! ");<br />

b1.addActionListener (this);<br />

add(b1);<br />

// ... more Components ...<br />

addWindowListener(this);<br />

setSize(300,200); // or: pack();<br />

setVisible(true);<br />

}<br />

public static void main (String[] args) {<br />

TestFrame f = new TestFrame("Test");<br />

f.init();<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 79


}<br />

public void actionPerformed (ActionEvent e) {<br />

System.out.println("Button was pressed.");<br />

}<br />

public void windowClosing (WindowEvent e) {<br />

dispose();<br />

System.exit(0);<br />

}<br />

public void windowClosed (WindowEvent e) { }<br />

public void windowOpened (WindowEvent e) { }<br />

public void windowIconified (WindowEvent e) { }<br />

public void windowDeiconified (WindowEvent e) { }<br />

public void windowActivated (WindowEvent e) { }<br />

public void windowDeactivated (WindowEvent e) { }<br />

Anmerkungen:<br />

Im Sinn der objekt-orientierten Programmierung erfolgen die wesentlichen Aktionen<br />

nicht direkt in der statischen main-Methode erfolgen sondern in der nicht-statischen<br />

Methode init. Der Name dieser Methode wurde so gewahlt, da eine Umwandlung<br />

der Applikation in ein Applet bei Bedarf leicht moglich ist. Der Aufruf dieser<br />

init-Methode kann entweder, wie oben, explizit in der main-Methode oder, wie im<br />

nachsten Beispiel unten, im Konstruktor erfolgen.<br />

Bei Fenstern (Frames) soll immer ein WindowListener aktiv sein, der das im Fenster<br />

laufende Programm beendet, wenn der Benutzer das Fenster schliet - dies gehort<br />

zum normalen Verhalten von Fenstern in jedem System.<br />

Weitere Beispiele fur typische GUI-Komponenten und Event-Handlung nden Sie<br />

im Kapitel uber Applets:<br />

Button-Aktionen (Button, Label, ActionListener)<br />

Maus-Aktionen (Graphics, MouseListener, MouseMotionListener)<br />

Text-Aktionen (TextField, Label, ActionListener)<br />

Das Event-Handling ist in allen diesen Beispielen der Einfachheit halber mit public<br />

Methoden in den public Klassen realisiert. Wenn man den Zugri auf diese Methoden<br />

von fremden Klassen aus verhindern will, kann man stattdessen sogenannte<br />

"anonyme innere Klassen" verwenden, Beispiele dafur ndet man in den Referenzen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 80


6.14 Beispiel: typischer Aufbau einer komplexen GUI-Applikation<br />

Applikation<br />

Datenmodell (Model)<br />

Bei sehr einfachen GUI-Applikationen kann man alles in einer Klasse denieren<br />

(siehe oben). Bei komplexeren GUI-Applikationen ist es aber besser, die Anwendung<br />

nach den Grundsatzen der objekt-orientierten Programmierung in mehrere kleinere<br />

Klassen fur die einzelnen Objekte aufzuteilen. In Sinne des MVC-Konzepts (Model,<br />

View, Controller) sollte man zumindest die folgenden Klassen bzw. Gruppen von<br />

Klassen verwenden:<br />

Applikation (main-Methode)<br />

Datenmodell (model)<br />

Ansicht (view)<br />

Steuerung (controller)<br />

Von den vielen Moglichkeiten, wie man das gestalten kann, wird im folgenden eine<br />

Moglichkeit skizziert:<br />

Die Applikation legt zuerst ein Objekt des Datenmodells an und dann ein Objekt<br />

der Ansicht. Die Referenz auf das Datenobjekt wird der Ansicht im Konstruktor<br />

ubergeben. Die init-Methode der Ansicht wird gleich vom Konstruktor ausgefuhrt:<br />

public class XxxApplication {<br />

public static void main (String[] args] {<br />

XxxModel model = new XxxModel();<br />

String title = "Title String";<br />

XxxView view = new XxxView (model, title);<br />

}<br />

}<br />

Das Datenmodell enthalt die Datenfelder, die get- und set-Methoden fur alle Datenfelder,<br />

sowie Berechnungsmethoden, mit denen die Ergebnisse aus den Eingabewerten<br />

berechnet werden:<br />

public class XxxModel {<br />

private type xxx;<br />

...<br />

public void setXxx (type xxx) {<br />

this.xxx = xxx;<br />

}<br />

public type getXxx() {<br />

return xxx;<br />

}<br />

...<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 81


Ansicht (View)<br />

Die Ansicht baut in der init-Methode das graphische User-Interface auf. Das Eventhandling<br />

wird jedoch nicht von dieser Klasse sondern von einem Objekt der Steuerungsklasse<br />

oder von mehreren solchen Objekten durchgefuhrt. Dem Steuerungsobjekt<br />

werden die Referenzen sowohl auf das Datenobjekt als auch auf die Ansicht<br />

(this) als Parameter ubergeben.<br />

Im Konstruktor der Ansicht wird nicht nur der Title-String des Frame sondern auch<br />

die Referenz auf das Datenobjekt ubergeben. Die Datenfelder konnen dann mit den<br />

get-Methoden des Datenmodells abgefragt und in den GUI-Komponenten graphisch<br />

dargestellt werden.<br />

Fur komplexere Anwendungen ist es eventuell besser, da sich alle View-Klassen<br />

bei der zugehorigen Model-Klasse "registrieren". Eine Skizze dazu nden Sie weiter<br />

unten am Ende dieses Beispiels.<br />

Auerdem wird im Konstruktor auch gleich die init-Methode aufgerufen, die den<br />

Frame komplett aufbaut.<br />

Die Komponenten werden hier nicht als private sondern als protected oder packagefriendly<br />

deklariert, damit sie vom Steuerungsobjekt angesprochen werden konnen.<br />

Die im Beans-Konzept verlangten set- und get-Methoden fehlen in dieser Skizze.<br />

import java.awt.* ;<br />

import java.awt.event.* ;<br />

public class XxxView extends Frame {<br />

private XxxModel model;<br />

private XxxController controller;<br />

protected TextField field1;<br />

protected Label label1;<br />

...<br />

public XxxView (XxxModel m, String s) {<br />

super(s);<br />

this.model = m;<br />

this.init();<br />

}<br />

public void init() {<br />

controller = new XxxController (this, model);<br />

setLayout ( new FlowLayout() );<br />

field1 = new TextField (30);<br />

field1.addActionListener (controller);<br />

add(field1);<br />

label1 = new Label ( model.getYyy() );<br />

add (label1);<br />

...<br />

addWindowListener (controller);<br />

setSize (300, 200);<br />

setVisible (true);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 82


}<br />

}<br />

Steuerung (Controller)<br />

Wenn das GUI aus mehreren Objekten besteht, werden dafur wiederum eigene Klassen<br />

deniert. So werden z.B. fur die graphische Darstellung von Datenfeldern Subklassen<br />

von Canvas (oder dergleichen) verwendet, denen ebenfalls die Referenz auf<br />

das Datenobjekt im Konstruktor ubergeben wird.<br />

Die Steuerungsklasse implementiert die Listener-Interfaces und fuhrt die entsprechenden<br />

Aktionen durch. Sie erhalt im Konstruktor die Referenzen sowohl auf das<br />

Datenobjekt als auch auf das Ansichtobjekt ubergeben und kann dann je nach den<br />

Benutzer-Aktionen die Datenfelder mit den set-Methoden des "Model" setzen und<br />

die Anzeige der Daten und Ergebnisse mit den set- und repaint-Methoden der GUI-<br />

Komponenten im "View" bewirken.<br />

import java.awt.* ;<br />

import java.awt.event.* ;<br />

public class XxxController<br />

implements YyyListener {<br />

private XxxModel model;<br />

private XxxView view;<br />

public XxxController (XxxView v, XxxModel m) {<br />

this.view = v;<br />

this.model = m;<br />

}<br />

}<br />

... // Methoden der Listener-Interfaces<br />

Hier eine Beispielskizze, wie die Aktionen innerhalb der Methoden des Listener-<br />

Interface aussehen konnen:<br />

public void actionPerformed (ActionEvent e) {<br />

Object which = e.getSource();<br />

if (which == view.field1) {<br />

model.setXxx ( view.field1.getText() );<br />

view.label1.setText ( model.getYyy() );<br />

}<br />

...<br />

}<br />

Wenn mehrere, verschiedene Aktionen von verschiedenen GUI-Komponenten ausgelost<br />

werden, dann konnen dafur jeweils eigene Steuerungsklassen deniert und<br />

entsprechend mehrere Steuerungsobjekte angelegt werden.<br />

In dem hier skizzierten Fall mu der Controller "wissen", welche Ansichten (View-<br />

Klassen) welche Daten (Model-Klassen) darstellen. Eine bessere Losung ware es, da<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 83


sich alle View-Klassen bei der Model-Klasse registrieren und dann von der Model-<br />

Klasse automatisch benachrichtigt werden, wenn die Daten sich geandert haben und<br />

daher von der View-Klasse neu dargestellt werden mussen. Beispielskizze:<br />

import java.util.*;<br />

public class XxxModel extends Observable {<br />

...<br />

// change some data in the model<br />

setChanged();<br />

notifyObservers (arg);<br />

...<br />

}<br />

import java.util.*;<br />

public class XxxView extends Xxx implements Observer {<br />

XxxModel m;<br />

...<br />

public XxxView (XxxModel m) {<br />

this.m = m;<br />

m.addObserver(this);<br />

}<br />

...<br />

public void update (Observable o, Object arg) {<br />

// show the new data in the view<br />

...<br />

}<br />

...<br />

}<br />

6.15 Ubung: einfache GUI-Applikation<br />

Schreiben Sie eine einfache GUI-Applikation, die ein Fenster mit folgendem Inhalt<br />

anzeigt:<br />

Am oberen Rand soll in der Mitte ein kurzer Text stehen.<br />

Am unteren Rand sollen 2 Buttons nebeneinander zu sehen sein:<br />

{ ein Open-Button, der keine Aktion bewirkt, und<br />

{ ein Close-Button, der die Beendigung der Applikation bewirkt.<br />

Fuhren Sie diese Applikation aus und testen Sie auch, was passiert, wenn Sie das<br />

Fenster vergroern oder verkleinern.<br />

Anmerkung: Diese Ubung stellt gleichzeitig eine Vorarbeit fur die Ubung im Kapitel<br />

Applets dar.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 84


6.16 Swing-Komponenten (JComponent)<br />

In Swing (<strong>Java</strong> Foundation Classes JFC) stehen als Alternative zu den AWT-<br />

Komponenten die folgenden "light weight" Komponenten zur Verfugung. Sie verwenden<br />

keine Peers vom Betriebssystem, sondern sind komplett in <strong>Java</strong> deniert.<br />

Man kann das Aussehen und die Funktionalitat (look and feel) fur diese Komponenten<br />

im <strong>Java</strong>-Programm genau festlegen:<br />

entweder, indem man eines der vorgefertigten Designs auswahlt (z.B. wie bei<br />

Motif oder wie bei Windows)<br />

oder, indem man alle Details selbst festlegt und damit ein produktspezisches<br />

Look-and-Feel erzeugt.<br />

Swing-Komponenten sollten niemals mit Peer-Komponenten gemischt verwendet<br />

werden.<br />

Fur Swing mu das Package javax.swing importiert werden. Dieses Package bzw.<br />

die <strong>Java</strong> Foundation Classes JFC mussen bei JDK 1.1 zusatzlich installiert werden<br />

und sind ab JDK 1.2 Teil des JDK.<br />

Die Swing-Komponenten werden von den meisten Web-Browsern noch nicht unterstutzt.<br />

Komponenten und Datenmodelle<br />

Die wichtigsten Swing-Kompontenten sind:<br />

JFrame mit ContentPane, fur ein Fenster mit Rahmen (wie Frame)<br />

JPanel, JInternalFrame, JDesktopPane, JLayeredPane, JTabbed-<br />

Pane, JApplet fur einen Bereich (wie Panel bzw. Applet)<br />

JComponent als Oberklasse fur alle Swing-Komponenten und Container,<br />

und fur eine Zeichenache (wie Canvas und Panel)<br />

JLabel fur einen Text oder ein Icon (wie Label)<br />

JButton fur einen Knopf mit Text oder Icon (wie Button)<br />

JCheckbox, JRadioButton, JToggleButton fur einen Schalter (wie<br />

Checkbox)<br />

JList, JComboBox in Verbindung mit einem Vector oder einem ListModel<br />

bzw. ComboBoxModel und ListCellRenderer fur Auswahllisten (wie Choice<br />

bzw. List)<br />

JTextField, JPasswordField, JTextArea in Verbindung mit String oder<br />

Document, fur Text-Eingaben (wie TextField bzw. TextArea)<br />

JDialog, JOptionPane fur Dialogfenster (wie Dialog)<br />

JFileDialog, JFileChooser fur die Auswahl einer Datei (wie FileDialog)<br />

JMenuBar, JMenu, JMenuItem, JCheckboxMenuItem,<br />

Menu, JSeparator fur Menus (wie MenuBar, Menu etc.)<br />

JPopup-<br />

JScrollBar, JScrollPane fur Scrollbars (wie ScrollBar bzw. ScrollPane)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 85


ImageIcon fur ein kleines Bild<br />

JProgressBar fur die graphische Darstellung eines Zahlenwertes<br />

JSlider fur die graphische Eingabe eines Zahlenwertes<br />

JColorChooser fur die Auswahl einer Farbe<br />

JToolBar fur eine Button-Leiste<br />

JToolTip bzw. setToolTipText() fur eine Zusatzinformation zu jeder Komponente<br />

JTable in Verbindung mit TableModel und TableCellRenderer fur die Anordnung<br />

von Komponenten in Tabellenform<br />

JTree in Verbindung mit TreeModel, TreePath, TreeNode und TreeCellRenderer<br />

oder TreeCellEditor sowie TreeSelectionModel und TreeSelectionListener<br />

fur die Darstellung eines hierarchischen Baums von Elementen wie z.B. ein<br />

Directory mit Subdirectories und Files<br />

JEditorPane, JTextPane in Verbindung mit einem String oder einem<br />

InputStream oder Reader oder einem Document wie PlainDocument, Default-<br />

StyledDocument oder HTMLDocument mit HyperlinkListener, und mit einem<br />

EditorKit wie DefaultEditorKit, HTMLEditorKit oder RTFEditorKit, fur die<br />

formatierte Darstellung von Text. Die HTML-Unterstutzung ist dabei nur relativ<br />

einfach, fur "besseres" HTML gibt es, alleridngs nicht kostenlos, eine<br />

Hot<strong>Java</strong>-Bean von der Firma Sun.<br />

Beispielskizze<br />

Hier ein kurze Skizze fur die Verwendung von einfachen Swing-Komponenten. Die<br />

Beschreibung der verwendeten Klassen und Methoden nden Sie in der Online-<br />

Dokumentation von Swing (im JDK ab 1.2).<br />

import java.awt.*;<br />

import java.awt.event.*;<br />

import javax.swing.*;<br />

public class SwingTest {<br />

public static void main (String[] args) {<br />

JFrame f = new JFrame ("Swing Test");<br />

Container inhalt = f.getContentPane();<br />

inhalt.setLayout (new FlowLayout() );<br />

String labText =<br />

"Lautst&auml;rke(volume)" ;<br />

JLabel lab = new JLabel ("" + labText + "");<br />

inhalt.add(lab);<br />

JSlider slid = new JSlider (0, 100, 50);<br />

// slid.addChangeListener ( ... );<br />

slid.setToolTipText("Stellt die Lautstrke ein.");<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 86


inhalt.add(slid);<br />

ImageIcon stopIcon = new ImageIcon ("images/stop.gif");<br />

JButton but = new JButton ( "Stop", stopIcon );<br />

// but.addActionListener ( ... );<br />

but.setToolTipText("Stoppt das Abspielen.");<br />

inhalt.add(but);<br />

}<br />

}<br />

f.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);<br />

f.setSize(400,150);<br />

f.setVisible(true);<br />

Model, View, Controller<br />

Die Swing-Klassen unterstutzen das Prinzip von Model, View und Controller.<br />

Zu den sichtbaren Komponenten (View) gibt es jeweils geeignete Datenobjekte (Model,<br />

siehe die Hinweise in der obigen Klassenliste).<br />

Die Verbindung vom View zum Controller erfolgt wie beim AWT durch das Event-<br />

Handling mit den add-Listener-Methoden.<br />

Der Controller mu nur die Daten im Model-Objekt verandern (set-Methoden).<br />

Die Verbindung zwischen Model und View erfolgt automatisch nach dem Konzept<br />

von Observer und Observable. Dafur mu man nur im Konstruktor des View-Objekts<br />

das entsprechende Model-Objekt angeben. Die Registrierung des View als Observer<br />

des Model (addObserver) wird vom Konstruktor erledigt, und das automatische Update<br />

der Daten-Darstellung im View (notifyObservers) wird von den set-Methoden<br />

des Model erledigt.<br />

Wie die Darstellung der Daten im View aussehen soll, wird mit Renderern festgelegt.<br />

Beispiel:<br />

Die Klasse JTree ist eine Komponente, mit der bestimmte Informationen (Knoten<br />

und Blatter) am Bildschirm in einer Baum-Struktur sichtbar gemacht werden<br />

sollen.<br />

Die im JTree dargestellten Informationen (Model) werden mit einem TreeModel<br />

beschrieben, das aus TreePaths und TreeNodes besteht. Fur die meisten<br />

Anwendungsfalle kann man die Klassen DefaultTreeModel und DefaultMutableTreeNode<br />

verwenden.<br />

Die Darstellung von TreeNodes im JTree (View) erfolgt mit einem TreeCell-<br />

Renderer.<br />

Die Steuerung der Aktionen, die der Benutzer mit dem JTree durchfuhrt (Controller),<br />

z.B. durch Auswahl oder Doppelklick auf Elemente darin, erfolgt mit<br />

dem in diesen Klassen vorgesehenen Event-Handling. Auerdem generieren<br />

die Methoden des TreeModel eigene Events, die dafur sorgen, da sich die<br />

Darstellung im JTree andert, wenn sich die Daten im TreeModel andern.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 87


Analoges gilt fur andere Komponenten wie JList, JTable usw.<br />

Fur genauere Informationen uber die Swing-Klassen fur Komponenten, Models, Renderer,<br />

Events, LookAndFeels etc. und uber die Konstruktoren und Methoden dieser<br />

Klassen wird auf die Online-Dokumentation (API) und auf die Referenzen verwiesen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 88


7. Applets<br />

Applet = Panel innerhalb einer Web-Page<br />

lauft innerhalb des Web-Browsers<br />

<strong>Java</strong>-Applets werden innerhalb einer Web-Page dargestellt und unter der Kontrolle<br />

eines Web-Browsers ausgefuhrt.<br />

Technisch gesehen zeichnen sich <strong>Java</strong>-Applets dadurch aus, da sie Unterklassen<br />

der Klasse Applet sind. Die Klasse Applet ist ihrerseits eine Unterklasse von Panel.<br />

Applets sind also Panels, die innerhalb des Browser-Fensters (das eine Art von Frame<br />

ist) dargestellt werden.<br />

Ausgaben auf System.out oder System.err werden bei Web-Browsern in einem eigenen<br />

Bereich, der "<strong>Java</strong>-Console", ausgegeben, der den Benutzern meist nur auf Umwegen<br />

zuganglich ist; beim Appletviewer erscheinen sie in dem Terminal-Fenster, in<br />

dem der Appletviewer aufgerufen wird. Dies eignet sich also nur fur Test-Meldungen,<br />

aber nicht fur die normale Interaktion mit dem Benutzer. Diese sollte ausschlielich<br />

uber die graphische Benutzungsoberache (GUI) des Applet erfolgen.<br />

Bei der Deklaration von Applets mussen die Packages java.applet sowie java.awt<br />

und java.awt.event importiert werden.<br />

7.1 Sicherheit (security, sandbox, signed applets)<br />

Applets werden meist uber das Internet von einem Server geladen, und spezielle<br />

Sicherungen innerhalb des Web-Browser ("Sandkasten", sandbox) sorgen dafur, da<br />

sie keine unerwunschten Wirkungen auf den Client-Rechner haben konnen.<br />

So konnen Applets im allgemeinen<br />

nicht auf lokale Files zugreifen,<br />

nicht auf Systemkomponenten oder andere Programme zugreifen,<br />

keine Befehle oder Programme am Client starten,<br />

keine Internet-Verbindungen aufbauen auer zu dem einen Server, von dem<br />

das Applet geladen wurde.<br />

Bei signierten und zertizierten Applets (signed Applets) kann der Benutzer, wenn er<br />

sie fur vertrauenswurdig halt, auch Ausnahmen von den strengen Sicherheitsregeln<br />

zulassen. Er kann z.B. vereinbaren, da ein bestimmtes Applet auf ein bestimmtes<br />

File oder ein bestimmtes Subdirectory seiner Harddisk zugreifen darf (nur lesend,<br />

oder lesend und schreibend), oder da ein anderes Applet E-Mail an fremde Internet-<br />

Rechner senden darf.<br />

Wie man die Applets bzw. ein Archiv-File, in dem sie gespeichert sind, mit einer<br />

verschlusselten Unterschrift (Signatur) versieht, wie man diesen Schlussel von einer<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 89


vertrauenswurdigen Person oder Institution beglaubigen (zertizieren) lat, und wie<br />

das Applet dann den Benutzer bittet, da dieser die Erlaubnis fur die normalerweise<br />

verbotenen Aktionen erteilt, mu leider fur jeden Web-Browser anders gemacht werden.<br />

Genauere Informationen uber die Version von Sun (javakey) ndet man in der<br />

Online-Dokumentation von <strong>Java</strong>, die Informationen fur die Versionen von Netscape<br />

und Microsoft ndet man auf den Web-Servern dieser Firmen.<br />

Fur die Zertizierung von Applets innerhalb eines kleinen Benutzerkreises wie z.B.<br />

innerhalb des Intranet einer Firma braucht man keine weltweite Zertizierung, sondern<br />

es genugt eine Gruppen- bzw. Firmen-interne Beglaubigung der Signatur durch<br />

eine personlich bekannte vertrauenswurdige Person.<br />

Beim Testen von Applets in einem lokalen HTML-File mit dem Appletviewer sind<br />

nicht alle diese Einschrankungen aktiv. Zum Testen der Security-Einschrankungen<br />

empehlt sich die Angabe eines URL im Appletviewer oder die Verwendung eines<br />

Web-Browsers.<br />

7.2 HTML-Tags <br />

Innerhalb der Web-Page werden Applets mit dem HTML-Tag eingefugt<br />

und aufgerufen. Dies erfolgt nach dem folgenden Schema:<br />

<br />

<br />

Text<br />

<br />

Im Applet-Tag mu mit dem Parameter code der Name des <strong>Java</strong>-Applet angegeben<br />

werden (Class-File mit dem plattformunabhangigen Bytecode), und mit width und<br />

height die Breite und Hohe des Applet in Pixels.<br />

In diesem Fall mu sich das Class-File im selben Directory am selben Server wie das<br />

HTML-File benden. Wenn dies nicht der Fall ist, mu man mit einem zusatzlichen<br />

Parameter codebase den URL des Directory angeben, aus dem das Class-File geladen<br />

werden soll. Der URL (Uniform Resource Locator) gibt im allgemeinen das<br />

Protokoll, die Internet-Adresse des Servers und den Namen des Directory innerhalb<br />

des Servers an. Dieses Directory ist dann auch das Package, aus dem eventuell weitere<br />

Klassen geladen werden, und dieser Server ist derjenige, auf den das Applet<br />

uber das Internet zugreifen darf. Beispiel:<br />

<br />

Falls das Class-File kein einzelnes File ist sondern in einem komprimierten Archiv<br />

(ZIP- oder JAR-File) enthalten ist, ist der Name dieses Archiv-Files mit dem Parameter<br />

archive anzugeben:<br />

<br />

Mit einem oder mehreren Param-Tags konnen Parameter an das Applet ubergeben<br />

werden, die innerhalb des Applet mit der Methode getParameter abgefragt werden<br />

konnen. Ein Beispiel dafur folgt im Kapitel uber Parameter.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 90


Der (abgesehen von den Param-Tags) zwischen und stehende<br />

Text wird von den Browser-Versionen, die <strong>Java</strong> nicht unterstutzen, an Stelle des<br />

<strong>Java</strong>-Applet dargestellt. Dies kann beliebig formatierter HTML-Text sein, also z.B.<br />

auch Bilder enthalten.<br />

In der neuen HTML-Norm HTML 4.0 ist vorgesehen, da statt dem Tag <br />

der Tag verwendet werden soll. Dies wird aber von dem meisten Browsern<br />

noch nicht unterstutzt.<br />

Ausfuhrlichere Informationen uber Web-Pages und die Hypertext Markup Language<br />

HTML nden Sie in der HTML-Einfuhrung und in den Referenzen.<br />

<strong>Java</strong> Plug-in<br />

Als Alternative zu den in die Web-Browser integrierten <strong>Java</strong> Virtual Machines, die<br />

die neueste <strong>Java</strong>-Version meist noch nicht oder nur unvollstandig unterstutzen, bietet<br />

die Firma Sun ein "<strong>Java</strong> Plug-in" an (auch <strong>Java</strong> Activator genannt), das von den<br />

Benutzern kostenlos in den Internet-Explorer oder in den Netscape-Navigator unter<br />

MS-Windows oder Sun Solaris oder HP-UX eingebaut werden kann und dann die<br />

jeweils neueste Version des JDK voll unterstutzt. Bei Netscape Version 6, iPlanet<br />

und Mozilla ist dies sogar der Standard.<br />

Dazu genugt allerdings nicht die Installation der entsprechenden Software am Client,<br />

sondern es mu auch das HTML-File am Web-Server verandert werden: Je nach<br />

der Browser-Version mu der Aufruf des Applet in diesem Fall nicht mit <br />

sondern mit oder erfolgen. Wenn man als Autor einer Web-Page<br />

erreichen will, da die Web-Page mit allen Web-Browsern funktioniert, mu man<br />

dafur eine geeignete Kombination der HTML-Befehle , und <br />

angeben. Genauere Informationen daruber nden Sie on-line an der Adresse<br />

http://java.sun.com/products/plugin/<br />

7.3 Beispiel: einfaches HelloWorld Applet<br />

Um einen ersten Eindruck zu geben, wie ein Applet aussieht, hier das Gegenstuck<br />

zur primitiven Hello-World-Applikation aus dem ersten Teil dieser Kursunterlage.<br />

Eine Erklarung der darin vorkommenden Methoden folgt weiter unten.<br />

Applet (<strong>Java</strong>-Source)<br />

import java.awt.*;<br />

import java.applet.*;<br />

public class HelloApp extends Applet {<br />

}<br />

private String s = "Hello World!";<br />

public void paint (Graphics g) {<br />

g.drawString (s, 25, 25);<br />

}<br />

Dieses <strong>Java</strong>-Programm mu in einem File mit dem Filenamen HelloApp.java stehen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 91


Web-Page (HTML-File)<br />

Ein einfaches HTML-File, das dieses Applet enthalt, konnte so aussehen:<br />

<br />

<br />

Example<br />

<br />

<br />

Example<br />

<br />

<br />

Hello World!<br />

<br />

<br />

<br />

<br />

Fur Tests mit dem Appletviewer genugt die folgende Minimalversion:<br />

<br />

<br />

<br />

<br />

Wenn dieses HTML-File den Filenamen hello.html hat, dann erfolgen Compilation<br />

und Ausfuhrung des Applet mit den folgenden Befehlen:<br />

javac HelloApp.java<br />

appletviewer hello.html<br />

Wenn Sie sehen wollen, wie das Applet funktioniert, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

7.4 Ubung: einfaches HelloWorld Applet<br />

Schreiben Sie das oben angefuhrte HelloWorld-Applet (oder eine Variante davon mit<br />

einem anderen Text) und ein entsprechendes HTML-File, ubersetzen Sie das Applet<br />

und rufen es mit dem Appletviewer auf.<br />

Falls Sie einen <strong>Java</strong>-fahigen Web-Browser zur Verfugung haben, probieren Sie auch<br />

aus, ob dieser Ihr Applet richtig verarbeiten kann.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 92


7.5 Methoden init, start, stop<br />

7.6 Groenangabe<br />

Analog zur main-Methode von Applikationen werden in Applets die folgenden Methoden<br />

automatisch ausgefuhrt:<br />

public void init()<br />

public void start()<br />

public void stop()<br />

Die Methode init wird ausgefuhrt, wenn die Web-Page und das Applet geladen<br />

werden.<br />

Die Methode start wird immer dann ausgefuhrt, wenn die Web-Page mit dem Applet<br />

im Browser sichtbar gemacht wird, also sowohl beim ersten Laden als auch bei<br />

jeder Ruckkehr in die Seite (z.B. mit dem Back-Button des Browsers, wenn man<br />

inzwischen eine andere Web-Page angesehen hat).<br />

Die Methode stop wird immer dann ausgefuhrt, wenn die Web-Page verlassen wird,<br />

also beim Anklicken einer anderen Web-Page oder beim Beenden des Web-Browsers.<br />

Im allgemeinen gibt man in der init-Methode alles an, was zur Vorbereitung des<br />

Applet und zum Aufbau der graphischen Benutzungsoberache (GUI) dient. In<br />

der start-Methode werden dann eventuelle Aktionen wie z.B. selbstandig laufende<br />

Threads gestartet. In der stop-Methode mussen diese Aktionen (Threads und dergleichen)<br />

gestoppt werden.<br />

Da das Laden und Starten des Applet ohnehin immer eine langere Wartezeit mit sich<br />

bringt, wird empfohlen, alle wahrend der Interaktion mit dem Benutzer benotigten<br />

weiteren Klassen sowie Bilder, Tone, Datenles etc. so weit wie moglich und sinnvoll<br />

schon bei der Initialisierung des Applet uber das Internet zu laden (also in der init-<br />

Methode), damit die interaktive Arbeit mit dem Benutzer dann zugig ablaufen kann<br />

und nicht durch neuerliche Wartezeiten fur das nachtragliche Laden solcher Files<br />

verzogert bzw. unterbrochen wird.<br />

Die Groe des Applet wird nicht innerhalb des Applet mit setSize, getPreferred-<br />

Size oder dergleichen angegeben, sondern mit den Parametern width und height im<br />

Applet-Tag im HTML-File.<br />

In den width- und height-Parametern von konnen nicht nur Pixel-Angaben<br />

sondern auch Prozent-Angaben stehen, dann kann der Benutzer die Groe des Applet<br />

verandern.<br />

Innerhalb des <strong>Java</strong>-Programms kann man die aktuelle Groe des Applet mit der<br />

Methode getSize() abfragen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 93


7.7 Beenden des Applet<br />

Bei Applikationen mit graphischen User-Interfaces ist meist ein Close- oder Exit-<br />

Button notwendig, um die Applikation zu beenden.<br />

Bei Applets ist ein Close- oder Exit-Button im allgemeinen nicht sinnvoll. Das Applet<br />

wird vom Benutzer einfach dadurch beendet, da er die Web-Page verlat oder<br />

den Web-Browser (mit Close oder Exit in seinem File-Menu) beendet.<br />

In Applets soll daher auch kein System.exit ausgefuhrt werden, d.h. das Applet<br />

darf den Web-Browser nicht "abschieen".<br />

7.8 Beispiel: typischer Aufbau eines Applet mit Button-Aktionen<br />

import java.applet.*;<br />

import java.awt.*;<br />

import java.awt.event.*;<br />

public class ButtonTest extends Applet<br />

implements ActionListener {<br />

}<br />

private Button b1, b2;<br />

private Label mess;<br />

public void init() {<br />

setLayout (new FlowLayout() );<br />

b1 = new Button("B1");<br />

b1.addActionListener (this);<br />

add(b1);<br />

b2 = new Button("B2");<br />

b2.addActionListener (this);<br />

add(b2);<br />

mess = new Label("Nothing was pressed.");<br />

add(mess);<br />

setVisible(true);<br />

}<br />

public void actionPerformed (ActionEvent e) {<br />

String s = e.getActionCommand();<br />

if (s.equals("B1")) {<br />

mess.setText("The first button was pressed.");<br />

}<br />

else<br />

if (s.equals("B2")) {<br />

mess.setText("The second button was pressed.");<br />

}<br />

this.validate();<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 94


Hier das zugehorige minimale HTML-File, mit der Angabe der Groe des Applet:<br />

<br />

<br />

<br />

<br />

Wenn Sie wissen wollen, was dieses Applet tut, probieren Sie es einfach aus (in Ihrem<br />

Browser, wenn er das kann, oder Abschreibubung oder Download).<br />

7.9 Beispiel: typischer Aufbau eines Applet mit Maus-Aktionen<br />

import java.applet.*;<br />

import java.awt.*;<br />

import java.awt.event.*;<br />

public class MouseTest extends Applet<br />

implements MouseListener, MouseMotionListener {<br />

private int mouseX, mouseY;<br />

private int radius, diameter = 20;<br />

private Color circleColor = Color.red;<br />

public void init() {<br />

Dimension full = getSize();<br />

mouseX = full.width/2;<br />

mouseY = full.height/2;<br />

radius=diameter/2;<br />

addMouseListener(this);<br />

addMouseMotionListener(this);<br />

}<br />

public void paint (Graphics g) {<br />

g.setColor (circleColor);<br />

g.fillOval ((mouseX-radius), (mouseY-radius),<br />

diameter, diameter);<br />

}<br />

public void mousePressed (MouseEvent e) {<br />

mouseX = e.getX();<br />

mouseY = e.getY();<br />

circleColor = Color.green;<br />

repaint();<br />

}<br />

public void mouseReleased (MouseEvent e) {<br />

mouseX = e.getX();<br />

mouseY = e.getY();<br />

circleColor = Color.red;<br />

repaint();<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 95


public void mouseClicked (MouseEvent e) { }<br />

public void mouseEntered (MouseEvent e) { }<br />

public void mouseExited (MouseEvent e) { }<br />

public void mouseDragged (MouseEvent e) {<br />

mouseX = e.getX();<br />

mouseY = e.getY();<br />

circleColor = Color.green;<br />

repaint();<br />

}<br />

public void mouseMoved (MouseEvent e) { }<br />

}<br />

Wenn Sie wissen wollen, was dieses Applet tut, probieren Sie es einfach aus (in Ihrem<br />

Browser, wenn er das kann, oder Abschreibubung oder Download).<br />

7.10 Beispiel: typischer Aufbau eines Applet mit Text-Eingaben<br />

import java.applet.*;<br />

import java.awt.*;<br />

import java.awt.event.*;<br />

public class TextTest extends Applet<br />

implements ActionListener {<br />

private TextField field1, field2;<br />

public void init() {<br />

setLayout (new FlowLayout() );<br />

field1 = new TextField("", 30);<br />

field1.addActionListener(this);<br />

add(field1);<br />

field2 = new TextField("", 30);<br />

field2.addActionListener(this);<br />

add(field2);<br />

Label helpText = new Label ("Enter text and hit return.");<br />

add(helpText);<br />

setVisible(true);<br />

}<br />

public void actionPerformed (ActionEvent e) {<br />

String s = null;<br />

Object which = e.getSource();<br />

if (which==field1) {<br />

s = field1.getText();<br />

field2.setText(s);<br />

field1.setText("");<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 96


}<br />

}<br />

else<br />

if (which==field2) {<br />

s = field2.getText();<br />

field1.setText(s);<br />

field2.setText("");<br />

}<br />

Wenn Sie wissen wollen, was dieses Applet tut, probieren Sie es einfach aus (in Ihrem<br />

Browser, wenn er das kann, oder Abschreibubung oder Download).<br />

7.11 Ubung: einfaches Applet Thermostat<br />

Schreiben Sie ein Applet, das folgende Daten und Steuerelemente darstellt und die<br />

folgenden Aktionen ausfuhrt:<br />

Im oberen Teil soll in der Mitte die Temperatur angezeigt werden.<br />

Im unteren Teil sollen 2 Buttons nebeneinander zu sehen sein, die den Wert<br />

der Temperatur um 1 verringern oder erhohen.<br />

Als Erweiterung konnen Sie die Anzeige farbig gestalten, und zwar je nach dem<br />

erreichten Temperaturbereich in verschiedenen Farben.<br />

Wenn Sie sehen wollen, wie das aussehen konnte, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

Fur das Grundgerust dieses Applet konnen Sie Teile der Ubung aus dem Kapitel<br />

uber Graphical User-Interfaces verwenden.<br />

Fuhren Sie dieses Applet mit einem minimalen HTML-File im Appletviewer aus<br />

und testen Sie auch, was passiert, wenn Sie das Fenster vergroern oder verkleinern.<br />

Falls Ihnen dieses Beispiel zu einfach ist und Sie mehr Zeit investieren wollen, konnen<br />

Sie auch eines oder mehrere der folgenden, aufwendigeren Beispiele ausprobieren.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 97


7.12 Ubung: Applet einfache Verkehrsampel<br />

Schreiben Sie ein Applet, das folgende Elemente darstellt und folgende Aktionen<br />

ausfuhrt:<br />

Am oberen Rand soll in der Mitte der Text "Trac Light Exercise" stehen.<br />

Im mittleren Bereich soll ein einfaches rechteckiges Bild einer Verkehrsampel<br />

zu sehen sein, ein schwarzes Rechteck mit bunten Kreisen, reihum in jeweils<br />

einem der folgenden 4 Zustande:<br />

1. rot<br />

2. rot + gelb<br />

3. grun<br />

4. gelb<br />

(Auf grunes oder gelbes Blinklicht verzichten wir in dieser Ubung, siehe die<br />

Ubung im Kapitel uber Threads)<br />

Am unteren Rand sollen 2 Buttons zu sehen sein:<br />

{ ein Next-Button, der ein Weiterspringen der Verkehrsampel auf den jeweils<br />

nachsten Zustand bewirkt, und<br />

{ ein Stop-Button, der die Ampel auf rot stellt.<br />

Wenn Sie sehen wollen, wie das aussehen konnte, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

Fuhren Sie dieses Applet mit einem minimalen HTML-File im Appletviewer aus<br />

und testen Sie auch, was passiert, wenn Sie das Fenster vergroern oder verkleinern.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 98


7.13 Ubung: komplexes Applet Sparbuch<br />

Erweitern Sie das einfache Rechenbeispiel Sparbuch aus dem Kapitel Syntax und<br />

Statements bzw. dessen Erweiterung aus dem Kapitel Exceptions zu einem Applet<br />

mit graphischem User-Interface.<br />

Uberlegen Sie zunachst die zu Grunde liegenden Daten (Model): Geldbetrag, Zinssatz,<br />

und der Wert in jedem Jahr.<br />

Uberlegen Sie dann die graphische Darstellung (View):<br />

Oben sollen Eingabefelder fur Geldbetrag und Zinssatz sowie Textbereiche fur<br />

Erklarungen und Fehlermeldungen vorhanden sein.<br />

Unten soll eine Ubersicht uber die Wertentwicklung in den 10 Jahren sowohl<br />

in Form einer Tabelle (Zahlenangaben) als auch in Form eines Diagramms<br />

(graphisch) erscheinen.<br />

Uberlegen Sie schlielich die Steuerung (Controller): Wenn der Benutzer einen<br />

neuen Geldbetrag oder Zinssatz eingibt, sollen sofort die entsprechenden Werte sichtbar<br />

werden (oder eine Fehlermeldung, wenn die Eingabe ungultig war).<br />

Wenn Sie sehen wollen, wie das aussehen konnte, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

Fuhren Sie dieses Applet mit einem minimalen HTML-File im Appletviewer aus<br />

und testen Sie auch, was passiert, wenn Sie das Fenster vergroern oder verkleinern.<br />

7.14 Ubung: komplexes Applet: Baume im Garten<br />

Uberlegen, entwerfen und schreiben Sie ein Applet, das folgende Elemente darstellt<br />

und folgende Aktionen ausfuhrt:<br />

Am oberen Rand soll in der Mitte eine Uberschrift stehen.<br />

Im linken Hauptbereich soll der Grundri eines Gartens zu sehen sein, zunachst<br />

ohne Baume, dann mit Kreisen fur die gepanzten Baume. Mit Mausklicks<br />

oder Mausdrags kann der Benutzer hier Stellen fur das geplante Panzen eines<br />

Baumes auswahlen.<br />

Im rechten Hauptbereich soll ein einfaches buntes Bild des Gartens im Aufri<br />

zu sehen sein, mit allen gepanzten Baumen.<br />

Der untere Bereich soll aus einem Textbereich und einem Buttonbereich bestehen.<br />

Der Textbereich soll kurze Texte (Anleitungen, Hinweise und Fehlermeldungen)<br />

fur die Benutzerfuhrung enthalten, je nach den Aktionen des Benutzers.<br />

Darunter sollen 3 Buttons zu sehen sein:<br />

{ ein Okay-Button, der den Baum an der vom Benutzer ausgewahlten Stelle<br />

panzt, wenn es eine erlaubte Stelle war.<br />

{ ein Undo-Button, mit dem der gerade geplante bzw. der zuletzt gepanzte<br />

Baum entfernt wird (bei mehrmaliger Verwendung bis zum Anfangszustand<br />

zuruck).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 99


{ ein Empty-Button, der den Anfangszustand (Garten ohne Baume) wieder<br />

herstellt.<br />

Fuhren Sie dieses Applet mit einem minimalen HTML-File im Appletviewer aus<br />

und testen Sie alle vorgesehenen Aktionen.<br />

Wenn Sie sehen wollen, wie das aussehen konnte, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

7.15 Vermeidung von Flimmern oder Flackern (buered image)<br />

Wenn die paint-Methode eine langere Rechnerzeit benotigt, kann beim Aufruf der<br />

repaint-Methode ein storendes Flimmern oder Flackern entstehen. Dies hat folgende<br />

Grunde:<br />

Die repaint-Methode ruft intern die update-Methode auf. Diese loscht zunachst den<br />

bisherigen Inhalt der Komponente (clear screen), indem sie die Flache mit der Hintergrundfarbe<br />

fullt, und ruft dann die paint-Methode auf, die die Graphik-Ausgabe<br />

bewirkt. Wenn der ganze Vorgang langer als etwa 1/20 Sekunde betragt, wird er als<br />

Flimmern oder Flackern wahrgenommen.<br />

Dieses storende Flimmern oder Flackern kann auf die folgende Weise vermieden<br />

werden:<br />

1. Man macht die zeitaufwendige Berechnung des neuen Bildes nicht in der paint-<br />

Methode sondern in einer eigenen Methode in einem eigenen Image-Objekt<br />

(Puerbild, buered image), und deniert die paint-Methode so, da sie nur<br />

das fertig aufbereitete Bild ausgibt.<br />

2. Man deniert die update-Methode so, da sie nur die paint-Methode aufruft,<br />

ohne vorheriges Clear-Screen, das in diesem Fall auch nicht notig ware, weil<br />

von der paint-Methode ohnehin die gesamte Flache neu gezeichnet wird.<br />

Dies erfolgt nach dem folgenden Schema:<br />

In der Klasse (die im allgemeinen eine Subklasse von Canvas oder Applet ist) werden<br />

globale Datenfelder fur das Puerbild und die darin enthaltene Graphik angelegt:<br />

private Image img;<br />

private Graphics g;<br />

In der init-Methode werden die Bild- und Graphik-Objekte mit der richtigen Groe<br />

angelegt:<br />

Dimension d = getSize();<br />

img = createImage (d.width, d.height);<br />

g = img.getGraphics();<br />

Das globale Graphik-Objekt kann nun in beliebigen Methoden der Klasse bearbeitet<br />

werden, und mit repaint kann dann die Ausgabe bewirkt werden:<br />

g.setColor (...);<br />

g.draw... (...);<br />

g.fill... (...);<br />

repaint();<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 100


Die paint-Methode wird so deniert, da sie nur das globale Puerbild in ihren<br />

Graphik-Parameter ausgibt, und zwar in diesem Fall ohne Image-Observer (null als<br />

4. Parameter):<br />

public void paint (Graphics g) {<br />

if (img != null)<br />

g.drawImage (img, 0, 0, null);<br />

}<br />

Die update-Methode wird so deniert, da sie nur die paint-Methode aufruft:<br />

public void update (Graphics g) {<br />

paint(g); // no clear<br />

}<br />

7.16 Uniform Resource Locators (URL)<br />

Die Klasse URL im Paket java.net beschreibt Netz-Adressen (Uniform Resource<br />

Locator). Applets konnen im allgemeinen nur Files und Directories auf dem Server<br />

ansprechen, vom dem sie geladen wurden. Zu diesem Zweck konnen die folgenden<br />

Methoden verwendet werden:<br />

URL getCodeBase()<br />

fur die Adresse bzw. das Directory, aus dem das Applet (Class-File) geladen<br />

wurde. Dies ist das Package, aus dem eventuell andere Klassen geladen werden,<br />

und dies gibt den Server an, den das Applet uber das Internet ansprechen darf.<br />

URL getDocumentBase()<br />

fur die Adresse bzw. das Directory, aus dem die Web-Page (das HTML-File),<br />

die das Applet enthalt, geladen wurde. Dies kann ein anderes Directory oder<br />

ein anderer Server als bei getCodeBase sein.<br />

Wie man ein Daten- oder Text-File vom Web-Server lesen kann, wird im Kapitel<br />

uber Ein-Ausgabe beschrieben. Hier folgen Hinweise zum Laden von Bildern und<br />

Tonen und dergleichen vom Web-Server.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 101


7.17 Bilder (Image, MediaTracker)<br />

Bilder konnen mit getImage vom Web-Server geladen und dann mit drawImage im<br />

Applet oder in einem Canvas innerhalb des Applet dargestellt werden. Die allgemeinen<br />

unterstutzten Bildformate sind GIF und JPEG.<br />

Methode im Applet-Objekt:<br />

Image getImage (URL directory, URL filename)<br />

Methoden im Image-Objekt:<br />

int getWidth(this)<br />

int getHeight(this)<br />

Methode im Graphics-Objekt:<br />

drawImage (Image, int x1, int y1, this)<br />

Beispielskizze:<br />

Image logo;<br />

public void init() {<br />

logo = getImage( getDocumentBase(), "logo.gif");<br />

}<br />

public void paint (Graphics g) {<br />

if (logo != null)<br />

g.drawImage (logo, 25, 25, null);<br />

}<br />

Die Methode getImage startet nur das Laden des Bildes. Der Ladevorgang uber<br />

das Internet kann langere Zeit dauern. Wenn man abwarten will, bis der Ladevorgang<br />

erfolgreich abgeschlossen ist, mu man ein Objekt der Klasse MediaTracker<br />

verwenden.<br />

Dies ist zum Beispiel dann notwendig, wenn man mit getWidth und getHeight die<br />

Groe des Bildes abfragen will, denn diese Werte sind erst dann verfugbar, wenn<br />

das Bild fertig geladen wurde.<br />

Beispiel:<br />

Image img;<br />

int imgWidth, imgHeight;<br />

public void init() {<br />

MediaTracker mt = new MediaTracker(this);<br />

img = getImage( getDocumentBase(), "img.jpg");<br />

mt.addImage (img, 0);<br />

try {<br />

mt.waitForID(0);<br />

imgWidth = img.getWidth(this);<br />

imgHeight = img.getHeight(this);<br />

...<br />

} catch (InterruptedException e) {<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 102


}<br />

System.out.println("Image not loaded.");<br />

}<br />

In Applikationen kann man Bilder analog mit<br />

x.getToolkit().getImage(...)<br />

(wobei x irgendeine AWT-Komponenente ist) oder mit<br />

Toolkit.getDefaultToolkit().getImage(...)<br />

laden.<br />

7.18 Tone (sound, AudioClip)<br />

Tone (Audio-Clips) konnen mit getAudioClip vom Web-Server geladen und mit<br />

den Methoden play, loop und stop abgespielt werden. Bis JDK 1.1 wird nur das<br />

Audio-Clip-Format (File-Extension .au) unterstutzt, ab JDK 1.2 auch andere Audio-<br />

Formate wie MIDI und WAV und auch Video-Clips (<strong>Java</strong> Media Framewortk JMF).<br />

Methode im Applet-Objekt:<br />

AudioClip getAudioClip (URL directory, URL filename)<br />

Methoden im AudioClip-Objekt:<br />

play()<br />

loop()<br />

stop()<br />

Beispielskizze fur ein einmaliges Abspielen beim Starten des Applet:<br />

AudioClip sayHello;<br />

public void init() {<br />

sayHello = getAudioClip( getDocumentBase(), "hello.au");<br />

sayHello.play();<br />

}<br />

Beispielskizze fur eine standige Wiederholung bis zum Verlassen des Applet:<br />

AudioClip music;<br />

public void init() {<br />

music = getAudioClip( getDocumentBase(), "music.au");<br />

}<br />

public void start() {<br />

music.loop();<br />

}<br />

public void stop() {<br />

music.stop();<br />

}<br />

Fur das Abspielen von AudioClips "im Hintergrund" zugleich mit anderen Aktionen<br />

verwendet man eigene Threads.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 103


7.19 Parameter<br />

Ahnlich wie die Laufzeit-Parameter beim Starten einer Applikation mit java, konnen<br />

mit dem -Tag in der Web-Page Parameter an das Applet ubergeben werden.<br />

Jeder Parameter hat einen Namen und einen Wert:<br />

<br />

Innerhalb des Applet konnen die Parameter mit der Methode getParameter abgefragt<br />

werden. Die in HTML-Tags angegebenen Werte sind immer Strings. Die Umwandlung<br />

von Ziernfolgen in Zahlen etc. mu innerhalb des <strong>Java</strong>-Applet erfolgen.<br />

Bei Namen in HTML-Tags wird meist nicht zwischen Gro- und Kleinbuchstaben<br />

unterschieden, es wird daher empfohlen, die Namen nur mit Kleinbuchstaben zu<br />

vereinbaren.<br />

Beispiel:<br />

<br />

<br />

<br />

<br />

<br />

<br />

import java.applet.*;<br />

public class ParamTest extends Applet {<br />

String firstname = null;<br />

int age = 0;<br />

public void init() {<br />

try {<br />

firstname = getParameter ("firstname");<br />

String ageString = getParameter ("age");<br />

age = Integer.parseInt(ageString);<br />

} catch (Exception e) {<br />

}<br />

if (age < 18) {<br />

System.out.println(name + ", you are too young!");<br />

}<br />

... // do something<br />

}<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 104


7.20 Web-Browser<br />

AppletContext<br />

Web-Pages, Mail, News<br />

Der Web-Browser, der das Applet geladen hat und darstellt, kann mit der Methode<br />

getAppletContext verfugbar gemacht werden. Dann kann man mit getApplets und<br />

getApplet auf die anderen, in derselben Web-Page enthaltenen Applets zugreifen,<br />

oder den Web-Browser mit der Methode showDocument bitten, eine andere Web-<br />

Page zu laden und darzustellen.<br />

Methode im Applet-Objekt:<br />

AppletContext getAppletContext()<br />

Methoden im AppletContext-Objekt:<br />

Enumeration getApplets()<br />

Applet getApplet (String appletName)<br />

showDocument (URL)<br />

showDocument (URL, String target)<br />

Wenn showDocument mit nur einem Parameter aufgerufen wird, wird die aktuelle<br />

Web-Page (die das Applet enthalt) durch eine neue Web-Page ersetzt.<br />

Wenn showDocument mit zwei Parametern aufgerufen wird, wird die neue Web-<br />

Page in dem angegebenen Target-Frame dargestellt. Dies eignet sich z.B. fur die<br />

Darstellung von Hilfe-Texten zum Applet in einem eigenen Frame (oder Browser-<br />

Fenster) mit dem Targetnamen "help".<br />

Wenn der URL nicht mit http: oder ftp: sondern mit mailto: oder news: beginnt,<br />

wird das Mail- bzw. News-Fenster des Web-Browsers mit der angegebenen Mail-<br />

Adresse bzw. Newsgruppe geonet, und der Benutzer kann eine E-Mail absenden<br />

bzw. eine Newsgruppe lesen.<br />

Im allen Fallen hangt es vom Web-Browser ab, ob und wie er das alles unterstutzt.<br />

Beispielskizze:<br />

URL newPage = null;<br />

AppletContext browser = getAppletContext();<br />

try {<br />

newPage = new URL (getDocumentBase(), "xxx.html");<br />

browser.showDocument (newPage);<br />

} catch (Exception e {<br />

}<br />

Zugri auf andere Applets<br />

Wenn die Web-Page mehrere Applets enthalt, etwa in der Form<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 105


Zugri auf <strong>Java</strong>Script<br />

<br />

<br />

...<br />

<br />

<br />

dann kann man innerhalb des Applet a1 nach folgendem Schema auf Felder xxxx<br />

und Methoden yyyy das Applet a2 zugreifen:<br />

AppletContext browser = getAppletContext();<br />

Applet2 otherApplet = (Applet2) browser.getApplet("a2");<br />

x = otherApplet.xxxx;<br />

otherApplet.yyyy();<br />

otherApplet.xxxx.yyyy();<br />

In dieser Skizze fehlt noch die Fehlerbehandlung, z.B. ob das andere Applet in der<br />

Web-Page gefunden wurde.<br />

Wenn ein Web-Browser sowohl <strong>Java</strong> als auch <strong>Java</strong>Script unterstutzt, dann kann<br />

man auch zwischen <strong>Java</strong>-Applets und <strong>Java</strong>Script-Scripts Daten und Informationen<br />

austauschen:<br />

Innerhalb von <strong>Java</strong>Script kann man public Methoden und Felder von <strong>Java</strong>-Applets<br />

in der Form<br />

document.appletname.feldname<br />

bzw.<br />

document.appletname.methodenaufruf<br />

ansprechen.<br />

Innerhalb von <strong>Java</strong>-Applets kann man <strong>Java</strong>Script-Funktionen aufrufen, wenn man<br />

die Klasse JSObject aus dem Package netscape.javascript (von Netscape) verwendet<br />

und im -Tag den Parameter mayscript angibt. Beispielskizze:<br />

import netscape.javascript.*;<br />

...<br />

String[] somehtml = {<br />

"Hello!",<br />

"Some <strong>Java</strong>-generated hypertext ..."<br />

};<br />

JSObject w = JSObject.getWindow(this);<br />

w.eval("w1 = window.open ('','windowname','')");<br />

w.call("w1.document.write", somehtml);<br />

w.eval("w1.document.close()");<br />

Achtung! <strong>Java</strong>Script wird nicht von allen Web-Browsern unterstutzt, und viele Benutzer<br />

haben <strong>Java</strong>Script wegen des damit verbundenen Sicherheitsrisikos in ihren<br />

Browser-Optionen ausgeschaltet. <strong>Java</strong>Script eignet sich daher nicht fur allgemein<br />

verwendbare Applets uber das Internet sondern nur fur Spezialfalle innerhalb eines<br />

Intranet.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 106


7.21 Ubung: Zwei Applets<br />

Schreiben Sie eine Web-Page mit zwei Applets:<br />

ein Resultat-Applet, das einen Text anzeigt, und<br />

ein Steuerungs-Applet, in dem der Benutzer einen Text eingibt, der dann im<br />

anderen Applet angezeigt wird.<br />

7.22 Applet-Dokumentation<br />

Um den Benutzern die richtige Verwendung eines Applet zu erleichtern, sollten die<br />

folgenden Hilfsmittel verwendet werden:<br />

spezielle Kommentare, aus denen mit <strong>Java</strong>doc die Dokumentation des <strong>Java</strong>-<br />

Programms erstellt wird, und<br />

die Methoden getAppletInfo() und getParameterInfo() im Applet, deren Ergebnisse<br />

von manchen Web-Browsern (z.B. dem Appletviewer) beim Anklicken<br />

von "Eigenschaften" oder "Info" angezeigt werden.<br />

Beispiel:<br />

import java.awt.*;<br />

import java.applet.*;<br />

/**<br />

* an example for an Applet with javadoc documentation,<br />

* Applet info, und parameter info.<br />

* @since JDK 1.0<br />

*/<br />

public class AppletDoc extends Applet {<br />

String text;<br />

int fontSize;<br />

Font f;<br />

public void init () {<br />

text = getParameter("text");<br />

if (text == null)<br />

text = "Hello World!";<br />

try {<br />

fontSize = Integer.parseInt (<br />

getParameter("fontsize").trim() );<br />

} catch (Exception e) {<br />

fontSize = 12;<br />

}<br />

f = new Font ("Helvetica", Font.BOLD, fontSize);<br />

}<br />

public void paint (Graphics g) {<br />

g.setFont (f);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 107


}<br />

g.drawString (text, 25, 50);<br />

}<br />

public String getAppletInfo() {<br />

String s =<br />

"AppletDoc = Hello World Applet with parameters";<br />

return s;<br />

}<br />

public String[][] getParameterInfo() {<br />

String[][] s = {<br />

{ "text", "String", "Text to be displayed" },<br />

{ "fontsize", "Integer", "Font size in points" }<br />

};<br />

return s;<br />

}<br />

7.23 Doppelnutzung als Applet und Applikation<br />

Man kann ein <strong>Java</strong>-Programm auch so schreiben, da es sowohl als Applet innerhalb<br />

einer Web-Page als auch als lokale Applikation ausgefuhrt werden kann. Zu diesem<br />

Zweck mu das Programm<br />

eine Subklasse von Applet sein und<br />

eine main-Methode enthalten.<br />

Die main-Methode wird nur bei Aufruf als Applikation ausgefuhrt und im Applet<br />

ignoriert. Sie mu ein Frame (als Ersatz fur das Fenster des Web-Browsers) erzeugen<br />

und in diesem ein Objekt des Applet einfugen und dann die init- und start-Methoden<br />

des Applet aufrufen, die den Inhalt des Applet darstellen.<br />

Auerdem sollte ein WindowListener implementiert werden, der beim Schlieen des<br />

Frame die Applikation beendet (analog zum Schlieen des Web-Browsers).<br />

Falls das Applet eine stop-Methode enthalt, mu diese von der Applikation vor deren<br />

Beendigung aufgerufen werden.<br />

Beispiel:<br />

import java.awt.*;<br />

import java.awt.event.*;<br />

import java.applet.*;<br />

public class AppApp extends Applet<br />

implements WindowListener {<br />

public void init() {<br />

setLayout( new FlowLayout() );<br />

Label hello = new Label("Hello World!");<br />

add(hello);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 108


}<br />

}<br />

// add more content ...<br />

setVisible(true);<br />

public static void main (String[] args) {<br />

AppApp a = new AppApp();<br />

Frame f = new Frame("AppApp");<br />

}<br />

f.setLayout( new BorderLayout() );<br />

a.init();<br />

f.add (a, "Center");<br />

f.setSize(300,200);<br />

f.addWindowListener( a );<br />

f.setVisible(true);<br />

a.start();<br />

public void windowClosing (WindowEvent e) {<br />

this.stop();<br />

System.exit(0);<br />

}<br />

public void windowClosed (WindowEvent e) { }<br />

public void windowOpened (WindowEvent e) { }<br />

public void windowIconified (WindowEvent e) { }<br />

public void windowDeiconified (WindowEvent e) { }<br />

public void windowActivated (WindowEvent e) { }<br />

public void windowDeactivated (WindowEvent e) { }<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 109


8. Threads<br />

Programmfaden<br />

mehrere Aktionen parallel<br />

8.1 Multithreading, Thread, Runnable<br />

Threads ("Faden") sind Programmteile, die parallel, also unabhangig voneinander,<br />

mehr oder weniger gleichzeitig ablaufen.<br />

Es gibt Threads, die von der <strong>Java</strong> Virtual Machine automatisch erzeugt werden, z.B.<br />

fur das Event-Handling und den Garbage-Collector. Fur die Aufspaltung eigener<br />

Programme in mehrere Threads dienen die folgenden beiden Objekte:<br />

die Klasse Thread fur die Steuerung von Threads (starten und beenden),<br />

das Interface Runnable, mit dem das innerhalb des Thread laufende Programm<br />

implementiert wird.<br />

Das Programm, das innerhalb des Thread lauft, mu das Interface Runnable implementieren<br />

und eine Methode mit der Signature<br />

public void run()<br />

enthalten, die dann innerhalb des Thread ausgefuhrt wird.<br />

Beispiel:<br />

public class MyProgram implements Runnable {<br />

public void run() {<br />

System.out.println("Hello World!");<br />

}<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 110


8.2 Starten eines Thread (start)<br />

Konstruktor:<br />

new Thread (Runnable)<br />

Der Parameter gibt an, welches Programm innerhalb des Thread laufen soll (siehe<br />

oben).<br />

Das Starten des Thread erfolgt mit der Methode<br />

start()<br />

Damit wird die run-Methode des Runnable-Objekts gestartet.<br />

Beispielskizze:<br />

Thread t;<br />

Runnable theProgram = new MyProgram();<br />

t = new Thread (theProgram);<br />

t.start();<br />

Der Zusammenhang zwischen Runnable-Objekt und Thread-Objekt ist ahnlich<br />

wie zwischen einem Auto und seinem Lenker:<br />

Das Runnable-Objekt entspricht dem Auto.<br />

das Thread-Objekt entspricht dem Lenker, der das Auto steuert.<br />

Jedes Auto mu von einer Person gelenkt werden, und jede Person kann nur<br />

ein Auto lenken.<br />

Der Konstruktor des Thread-Objekts entspricht der Ubergabe des Autoschlussels<br />

an den Lenker: Damit wird festgelegt, welches Auto er lenken<br />

soll.<br />

Die start-Methode entspricht dem Starten mit dem Startschlussel, die run-<br />

Methode entspricht dem Laufen des Motors: Der Lenker dreht den Startschlussel,<br />

und das bewirkt, da der Motor zu laufen beginnt.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 111


8.3 Beenden oder Abbrechen eines Thread<br />

Der Thread lauft selbstandig (also unabhangig von dem Thread, der ihn gestartet<br />

hat, siehe auch unten) und endet automatisch, wenn das Ende der run-Methode<br />

erreicht wird.<br />

Falls die Aktionen des Thread eine langere Ausfuhrungszeit benotigen oder in einer<br />

Schleife wiederholt werden, mu man eine Moglichkeit vorsehen, den Thread "von<br />

auen" zu beenden oder abzubrechen.<br />

Dazu verwendet man am besten ein boolean Datenfeld, das von auen gesetzt werden<br />

kann und innerhalb des Runnable-Objekts abgefragt wird.<br />

Beispielskizze:<br />

Thread t;<br />

MyProgram myProg = new MyProgram();<br />

t = new Thread (myProg);<br />

t.start();<br />

...<br />

myProg.setRunFlag(false);<br />

public class MyProgram implements Runnable {<br />

private boolean runFlag;<br />

public void setRunFlag (boolean runFlag) {<br />

this.runFlag = runFlag;<br />

}<br />

public boolean getRunFlag() {<br />

return this.runFlag;<br />

}<br />

public void run() {<br />

runFlag=true;<br />

while (runFlag) {<br />

// do something<br />

}<br />

}<br />

}<br />

Es gibt auch Methoden stop(), interrupt(), suspend() und resume() fur das Beenden,<br />

Abbrechen oder Unterbrechen eines Thread. Die Verwendung dieser Methoden<br />

wird jedoch nicht empfohlen ("deprecated" ab JDK 1.2), weil es dabei entweder zu<br />

Deadlock-Situationen oder zu unvollstandig ausgefuhrten Aktionen und damit zu<br />

ungultigen Objekt- oder Datenzustanden kommen kann.<br />

Beispiel: Wenn ein Thread, der mehrere zusammengehorige Daten in eine oder mehrere<br />

Files oder Datenbanken schreiben will, mit einer dieser Methoden abgebrochen<br />

wird, so kann es passieren, da nur ein Teil der neuen Daten abgespeichert wird und<br />

damit ein ungultiger, inkonsistenter Datenzustand entsteht.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 112


8.4 Unterbrechungen (sleep)<br />

Man kann nicht davon ausgehen, da die Rechenzeit "gerecht" auf alle parallel<br />

laufenden Threads aufgeteilt wird. Es kann durchaus passieren, da ein Thread alle<br />

Betriebsmittel fur sich verbraucht und alle anderen Threads dadurch aufgehalten<br />

werden und untatig warten mussen. Dies kann auch durch das Setzen von Prioriaten<br />

mit setPriority() oder yieald() nicht vollig ausgeschlossen werden.<br />

Deshalb mu man bei parallel laufenden Threads immer dafur sorgen, da jeder<br />

von ihnen Pausen einlegt, in denen die anderen Threads eine Chance bekommen,<br />

ihrerseits zu laufen. Dies gilt auch fur das Programm, das den Thread mit start()<br />

gestartet hat und nun will, da dieser auch tatsachlich lauft.<br />

Die wichtigste Warte-Methode ist die statische Methode<br />

Thread.sleep (long)<br />

fur eine Pause mit einer bestimmten Zeitdauer (in Millisekunden)<br />

Beim Aufruf von sleep mu die Fehlersituation InterruptedException abgefangen<br />

werden, fur den Fall, da der Thread wahrend der Wartezeit gestoppt oder abgebrochen<br />

wird.<br />

Besonders wichtig ist die sleep-Methode, wenn die run-Methode eine Schleife oder<br />

Endlos-Schleife ist, die bestimmte Aktionen immer wieder wiederholt (so lange, bis<br />

der Thread beendet wird). Beispiel:<br />

public class MyProgram implements Runnable {<br />

private boolean runFlag;<br />

public void setRunFlag (boolean runFlag) {<br />

this.runFlag = runFlag;<br />

}<br />

public boolean getRunFlag() {<br />

return this.runFlag;<br />

}<br />

public void run() {<br />

runFlag=true;<br />

while (runFlag) {<br />

// do something<br />

try {<br />

Thread.sleep(1000);<br />

} catch (InterruptedException e) { }<br />

}<br />

}<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 113


8.5 Synchronisierung (join, wait, notify, synchronized)<br />

Wenn ein Thread die Ergebnisse, die ein anderer Thread produziert, verwenden will,<br />

mu der eine Thread auf den anderen warten und der andere dem einen mitteilen,<br />

wann er mit seiner Aufgabe fertig ist. Dazu dienen die folgenden Methoden:<br />

Methode im Thread-Objekt:<br />

join()<br />

fur das Abwarten, bis der gestartete Thread fertig gelaufen ist (d.h. sein Ende<br />

erreicht hat)<br />

Methoden in jedem Objekt (jeder Subklasse von Object):<br />

wait()<br />

fur das Abwarten, bis der gestartete Thread ein notify() fur dieses Objekt<br />

sendet<br />

wait(long timeout)<br />

ebenso, aber mit einem Timeout (maximale Wartezeit im Millisekunden)<br />

notify()<br />

fur das Beenden eines wait()-Zustandes fur dieses Objekt, wenn ein oder mehrere<br />

Threads mit wait() darauf warten; sonst ohne Bedeutung<br />

notifyAll()<br />

fur das Beenden von allen eventuell fur dieses Objekt wartenden wait()-<br />

Zustanden<br />

Dabei mu darauf geachtet, da keine Deadlock-Situation auftritt (Proze A wartet,<br />

das Proze B ein notify() sendet, und Proze B wartet, da Proze A ein notify()<br />

sendet).<br />

Wenn zwei oder mehrere parallel laufende Threads dasselbe Objekt ansprechen, kann<br />

es zu Problemen kommen, wenn beide gleichzeitig das Objekt verandern wollen<br />

und dabei auf vom anderen Thread halb ausgefuhrte Zwischenzustande zugreifen<br />

(concurrent update problem). In diesem Fall mu man alle "gefahrlichen" Aktionen<br />

jeweils in einen synchronized-Block der folgenden Form einfugen:<br />

synchronized (Object) {<br />

Statements;<br />

}<br />

wobei fur Object meistens this anzugeben ist, oder die jeweilige Methode insgesamt<br />

als synchronized deklarieren:<br />

public synchronized typ name (parameter) {<br />

Statements;<br />

}<br />

Dies bewirkt da der mit synchronized markierte Statement-Block (bzw. die mit<br />

synchronized markierte Methode) nur dann ausgefuhrt wird, wenn kein anderer,<br />

ebenfalls mit synchronized markierter Statement-Block fur dieses Objekt lauft; andernfalls<br />

wartet der neue Statement-Block, bis der alte Statement-Block fertig ist<br />

und sich das Objekt daher wieder in einem gultigen Zustand bendet, und fuhrt<br />

dann seine Aktionen ebenfalls komplett und ungestort aus.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 114


Die Methoden wait() und notify() sind nur innerhalb von synchronized Blocks oder<br />

Methoden erlaubt.<br />

Ab JDK 1.3 kann man auch sogenannte "Piped Streams" zur Kommunikation von<br />

Daten und von Wartezustanden zwischen zwei Threads verwenden (Klassen Piped-<br />

Writer und PipedReader im Pakte java.io): Jedes Lesen aus dem PipedReader in<br />

dem einen Thread wartet, bis vom anderen Thread entsprechende Daten in den<br />

zugehorigen PipedWriter geschrieben werden.<br />

8.6 Beispiel: eine einfache Animation<br />

import java.awt.* ;<br />

import java.applet.* ;<br />

public class Anima extends Applet<br />

implements Runnable {<br />

private boolean runFlag;<br />

private int x, y, height, width;<br />

private Image img;<br />

private Graphics g;<br />

private Thread t = null;<br />

private Color nightColor = new Color (0, 0, 102);<br />

private Color moonColor = new Color (204, 204, 255);<br />

public void init() {<br />

Dimension d = getSize();<br />

width = d.width;<br />

height = d.height;<br />

img = createImage (width, height);<br />

g=img.getGraphics();<br />

x = width/2;<br />

y = height/2;<br />

}<br />

public void start() {<br />

if (t == null)<br />

{<br />

t = new Thread (this);<br />

t.start();<br />

}<br />

}<br />

public void stop() {<br />

if (t != null)<br />

{<br />

runFlag=false; // or: t.stop();<br />

t=null;<br />

}<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 115


public void run () {<br />

runFlag=true;<br />

while (runFlag) {<br />

g.setColor (nightColor);<br />

g.fillRect(0,0,width,height);<br />

g.setColor (moonColor);<br />

g.fillArc(x, y-25, 50, 50, 270, 180);<br />

repaint();<br />

x = x + 2;<br />

if (x > width+50 ) {<br />

x = -50;<br />

}<br />

try { Thread.sleep(100); }<br />

catch (InterruptedException e) {}<br />

}<br />

}<br />

public void update (Graphics g) {<br />

paint(g);<br />

}<br />

public void paint (Graphics g) {<br />

if (img != null) {<br />

g.drawImage(img,0,0,null);<br />

}<br />

}<br />

}<br />

Wenn Sie wissen wollen, was dieses Applet tut, probieren Sie es einfach aus (in Ihrem<br />

Browser, wenn er das kann, oder Abschreibubung oder Download).<br />

8.7 Ubung: einfaches Applet Blinklicht<br />

Schreiben Sie ein einfaches Applet, das eine gelb blinkende Verkehrsampel zeigt<br />

(schwarzes Rechteck mit oder ohne gelbem Kreis).<br />

Wenn Sie sehen wollen, wie das aussehen konnte, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 116


8.8 Ubung: erweitertes Applet Verkehrsampel mit Blinklicht<br />

Erweitern Sie das Applet Verkehrsampel (siehe die Ubung im Kapitel Applets) in<br />

folgender Weise:<br />

Fugen Sie einen weiteren Button "Blink" hinzu.<br />

Wenn dieser Blink-Button angeklickt wird, dann soll die Verkehrsampel gelb<br />

blinken (wie in der vorhergehenden einfachen Ubung).<br />

Das Blinken soll enden und die Verkehrsampel wieder die normalen Farben<br />

zeigen, wenn der Blink-Button nochmals angeklickt wird, oder wenn der Nextoder<br />

Stop-Button angeklickt wird, oder wenn die Web-Page verlassen oder das<br />

Applet oder der Web-Browser beendet wird.<br />

Wenn Sie sehen wollen, wie das aussehen konnte, probieren Sie es in Ihrem Browser<br />

aus (falls er das kann).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 117


System-Interfaces<br />

Ein-Ausgabe (IO)<br />

Networking (Web-Server, Sockets)<br />

System-Funktionen und Utilities<br />

Datenbanken<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 118


9. Ein-Ausgabe (IO)<br />

Das Lesen und Schreiben von lokalen Dateien (Files) ist im allgemeinen nur fur<br />

Applikationen, aber nicht fur Applets erlaubt. Applets konnen im allgemeinen nur<br />

Files auf dem Server ansprechen, von dem sie geladen wurden (siehe die Kapitel<br />

uber das Lesen von einem Web-Server und uber Networking).<br />

Fur die Verwendung der Ein-Ausgabe-Klassen mu das Package java.io importiert<br />

werden.<br />

Alle Ein-Ausgabe-Operationen konnen bestimmte Fehlersituationen auslosen (IO-<br />

Exception, SecurityException, FileNotFoundException u.a.), die mit try und catch<br />

abgefangen werden sollen (siehe das Kapitel uber Exceptions).<br />

9.1 Dateien (Files) und Directories<br />

Deklaration eines Files:<br />

Die folgenden Datenstrome ("Systemdateien") stehen innerhalb der System-Klasse<br />

statisch zur Verfugung und mussen nicht explizit deklariert werden:<br />

PrintStream System.out<br />

PrintStream System.err<br />

InputStream System.in<br />

fur die Standard-Ausgabe<br />

fur die Fehlerausgabe<br />

fur die Standard-Eingabe<br />

Andere Files kann man im einfachsten Fall ansprechen, indem man den Filenamen<br />

im Konstruktor eines Datenstromes angibt (siehe unten).<br />

Fur kompliziertere Aktionen mit Dateien und Directories konnen File-Objekte mit<br />

den folgenden Konstruktoren angelegt und mit den folgenden Methoden verwendet<br />

werden:<br />

File f = new File (filename);<br />

File f = new File (directory, filename);<br />

Der Filename ist als String anzugeben. Er kann auch den kompletten Pfad enthalten,<br />

also mit Schragstrichen oder Backslashes oder Doppelpunkten, je nach Betriebssystem,<br />

die Applikation ist dann aber nicht plattformunabhangig. Statt diesen File-<br />

Separator explizit im String anzugeben, sollte man deshalb immer den am jeweiligen<br />

System gultigen Separator mit dem statischen Datenfeld<br />

File.separator<br />

ansprechen und mit + in den String einbauen.<br />

Die Version des Konstruktors mit zwei Parametern ist dann sinnvoll, wenn man<br />

mehrere Files in einem Directory ansprechen will, oder wenn das Directory innerhalb<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 119


des Programms bestimmt oder vom Benutzer ausgewahlt wird. Fur den Directory-<br />

Namen kann entweder ein String (wie oben) oder ein File-Objekt, das ein Directory<br />

beschreibt, angegeben werden.<br />

Das Onen oder Anlegen des Files erfolgt erst dann, wenn das File-Objekt im Konstruktor<br />

eines Datenstromes (InputStream, OutputStream, Reader, Writer, siehe<br />

unten) verwendet wird.<br />

Deklaration eines Directory:<br />

Methoden<br />

Directories werden wie Files deklariert und "geonet":<br />

File dir = new File (dirname);<br />

File dir = new File (parentdir, dirname);<br />

Mit den Methoden isFile() und isDirectory() kann abgefragt werden, ob es sich um<br />

ein File oder um ein Directory handelt. Das Anlegen eines Directory erfolgt mit der<br />

Methode mkdir().<br />

Die wichtigsten Methoden fur File-Objekte (Dateien und Directories) sind:<br />

String getName()<br />

fur den File- bzw. Directory-Namen ohne Pfad<br />

String getPath() und getAbsolutePath()<br />

fur den File- bzw. Directory-Namen mit Pfad<br />

String getParent()<br />

fur das Parent-Directory<br />

boolean exists(), boolean canWrite(), boolean canRead()<br />

fur die Existenz und die Permissions<br />

boolean isFile(), boolean isDirectory()<br />

fur die Art (File oder Directory)<br />

long length()<br />

fur die Lange in Bytes<br />

long lastModified()<br />

ist eine system-interne Zahl, die das Alter des File-Inhalts angibt (nur fur<br />

relative Vergleiche brauchbar, nicht fur Datums-Angaben)<br />

boolean mkdir()<br />

fur das Anlegen des Directory (liefert true, wenn erfolgreich durchgefuhrt,<br />

sonst false)<br />

String[] list()<br />

fur eine Liste von allen in einem Directory enthaltenen File- und Directory-<br />

Namen. Wenn man diese Files oder Subdirectories ansprechen will, mu man<br />

mit Konstruktoren wie new File(name[i]) File-Objekte dafur erzeugen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 120


static File[] listRoots()<br />

fur eine Liste von allen Filesystem-Anfangen ("Laufwerken" unter MS-<br />

Windows).<br />

boolean renameTo (new File(filename))<br />

fur die Anderung des File- oder Directory-Namens (liefert true, wenn erfolgreich<br />

durchgefuhrt, sonst false)<br />

boolean delete()<br />

fur das Loschen des Files oder Directory (liefert true, wenn erfolgreich durchgefuhrt,<br />

sonst false)<br />

9.2 Datenstrome (stream)<br />

Im Sinne der Grundsatze der objekt-orientierten Programmierung gibt es in <strong>Java</strong><br />

verschiedene Klassen und Objekte fur Datenstrome, die je nach der Anwendung<br />

entsprechend kombiniert werden mussen. Dabei sind die Spezialfalle jeweils Unterklassen<br />

der einfachen Falle (Vererbung), alle Ein-Ausgabe-Operationen konnen also<br />

direkt am Objekt der Unterklasse durchgefuhrt werden.<br />

Einfache, grundlegende Stream-Klassen denieren auf einer niedrigen Ebene<br />

die Ein- und Ausgabe in Dateien (Files) oder auch in anderen Datenstromen<br />

wie z.B. Pipes, Byte-Arrays oder Netzverbindungen (Sockets, URLs).<br />

Spezielle, darauf aufbauende Stream-Klassen denieren zusatzliche Eigenschaften<br />

wie z.B. Puerung, zeilenorientierte Text-Ausgabe, automatische Zeilennumerierung<br />

und dergleichen.<br />

Es gibt in <strong>Java</strong> zwei verschiedene Gruppen von Datenstromen:<br />

InputStream, OutputStream und RandomAccessFile fur byte-orientierte Datenles,<br />

Reader und Writer fur zeichen- und zeilen-orientierte Textles.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 121


9.3 InputStream (Eingabe)<br />

Byte-weises Lesen<br />

InputStream ist die Oberklasse fur das Lesen, also die Eingabe von Datenstromen<br />

(siehe auch die Alternative Reader).<br />

FileInputStream ist die grundlegende Klasse fur das Lesen von Dateien (siehe auch<br />

die Alternative FileReader).<br />

Das Onen des Lese-Stroms bzw. des Files erfolgt mit einem Konstruktor der Form<br />

FileInputStream infile = new FileInputStream (filename);<br />

Der Filename kann entweder als String oder als File-Objekt angegeben werden (siehe<br />

oben).<br />

Die wichtigsten Methoden fur InputStreams sind:<br />

int read()<br />

liefert ein Byte, oder den Wert -1, wenn das Ende des Datenstroms (End-of-<br />

File) erreicht wurde. Beispiel:<br />

int b = infile.read();<br />

int read (byte[])<br />

int read (byte[], offset, length)<br />

liest so viele Zeichen wie moglich in das Byte-Array bzw. in den angegebenen<br />

Teilbereich des Byte-Array und liefert die Anzahl der gelesenen Zeichen<br />

(eventuell 0), oder den Wert -1, wenn das Ende des Datenstroms (End-of-File)<br />

erreicht wurde. Beispiel:<br />

byte[] b = new byte[1024];<br />

int n = infile.read (b[]);<br />

skip(long)<br />

uberspringt die angegebene Anzahl von Bytes im Eingabestrom.<br />

close()<br />

schliet den Eingabestrom bzw. das File.<br />

Ein typisches Beispiel fur das Byte-weise Lesen eines Daten-Files hat folgenden<br />

Aufbau:<br />

int b;<br />

try {<br />

BufferedInputStream in = new BufferedInputStream (<br />

new FileInputStream ("filename.dat") );<br />

while( (b = in.read()) != -1 ) {<br />

// do something ...<br />

}<br />

in.close();<br />

} catch (Exception e) {<br />

System.out.println("error " + e);<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 122


9.4 Spezielle Input-Streams<br />

BueredInputStream<br />

DataInputStream<br />

Spezielle InputStreams bauen auf grundlegenden InputStreams auf. Der Konstruktor<br />

hat als Parameter ein Objekt des darunterliegenden InputStream.<br />

Die wichtigsten Input-Streams und ihre Methoden sind:<br />

Um die Eingabe ezienter und schneller zu machen, soll nicht jedes Byte einzeln<br />

von der Hardware gelesen werden, sondern aus einem Puerbereich. Daher sollte fast<br />

immer ein BueredInputStream uber den einfachen FileInputStream gelegt werden.<br />

Konstruktoren:<br />

new BufferedInputStream (InputStream)<br />

fur einen Puer mit Standardgroe<br />

new BufferedInputStream (InputStream, int)<br />

fur einen Puer mit der angegebenen Groe<br />

Beispiel:<br />

BufferedInputStream in = new BufferedInputStream<br />

( new FileInputStream (filename) );<br />

Der DataInputStream erlaubt es, bestimmte primitive Datentypen direkt einzulesen,<br />

d.h. die Daten mussen in der plattformunabhangigen <strong>Java</strong>-internen Darstellung<br />

im Input-Stream stehen ("binares Datenle", z.B. mit DataOutputStream geschrieben).<br />

Konstruktor:<br />

new DataInputStream (InputStream)<br />

Beispiel:<br />

DataInputStream in = new DataInputStream<br />

( new BufferedInputStream<br />

( new FileInputStream (filename) ) );<br />

Methoden:<br />

boolean readBoolean()<br />

byte readByte()<br />

int readInt()<br />

long readLong()<br />

float readFloat()<br />

double readDouble()<br />

und so weiter<br />

Es gibt hier auch eine String-Methode readLine(), es wird aber empfohlen, fur die<br />

Verarbeitung von Textzeilen lieber die Klasse BueredReader zu verwenden (siehe<br />

unten).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 123


ObjectInputStream<br />

Ahnlich wie der DataInputStream, erlaubt es aber auch, beliebige Objekt-Typen zu<br />

lesen, die im Input-Stream in der <strong>Java</strong>-internen Darstellung stehen ("Serialization",<br />

z.B. mit ObjectOutputStream geschrieben, Filenamen der Form xxxx.ser).<br />

Konstruktor:<br />

new ObjectInputStream (InputStream)<br />

Methoden:<br />

wie beim DataInputStream, und zusatzlich<br />

Object readObject()<br />

fur beliebige Objekte<br />

Anmerkung: Object ist die Superklasse fur alle Klassen. Das Ergebnis von read-<br />

Object() mu mit "Casting" auf den Typ des tatsachlich gelesenen Objekts umgewandelt<br />

werden. Beispiel:<br />

Date d;<br />

...<br />

d = (Date) in.readObject();<br />

9.5 Lesen einer Datei von einem Web-Server (URL)<br />

Mit den Klassen URL (uniform resource locator) und URLConnection im Paket<br />

java.net kann eine beliebige Datei von einem Web-Server oder FTP-Server gelesen<br />

werden (bei Applikationen von einem beliebigen Server, bei einem Applet im allgemeinen<br />

nur von dem Web-Server, von dem es geladen wurde). Mit der Methode<br />

openStream() erhalt man einen InputStream, der dann wie ein FileInputStream<br />

verwendet werden kann.<br />

Beispiel:<br />

import java.io.*;<br />

import java.net.*;<br />

...<br />

BufferedInputStream in;<br />

URL url;<br />

try {<br />

url = new URL( "http://www.xxx.com/yyy.html" );<br />

in = new BufferedInputStream ( url.openStream() );<br />

...<br />

// Lesen mit in.read()<br />

...<br />

} catch (Exception e) {<br />

System.out.println("error "+e);<br />

}<br />

Dies eignet sich bis JDK 1.1 primar fur das Lesen von Textles (siehe InputStream-<br />

Reader) und Datenles (siehe DataInputStream). Ab JDK 1.2 gibt es auch eigene<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 124


Klassen fur die Interpretation von HTML-Files (JEditorPane, HTMLDocument,<br />

HTMLReader).<br />

Komplexere Moglichkeiten fur Ein-Ausgabe-Operationen uber das Internet sind im<br />

Kapitel uber Networking und Sockets beschrieben.<br />

9.6 OutputStream (Ausgabe)<br />

Byte-weises Schreiben<br />

OutputStream ist die Oberklasse fur das Schreiben, also die Ausgabe von Datenstromen<br />

(siehe auch die Alternative Writer).<br />

FileOutputStream ist die grundlegende Klasse fur das Schreiben von Dateien (siehe<br />

auch die Alternative FileWriter).<br />

Das Onen des Ausgabe-Stroms bzw. des Files erfolgt mit Konstruktoren der Form<br />

new FileOutputStream (filename);<br />

new FileOutputStream (filename, false);<br />

new FileOutputStream (filename, true);<br />

Der Filename kann entweder als String oder als File-Objekt angegeben werden<br />

(siehe oben). In den ersten beiden Fallen wird die Datei neu geschrieben oder<br />

uberschrieben, im dritten Fall (Appendmode true) werden die Informationen an<br />

das Ende einer bereits existierenden Datei hinzugefugt.<br />

In JDK 1.0 ist die Angabe des Appendmode nicht moglich, dort mu fur das Hinzufugen<br />

an eine bereits bestehende Datei stattdessen die Klasse RandomAccessFile<br />

verwendet werden (siehe unten).<br />

Die wichtigsten Methoden fur OutputStreams sind:<br />

write(int)<br />

schreibt ein Byte mit den angegeben Wert<br />

write (byte[])<br />

write (byte[], offset, length)<br />

schreibt alle im Byte-Array bzw. im angegebenen Teilbereich des Byte-Array<br />

enthaltenen Bytes<br />

flush()<br />

sorgt dafur, da alle eventuell noch im Puer wartenden Bytes tatsachlich<br />

in die Datei geschrieben werden (sollte immer vor dem Close bzw. vor der<br />

Beendigung oder einem Abbruch des Programms aufgerufen werden)<br />

close()<br />

schliet den Ausgabestrom bzw. das File.<br />

Ein typisches Beispiel fur das Byte-weise Schreiben eines Daten-Files hat folgenden<br />

Aufbau:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 125


try {<br />

BufferedOutputStream out = new BufferedOutputStream (<br />

new FileOutputStream ("filename.dat") );<br />

...<br />

out.write(...);<br />

...<br />

out.flush();<br />

out.close();<br />

} catch (Exception e) {<br />

System.out.println("error " + e);<br />

}<br />

9.7 Spezielle Output-Streams<br />

BueredOutputStream<br />

DataOutputStream<br />

Spezielle OutputStreams bauen auf grundlegenden OutputStreams auf. Der Konstruktor<br />

hat als Parameter ein Objekt des darunterliegenden OutputStream.<br />

Die wichtigsten Output-Streams und ihre Methoden sind:<br />

Um die Ausgabe ezienter und schneller zu machen, soll nicht jedes Byte einzeln<br />

auf die Hardware geschrieben werden, sondern aus einem Puerbereich. Daher sollte<br />

fast immer ein BueredOutputStream uber den einfachen FileOutputStream gelegt<br />

werden.<br />

Konstruktoren:<br />

new BufferedOutputStream (OutputStream)<br />

fur einen Puer mit Standardgroe<br />

new BufferedOutputStream (OutputStream, int)<br />

fur einen Puer mit der angegebenen Groe<br />

Beispiel:<br />

BufferedOutputStream out = new BufferedOutputStream<br />

( new FileOutputStream (filename) );<br />

Der DataOutputStream erlaubt es, bestimmte primitive Datentypen direkt in ihrer<br />

(plattformunabhangigen) <strong>Java</strong>-internen Darstellung zu schreiben ("binares Daten-<br />

le", kann dann mit DataInputStream gelesen werden).<br />

Konstruktor:<br />

new DataOutputStream (OutputStream)<br />

Beispiel:<br />

DataOutputStream out = new DataOutputStream<br />

( new BufferedOutputStream<br />

( new FileOutputStream (filename) ) );<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 126


Methoden:<br />

ObjectOutputStream<br />

PrintStream<br />

writeBoolean(boolan)<br />

writeByte(int)<br />

writeBytes(String)<br />

writeInt(int)<br />

writeLong(long)<br />

writeFloat(float(<br />

writeDouble(double)<br />

und so weiter<br />

Ahnlich wie der DataOutputStream, erlaubt es aber auch, Objekt-Typen in der<br />

<strong>Java</strong>-internen Darstellung zu schreiben (kann dann mit ObjectInputStream gelesen<br />

werden). Dazu mu das Objekt nur das Interface Serializable implementieren (was<br />

im allgemeinen kein Problem ist).<br />

Konstruktor:<br />

new ObjectOutputStream (OutputStream)<br />

Methoden:<br />

wie beim DataOutputStream, und zusatzlich<br />

writeObject(Object)<br />

Anmerkung: Object ist die Superklasse fur alle Klassen, der Parameter von write-<br />

Object kann also ein Objekt einer beliebigen Klasse sein. Beispiel:<br />

Date d;<br />

...<br />

out.writeObject (d);<br />

Es wird empfohlen, fur das Schreiben von zeilenorientierten Datenstromen lieber die<br />

Klasse PrintWriter zu verwenden (siehe unten)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 127


9.8 RandomAccessFile (Ein- und Ausgabe)<br />

Random-Access-Files erlauben es, Daten nicht nur in einem Datenstrom vom Anfang<br />

bis zum Ende zu lesen oder zu schreiben, sondern an bestimmte Stellen eines Files zu<br />

"springen" und dort direkt zu lesen und zu schreiben. Dabei ist auch ein Abwechseln<br />

zwischen Lese- und Schreiboperationen moglich.<br />

Konstruktor:<br />

new RandomAccessFile (filename, mode)<br />

Der Filename kann als String oder als File-Objekt angegeben werden.<br />

Der Mode ist ein String, der entweder nur "r" oder "rw" enthalt. Im ersten Fall<br />

kann der File-Inhalt nur gelesen werden, im zweiten Fall (auch) geschrieben bzw.<br />

verandert werden.<br />

Methoden:<br />

Es stehen alle fur InputStreams und fur OutputStreams denierten Methoden zur<br />

Verfugung, also insbesondere read, write, close, ush, und auerdem die folgenden<br />

Methoden:<br />

long getFilePointer()<br />

liefert die aktuelle Position innerhalb des Files<br />

long length()<br />

liefert die Lange des Files<br />

seek (long)<br />

setzt den FilePointer auf eine bestimmte Stelle fur das nachste read oder write<br />

Wenn man Daten an das Ende einer bereits existierenden Datei hinzufugen will,<br />

kann man diese Datei als RandomAccessFile mit mode "rw" onen und mit<br />

file.seek( file.length() );<br />

an das File-Ende positionieren, bevor man den ersten write-Befehl ausfuhrt. Ab JDK<br />

1.1 kann man dies aber einfacher mit dem Appendmode-Parameter im Konstruktor<br />

des FileOutputStream bzw. FileWriter erreichen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 128


9.9 Reader und Writer (Text-Files)<br />

FileReader<br />

FileWriter<br />

<strong>Java</strong> als plattformunabhangige Sprache verwendet den Zeichencode "Unicode" (16<br />

bit pro Zeichen) fur die Verarbeitung von allen weltweit verwendeten Schriftzeichen.<br />

Die Reader- und Writer-Klassen unterstutzen die Umwandlung zwischen diesem 16<br />

bit Unicode und dem auf dem jeweiligen Rechnersystem verwendeten (meist 8 bit)<br />

Zeichencode fur Textles. Dies kann der in englisch-sprachigen und westeuropaischen<br />

Landern verwendete Zeichencode Iso-Latin-1 (ISO-8859-1) oder ein anderer Zeichencode<br />

sein, z.B. fur osteuropaische lateinische Schriften (Iso-Latin-2) oder fur<br />

kyrillische, griechische, arabische, hebraische oder ostasiatische Schriften, oder die<br />

Unicode-Kodierung mit UTF-8, oder auch ein Computer-spezischer Code wie z.B.<br />

fur MS-DOS, MS-Windows oder Apple Macintosh.<br />

Fur die Verarbeitung von Textles sollten daher ab JDK 1.1 Reader und Writer<br />

statt Input-Streams und Output-Streams verwendet werden. Diese Klassen enthalten<br />

nicht nur Methoden fur das Lesen und Schreiben von einzelnen Bytes (read,<br />

write) sondern auch zusatzliche Methoden fur das Lesen und Schreiben von ganzen<br />

Zeilen (readLine, newLine) sowie fur die Darstellung von Zahlen und anderen Datentypen<br />

als menschenlesbare Texte (print, println).<br />

Die wichtigsten Klassen sind:<br />

FileReader, FileWriter und PrintWriter<br />

BueredReader und BueredWriter<br />

InputStreamReader und OutputStreamWriter<br />

StringReader und StringWriter<br />

Der FileReader ist die grundlegende Klasse zum text- und zeilen-orientierten Lesen<br />

von Dateien (Files). Aus Ezienzgrunden sollte er innerhalb eines BueredReader<br />

verwendet werden (siehe unten).<br />

Konstruktor:<br />

new FileReader (filename)<br />

Der Filename ist als String oder als File-Objekt anzugeben.<br />

Das Encoding kann hier nicht angegeben werden, es wird immer das lokale Encoding<br />

des Systems angenommen. Falls Sie das Encoding (z.B. "8859 1") explizit angeben<br />

wollen, mussen Sie statt dem FileReader eine Kombination von InputStreamReader<br />

und FileInputStream verwenden (siehe unten).<br />

Der FileWriter ist die grundlegende Klasse zum text- und zeilen-orientierten Schreiben<br />

von Dateien (Files). Aus Ezienzgrunden sollte er innerhalb eines BueredWriter<br />

verwendet werden (siehe unten).<br />

Konstruktoren:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 129


new FileWriter (filename)<br />

new FileWriter (filename, false)<br />

new FileWriter (filename, true)<br />

Der Filename ist als String oder als File-Objekt anzugeben. In den ersten beiden<br />

Fallen wird die Datei neu geschrieben oder uberschrieben, im dritten Fall (Appendmode<br />

true) werden die Informationen an das Ende einer bereits existierenden Datei<br />

hinzugefugt.<br />

Das Encoding kann hier nicht angegeben werden, es wird immer das lokale Encoding<br />

des Systems angenommen. Falls Sie das Encoding (z.B. "8859 1") explizit angeben<br />

wollen, mussen Sie statt dem FileWriter eine Kombination von OutputStreamWriter<br />

und FileOutputStream verwenden (siehe unten).<br />

PrintWriter<br />

Der PrintWriter ist eine spezielle Klasse zum text- und zeilen-orientierten Schreiben<br />

von Datenstromen oder Files. Sie enthalt zusatzliche Methoden fur die Umwandlung<br />

von Zahlen und anderen Objekten in menschenlesbare Texte (print, println, siehe<br />

unten).<br />

Konstruktoren:<br />

new PrintWriter (Writer)<br />

new PrintWriter (OutputStream)<br />

Das Encoding kann hier nicht angegeben werden, es wird immer das lokale Encoding<br />

des Systems angenommen.<br />

BueredReader und BueredWriter<br />

Um die Ausgabe ezienter und schneller zu machen, soll nicht jedes Byte einzeln von<br />

der Hardware gelesen bzw. auf die Hardware geschrieben werden, sondern aus einem<br />

Puerbereich. Daher sollte fast immer ein BueredReader bzw. BueredWriter uber<br />

den einfachen FileReader, InputStreamReader, FileWriter oder OutputStreamWriter<br />

gelegt werden.<br />

Konstruktoren:<br />

new BufferedReader (Reader)<br />

fur einen Puer mit Standardgroe<br />

new BufferedReader (Reader, int)<br />

fur einen Puer mit der angegebenen Groe<br />

new BufferedWriter (Writer)<br />

fur einen Puer mit Standardgroe<br />

new BufferedWriter (Writer, int)<br />

fur einen Puer mit der angegebenen Groe<br />

Beispiele:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 130


BufferedReader infile = new BufferedReader<br />

(new FileReader (infileName) );<br />

BufferedWriter outfile = new BufferedWriter<br />

(new FileWriter (outfileName) );<br />

InputStreamReader und OutputStreamWriter<br />

Die Klasse InputStreamReader dient dazu, einen byte-orientierten InputStream zum<br />

Lesen von Texten und Textzeilen zu verwenden. Dies ist fur Spezialfalle notwendig,<br />

die nicht mit dem FileReader abgedeckt werden konnen. Aus Ezienzgrunden sollte<br />

sie innerhalb eines BueredReader verwendet werden.<br />

Konstruktor:<br />

new InputStreamReader (InputStream)<br />

new InputStreamReader (InputStream, String)<br />

Der String im zweiten Fall gibt den Zeichencode an, z.B. "8859 1". Im ersten Fall<br />

wird der am jeweiligen Rechnersystem "ubliche" Zeichencode verwendet. Beim Lesen<br />

von Dateien uber das Internet soll immer der Code der Datei explizit angegeben<br />

werden, damit man keine bosen Uberraschungen auf Grund von lokalen Spezialfallen<br />

am Client erlebt.<br />

Beispiele:<br />

BufferedReader stdin = new BufferedReader<br />

(new InputStreamReader (System.in) );<br />

BufferedReader infile = new BufferedReader<br />

(new InputStreamReader<br />

(new FileInputStream("message.txt"), "8859_1" ) )<br />

String fileUrl = "ftp://servername/dirname/filename";<br />

BufferedReader infile = new BufferedReader<br />

(new InputStreamReader<br />

( ( new URL(fileUrl) ).openStream(), "8859_1" ) )<br />

Die Klasse OutputStreamReader funktioniert analog zum InputStreamReader und<br />

dient zum Schreiben von Texten und Textzeilen auf einen byte-orientierten OutputStream<br />

in Spezialfallen, die nicht mit dem FileWriter abgedeckt werden konnen.<br />

Beispiele:<br />

BufferedWriter stdout = new BufferedWriter<br />

(new OutputStreamWriter (System.out) );<br />

BufferedWriter outfile = new BufferedWriter<br />

(new OutputStreamWriter<br />

(new FileOutputStream("message.txt"),<br />

"8859_1" ) )<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 131


StringReader und StringWriter<br />

Die Klassen StringReader und StringWriter dienen dazu, aus einem langen String-<br />

Objekt (statt einem File oder InputStream) zu lesen bzw. in ein String-Objekt zu<br />

schreiben.<br />

Konstruktoren:<br />

new StringReader (String)<br />

new StringWriter()<br />

Den Inhalt des StringWriter-Objekts kann man mit der folgenden zusatzlichen Methode<br />

erhalten:<br />

String toString()<br />

9.10 Reader<br />

Reader - Methoden<br />

zeichenweises Lesen<br />

Die wichtigsten Methoden bei den Reader-Klassen sind:<br />

int read()<br />

liefert ein Zeichen, oder den Wert -1, wenn das Ende des Datenstroms (Endof-File)<br />

erreicht wurde.<br />

int read (char[])<br />

int read (char[], offset, length)<br />

liest so viele Zeichen wie moglich in das Zeichen-Array bzw. in den angegebenen<br />

Teilbereich des Zeichen-Array und liefert die Anzahl der gelesenen Zeichen<br />

(eventuell 0), oder den Wert -1, wenn das Ende des Datenstroms (End-of-File)<br />

erreicht wurde.<br />

String readLine()<br />

liefert eine Zeile, oder den Wert null, wenn das Ende des Datenstroms (Endof-File)<br />

erreicht wurde.<br />

skip(long)<br />

uberspringt die angegebene Anzahl von Zeichen im Eingabestrom.<br />

close()<br />

schliet den Eingabestrom bzw. das File.<br />

Ein typisches Beispiel fur das zeichenweise Lesen eines Text-Files hat folgenden<br />

Aufbau:<br />

int ch;<br />

try {<br />

BufferedReader in = new BufferedReader (<br />

new FileReader ("filename.txt") );<br />

while( (ch = in.read()) != -1 ) {<br />

// do something ...<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 132


zeilenweises Lesen<br />

9.11 Writer<br />

Writer - Methoden<br />

}<br />

in.close();<br />

} catch (Exception e) {<br />

System.out.println("error " + e);<br />

}<br />

Ein typisches Beispiel fur das zeilenweise Lesen eines Text-Files hat folgenden Aufbau:<br />

String thisLine;<br />

try {<br />

BufferedReader in = new BufferedReader (<br />

new FileReader ("filename.txt") );<br />

while( (thisLine = in.readLine()) != null ) {<br />

// do something ...<br />

}<br />

in.close();<br />

} catch (Exception e) {<br />

System.out.println("error " + e);<br />

}<br />

Die wichtigsten Methoden bei den Writer-Klassen sind:<br />

write(int)<br />

schreibt ein Zeichen mit den angegeben Wert<br />

write (char[])<br />

write (char[], offset, length)<br />

schreibt alle im Zeichen-Array bzw. im angegebenen Teilbereich des Zeichen-<br />

Array enthaltenen Zeichen<br />

write(String)<br />

schreibt die im angebenen String enthaltene Zeichenkette<br />

newLine()<br />

schreibt ein Zeilenende-Zeichen<br />

flush()<br />

sorgt dafur, da alle eventuell noch im Puer wartenden Zeichen tatsachlich<br />

in die Datei geschrieben werden (sollte immer vor dem Close bzw. vor der<br />

Beendigung oder einem Abbruch des Programms aufgerufen werden)<br />

close()<br />

schliet den Ausgabestrom bzw. das File.<br />

Anmerkung: Um plattformunabhangige Dateien zu erzeugen, sollten Zeilenenden<br />

stets mit der Methode newLine() geschrieben werden und nicht mit "nn" oder "nrnn"<br />

innerhalb von Strings.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 133


PrintWriter - Methoden<br />

Der PrintWriter hat zusatzlich die folgenden Methoden:<br />

print(String)<br />

fur die Ausgabe eines Textstrings<br />

print(boolean)<br />

print(char)<br />

print(int)<br />

print(long)<br />

print(float)<br />

print(double)<br />

und so weiter fur eine menschenlesbare Darstellung des jeweiligen Wertes in<br />

Zeichen<br />

print(Object)<br />

fur eine menschenlesbare Darstellung des Objekts unter Verwendung der Methode<br />

toString()<br />

println()<br />

fur die Ausgabe eines Zeilenende-Zeichens<br />

println(String)<br />

println(Object)<br />

println(boolean)<br />

und so weiter<br />

fur die Ausgabe des Strings bzw. Wertes bzw. Objekts und anschlieend eines<br />

Zeilenende-Zeichens ("print line")<br />

Wenn Sie angeben wollen, mit wie vielen Nachkommstellen Float- und Double-<br />

Zahlen ausgegeben werden sollen, konnen Sie die Klassen DecimalFormat oder NumberFormat<br />

aus dem Package java.text verwenden. Beispiel:<br />

double x = ...;<br />

DecimalFormat dec = new DecimalFormat ("#,###,##0.00");<br />

System.out.println("x = " + dec.format(x));<br />

zeichen- und zeilenweises Schreiben<br />

Ein typisches Beispiel fur das Schreiben eines Text-Files hat folgenden Aufbau:<br />

try {<br />

BufferedWriter out = new BufferedWriter (<br />

new FileWriter ("filename.txt") );<br />

...<br />

out.write(...);<br />

out.newLine();<br />

...<br />

out.flush();<br />

out.close();<br />

} catch (Exception e) {<br />

System.out.println("error " + e);<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 134


oder mit Verwendung von PrintWriter (mit auto-ush):<br />

try {<br />

PrintWriter out = new PrintWriter (<br />

new BufferedWriter (<br />

new FileWriter ("filename.txt") ) );<br />

...<br />

out.print(...);<br />

out.println(...);<br />

...<br />

// out.flush(); not needed with autoflush PrintWriter<br />

out.close();<br />

} catch (Exception e) {<br />

System.out.println("error " + e);<br />

}<br />

9.12 Ubung: zeilenweises Ausdrucken eines Files<br />

Schreiben Sie eine einfache Applikation, die ein Text-File (ihr eigenes <strong>Java</strong>-Source-<br />

File) Zeile fur Zeile liest und auf die Standard-Ausgabe ausgibt.<br />

Dieses Programm kann dann als Muster fur kompliziertere Programme verwendet<br />

werden.<br />

9.13 Ubung: zeichenweises Kopieren eines Files<br />

Schreiben Sie eine einfache Applikation, die ein Text-File (ihr eigenes <strong>Java</strong>-Source-<br />

File) Byte fur Byte oder Zeichen fur Zeichen auf ein neues File ("test.out") kopiert.<br />

Diese beiden Programmvarianten konnen dann als Muster fur kompliziertere Programme<br />

verwendet werden.<br />

9.14 Ubung: Lesen eines Files uber das Internet<br />

Schreiben Sie eine einfache Applikation, die ein kurzes Text-File von einem Web-<br />

Server oder FTP-Server liest und Zeile fur Zeile auf die Standard-Ausgabe ausgibt.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 135


10. Networking<br />

<strong>Java</strong> unterstutzt standardmaig nicht nur das Lesen und Schreiben von lokalen<br />

Dateien (siehe oben) sondern auch die Kommunikation uber Computer-Netze mit<br />

der Technik des Internet-Protokolls TCP/IP.<br />

Die wichtigsten Moglichkeiten, Pakete und Klassen sind:<br />

Zugri auf Web-Server (URL):<br />

Paket java.net<br />

Klassen URL, HttpURLConnection, ...<br />

<strong>Java</strong> im Web-Server (Servlet):<br />

Pakete javax.servlet, javax.servlet.http<br />

Klassen GenericServlet, HttpServlet, ...<br />

Client-Server-Systeme (Socket):<br />

Paket java.net<br />

Klassen ServerSocket, Socket<br />

Fur die Details wird auf die Online-Dokumentation verwiesen. Beispiele fur die<br />

Verwendung der Klasse URL nden Sie oben. Weitere Hinweise zu einigen dieser<br />

Klassen nden Sie nachfolgend.<br />

10.1 <strong>Java</strong> im Web-Server (CGI, Servlets)<br />

Web-Server konnen nicht nur fertige Files liefern sondern auch Programme<br />

ausfuhren. Dazu dient die Schnittstelle Common Gateway Interface (CGI). Die<br />

CGI-Programme konnen, eventuell in Abhangigkeit von Benutzer-Eingaben, irgendwelche<br />

Aktionen ausfuhren und die Ergebnisse uber das Hypertext Transfer<br />

Protocol HTTP an den Web-Browser senden.<br />

CGI-Programme konnen im HTML-File oder Applet entweder uber ein Hypertext-<br />

Link aufgerufen werden (nur Ausgabe an den Client) oder uber ein Formular oder<br />

GUI (Eingabe vom Client an das CGI-Programm, Ausgabe an den Client).<br />

CGI-Programme konnen in jeder beliebigen Programmier- oder Script-Sprache geschrieben<br />

werden, auch in <strong>Java</strong>. In diesem Fall besteht das CGI-Programm aus einem<br />

Shell-Script, in dem die <strong>Java</strong> Virtual Machine aufgerufen wird, die den Bytecode der<br />

<strong>Java</strong>-Applikation interpretiert, etwa in einer der folgenden Formen:<br />

java Classname<br />

java Classname Parameter<br />

java -Dvariable=wert Classname<br />

Dies bedeutet, da bei jedem Aufruf des CGI-Programms die <strong>Java</strong> Virtual Machine<br />

neu gestartet werden mu, was eventuell zu langeren Wartezeiten fuhren kann.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 136


Diesen Nachteil kann man vermeiden, wenn man einen Web-Server verwendet, der<br />

die <strong>Java</strong> Virtual Machine integriert enthalt und <strong>Java</strong>-Programme sofort direkt aufrufen<br />

kann (z.B. die neueren Versionen von Apache, Netscape Enterprise Server und<br />

vielen anderen).<br />

Diese <strong>Java</strong>-Programme werden als Servlets bezeichnet. Der Name "Servlet" ist<br />

analog zu "Applet" gebildet: So wie Applets von einer <strong>Java</strong> Virtual Machine innerhalb<br />

des Web-Browsers ausgefuhrt werden, so werden Servlets von einer <strong>Java</strong><br />

Virtual Machine innerhalb des Web-Servers ausgefuhrt.<br />

Dafur gibt es die Packages javax.servlet und javax.servlet.http sowie ein <strong>Java</strong> Servlet<br />

Development Kit JSDK mit einem ServletRunner zum Testen von Servlets, bevor<br />

sie im echten Web-Server eingebaut werden.<br />

Die wichtigsten Methoden von Servlets sind:<br />

Wenn der Web-Server startet und die Servlets initialisiert, wird die init-<br />

Methode ausgefuhrt.<br />

Bei jedem Client-Request ("User-Click") wird die service-Methode oder die<br />

von dort je nach der Request-Methode aufgerufene Methode doGet, doPost<br />

etc. ausgefuhrt. Diese Methoden haben 2 Parameter:<br />

{ Mit dem Parameter ServletRequest konnen die vom Client mitgesendeten<br />

Informationen abgefragt werden.<br />

{ Mit dem Parameter ServletResponse mu die Antwort an den Client<br />

gesendet werden.<br />

Mit der Methode getServletInfo kann man das Servlet dokumentieren.<br />

Servlets konnen wie <strong>Java</strong>-Applikationen auch auf lokale Files, Programme und Systemfunktionen<br />

am Web-Server zugreifen.<br />

Fur ausfuhrlichere Informationen wird auf die Referenzen und die Literatur verwiesen.<br />

Hier nur eine kurze Skizze fur den typischen Aufbau eines Servlet:<br />

import java.io.*;<br />

import javax.servlet.*;<br />

import javax.servlet.http.*;<br />

public class ... extends HttpServlet {<br />

public void init (ServletConfig config)<br />

throws ServletException {<br />

super.init( config );<br />

...<br />

}<br />

public void service<br />

(HttpServletRequest req, HttpServletResponse resp)<br />

throws ServletException, IOException {<br />

String xxx = req.getParameter("xxx");<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 137


}<br />

}<br />

...<br />

resp.setContentType("text/html");<br />

PrintWriter out =<br />

new PrintWriter( resp.getOutputStream() );<br />

out.println (" ... ");<br />

...<br />

out.println (" ... ");<br />

out.flush();<br />

out.close();<br />

public String getServletInfo() {<br />

return "...";<br />

}<br />

10.2 Internet-Protokoll, Server und Clients<br />

Grundbegrie<br />

Vorgangsweise<br />

<strong>Java</strong> unterstutzt die Kommunikation uber das weltweite Internet und uber interne<br />

Intranets und Extranets mit den Internet-Protokollen TCP und UDP. Dazu mu<br />

das Package java.net importiert werden.<br />

Die programmtechnischen Mechanismen fur Netzverbindungen werden Sockets<br />

(vom englischen Wort fur Steckdose) genannt.<br />

Fur die Adressierung werden Hostname und Portnummer verwendet.<br />

Der Hostname ist eine weltweit bzw. netzweit eindeutige Bezeichnung des Rechners<br />

(Name oder Nummer).<br />

Die Portnummer gibt an, welches Programm auf diesem Rechner die uber das<br />

Netz ubertragenen Informationen verarbeiten soll. Portnummern unter 1024 haben<br />

eine vordenierte Bedeutung und konnen nur mit Supervisor-Privilegien (root<br />

unter Unix) verwendet werden. Portnummern uber 1024 sind "frei". Fur <strong>Java</strong>-<br />

Anwendungen, die von gewohnlichen Benutzern geschrieben werden, kommen also<br />

meist nur Portnummern uber 1024 in Frage, und man mu sicherstellen, da nicht jemand<br />

anderer auf demselben Rechner dieselbe Portnummer schon fur andere Zwecke<br />

verwendet.<br />

Server sind die Rechner, die ein bestimmtes Service bieten und damit die Kunden<br />

(Clients) "bedienen".<br />

Clients ("Kunden") sind die Benutzer, die das Service des Servers in Anspruch<br />

nehmen wollen, bzw. die von ihnen dafur benutzten Rechner.<br />

Der Server "horcht" (listen) mit Hilfe einer ServerSocket auf eine Portnummer,<br />

d.h. er wartet darauf, da ein Client etwas von ihm will ("einen Request sendet"). In<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 138


10.3 Sockets<br />

diesem Fall baut er, meist in einem eigenen Thread, eine Verbindung (connection)<br />

mit dem Client uber eine Socket auf, liest eventuell vom Client kommende Befehle<br />

und Dateneingaben und sendet jedenfalls Meldungen und Ergebnisse an den Client.<br />

Clients bauen uber eine Socket eine Verbindung (connection) zum Server auf,<br />

senden eventuell Befehle oder Daten an den Server und lesen jedenfalls alle vom<br />

Server kommenden Informationen.<br />

ServerSocket (listen, accept)<br />

Die Klasse ServerSocket dient dazu, auf Client-Requests zu warten (listen) und bei<br />

Bedarf eine Verbindung (connection, Socket) zum Client aufzubauen.<br />

Konstruktor:<br />

new ServerSocket (int portnumber)<br />

new ServerSocket (int portnumber, int max)<br />

Mit portnumber gibt man an, auf welche Portnummer die ServerSocket "horcht".<br />

Mit max kann man angeben, wieviele Verbindungen maximal gleichzeitig aktiv sein<br />

durfen (default 50).<br />

Methoden:<br />

Socket accept()<br />

wartet auf eine Verbindungsaufnahme (request) von einem Client und baut<br />

dann eine Verbindung (connection, Socket) zum Client mit der entsprechenden<br />

Portnummer auf.<br />

close()<br />

beendet die ServerSocket.<br />

InetAddress getInetAddress()<br />

liefert den Hostnamen des Servers<br />

int getLocalPort()<br />

liefert die Portnummer<br />

synchronized setSoTimeout(int)<br />

setzt eine Beschrankung fur die maximale Wartezeit des accept(), in Millisekunden,<br />

oder 0 fur unbeschrankt.<br />

synchronized int getSoTimeout()<br />

liefert den Timeout-Wert.<br />

Die Konstruktoren und Methoden konnen die Fehlersituation IOException werfen,<br />

z.B. wenn bereits ein anderes Programm diese Portnummer verwendet.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 139


Socket (connection)<br />

Die Klasse Socket dient fur die Verbindung (connection) zwischen Client und Server.<br />

Konstruktor:<br />

new Socket (String hostname, int portnumber)<br />

baut eine Verbindung zum angegebenen Rechner (z.B. Server) unter der angegebenen<br />

Portnummer auf.<br />

Methoden:<br />

InputStream getInputStream()<br />

onet einen Datenstrom zum Empfangen (Lesen) von Informationen uber die<br />

Verbindung<br />

OutputStream getOutputStream()<br />

onet einen Datenstrom zum Senden (Schreiben) von Informationen uber die<br />

Verbindung<br />

synchronized close()<br />

beendet die Verbindung (connection).<br />

InetAddress getLocalAddress()<br />

liefert den eigenen Hostnamen (z.B. des Client)<br />

InetAddress getInetAddress()<br />

liefert den Hostnamen des anderen Rechners (z.B. des Servers)<br />

int getLocalPort()<br />

liefert die Portnummer<br />

synchronized setSoTimeout(int)<br />

setzt eine Beschrankung fur die maximale Wartezeit beim Lesen im Input-<br />

Stream, in Millisekunden, oder 0 fur unbeschrankt.<br />

synchronized int getSoTimeout()<br />

liefert den Timeout-Wert.<br />

Die Konstruktoren und Methoden konnen die Fehlersituation IOException oder InterruptedException<br />

werfen, z.B. wenn der Rechnername ungultig ist oder der Server<br />

keine Verbindung unter dieser Portnummer akzeptiert oder wenn beim Lesen ein<br />

Timeout passiert.<br />

Die Datenstrome konnen genauso wie "normale" Datenstrome (siehe oben) zum<br />

Lesen bzw. Schreiben verwendet werden und zu diesem Zweck mit weiteren Datenstromen<br />

wie BueredInputStream, BueredOutputStream, DataInputStream,<br />

InputStreamReader, OutputStreamWriter, BueredReader, BueredWriter, Print-<br />

Writer kombiniert werden.<br />

Lese-Befehle (read, readLine) warten dann jeweils, bis entsprechende Daten von der<br />

Gegenstelle gesendet werden und uber die Verbindung ankommen.<br />

Um eine eziente Ubertragung uber das Netz zu erreichen, wird die Verwendung<br />

von Puerung empfohlen, dann darf aber beim Schreiben die Methode ush() nicht<br />

vergessen werden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 140


Fur die Verarbeitung von "Befehlen", die aus mehreren Wortern oder Feldern bestehen,<br />

kann die Klasse StringTokenizer oder StreamTokenizer verwendet werden<br />

(siehe die Online-Dokumentation).<br />

10.4 Beispiel: typischer Aufbau eines Servers<br />

ServerSocket<br />

Das Hauptprogramm des Servers, das auf die Portnummer "horcht" hat folgenden<br />

Aufbau:<br />

import java.net.* ;<br />

public class ServerMain {<br />

public static void main (String[] args) {<br />

ServerSocket server = null;<br />

Socket s = null;<br />

ServerCon doIt;<br />

Thread t;<br />

int port = ...;<br />

}<br />

}<br />

try {<br />

server = new ServerSocket (port);<br />

while(true) {<br />

s = server.accept();<br />

doIt = new ServerCon (s);<br />

t = new Thread (doIt);<br />

t.start();<br />

}<br />

} catch (Exception e) {<br />

try { server.close(); } catch (Exception e2) {}<br />

System.out.println("ServerMain " +e);<br />

System.exit(1);<br />

}<br />

Socket<br />

Das fur jede Verbindung aufgerufene Server-Programm ist ein Thread mit folgendem<br />

Aufbau:<br />

import java.net.* ;<br />

import java.io.* ;<br />

public class ServerCon implements Runnable {<br />

private Socket socket;<br />

private BufferedReader in;<br />

private PrintWriter out;<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 141


public ServerCon (Socket s) {<br />

socket = s;<br />

}<br />

}<br />

public void run() {<br />

try {<br />

out = new PrintWriter<br />

(new BufferedWriter<br />

(new OutputStreamWriter<br />

(socket.getOutputStream() ) ) );<br />

in = new BufferedReader<br />

(new InputStreamReader<br />

(socket.getInputStream() ) );<br />

...<br />

... in.readLine() ...<br />

...<br />

out.println(...);<br />

out.flush();<br />

...<br />

in.close();<br />

out.close();<br />

socket.close();<br />

} catch (Exception e) {<br />

System.out.println("ServerCon " + e);<br />

}<br />

}<br />

10.5 Beispiel: typischer Aufbau eines Client<br />

import java.net.* ;<br />

import java.io.* ;<br />

public class ClientCon {<br />

public static void main (String[] args) {<br />

int port = ...;<br />

String host = "...";<br />

Socket socket;<br />

BufferedReader in;<br />

PrintWriter out;<br />

try {<br />

socket = new Socket (host, port);<br />

out = new PrintWriter<br />

(new BufferedWriter<br />

(new OutputStreamWriter<br />

(socket.getOutputStream() ) ) );<br />

in = new BufferedReader<br />

(new InputStreamReader<br />

(socket.getInputStream() ) );<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 142


}<br />

}<br />

...<br />

out.println(...);<br />

out.flush();<br />

...<br />

... in.readLine() ...<br />

...<br />

out.close();<br />

in.close();<br />

socket.close();<br />

} catch (Exception e) {<br />

System.out.println ("ClientCon " + e);<br />

}<br />

10.6 Ubung: einfache Client-Server-Applikation<br />

Schreiben Sie einen Server (als Applikation), der auf Verbindungsaufnahmen wartet<br />

und an jeden Client zunachst einen Willkommensgru und dann - 6 mal (also ca.<br />

1 Minute lang) in Abstanden von ungefahr 10 Sekunden - jeweils zwei Textzeilen<br />

liefert, die einen kurzen Text und Datum und Uhrzeit enthalten, und schlielich die<br />

Verbindung zum Client schliet.<br />

Fur die Datums- und Zeitangabe verwenden Sie das Standard-Format der aktuellen<br />

Uhrzeit, das Sie mit<br />

( new Date() ).toString()<br />

erhalten, auch wenn dabei nicht die richtige Zeitzone verwendet wird. (Mehr uber<br />

die Problematik von Datums- und Zeitangaben nden Sie im Kapitel uber Datum<br />

und Uhrzeit).<br />

Schreiben Sie einen Client (als Applikation), der mit diesem Server Verbindung<br />

aufnimmt und alle Informationen, die vom Server gesendet werden, Zeile fur Zeile<br />

auf die Standard-Ausgabe ausgibt.<br />

Testen Sie dieses System. Die Beendigung des Servers (und auch des Clients, falls<br />

er Probleme macht) erfolgt durch Abbruch des Programmes mittels Ctrl-C.<br />

Fur diese Ubung mussen Sie die Hostnamen der verwendeten Rechner (innerhalb<br />

des lokalen Netzes) kennen und sich auf eine Portnummer einigen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 143


11. System-Funktionen und Utilities<br />

Einer der groen Vorteile von <strong>Java</strong> ist die umfangreiche Klassenbibliothek, die fur<br />

eine Unmenge von Anwendungsbereichen bereits fertige Programme und Klassen<br />

enthalt, die einfach und bequem verwendet werden konnen.<br />

Ein paar typische Beispiele fur besonders interessante Klassen sind:<br />

Paket java.lang<br />

Klassen Object, Class, System, Runtime, Process,<br />

String, StringBuer, Math, Integer, Double ...<br />

Paket java.util<br />

Date, GregorianCalendar ...<br />

StringTokenizer,<br />

Vector, Hashtable, LinkedList ...<br />

Paket java.text<br />

SimpeDateFormat, DecimalFormat, ...<br />

Paket java.awt<br />

Toolkit, PrintJob ...<br />

Pakete javax.swing, javax.swing.xxxx<br />

ListModel, TableModel, TreeModel ...<br />

Fur die Details wird auf die Online-Dokumentation verwiesen. Zu einigen dieser<br />

Klassen nden Sie nachfolgend ein paar Hinweise.<br />

11.1 Datum und Uhrzeit (Date)<br />

Fur die Verarbeitung von Datums- und Zeitangaben mu das Package java.util importiert<br />

werden, fur die DateFormat-Klassen zusatzlich das Package java.text.<br />

Im JDK ab Version 1.1 mu fur die "richtige", fur alle Lander der Welt brauchbare<br />

Verarbeitung von Datums- und Zeitangaben eine Kombination von mehreren Klassen<br />

fur Datum und Uhrzeit, Datums-Berechnungen (Kalender), Zeitzonen, Sprachen<br />

und Ausgabeformate verwendet werden. Ein kurzes Beispiel folgt unten.<br />

Die Verwendung ist dementsprechend kompliziert, auerdem enthalten die meisten<br />

Implementierungen auch verschiedene Fehler (Bugs).<br />

Fur einfache Anwendungen konnen die alten Funktionen der Date-Klasse Version<br />

1.0 verwendet werden (siehe anschlieend).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 144


11.2 Date Version 1.0<br />

Konstruktoren<br />

Die hier beschriebenen Funktionen der Klasse Date werden vom Compiler mit der<br />

Warnung "deprecated" versehen, sind aber fur einfache Anwendungen ausreichend<br />

und wesentlich einfacher zu programmieren als die neuen Funktionen von Version<br />

1.1 (siehe unten).<br />

new Date()<br />

setzt Datum und Uhrzeit auf heute und die aktuelle Zeit.<br />

new Date (year, month, day)<br />

setzt das Datum auf den angegebenen Tag (siehe unten) und die Uhrzeit auf<br />

0 Uhr.<br />

new Date(year, month, day, hour, minutes)<br />

setzt Datum und Uhrzeit auf die angegebene Zeit (siehe unten).<br />

new Date(year, month, day, hour, minutes, seconds)<br />

setzt Datum und Uhrzeit auf die angegebene Zeit (siehe unten).<br />

new Date(long)<br />

setzt Datum und Uhrzeit auf die angegebene Zeit im Millisekunden (siehe<br />

unten).<br />

Jahre mussen relativ zum Jahr 1900 angegeben werden, also<br />

-8 bedeutet das Jahr 1892,<br />

98 bedeutet das Jahr 1998,<br />

101 bedeutet das Jahr 2001,<br />

1990 bedeutet das Jahr 3890.<br />

Monate mussen im Bereich 0 bis 11 angegeben werden, also<br />

0fur Janner,<br />

1fur Februar, usw. bis<br />

11 fur Dezember.<br />

Dies ist fur die Verwendung als Array-Index gunstig, fuhrt aber sonst leicht zu<br />

Irrtumern. Es wird daher empfohlen, statt der Zahlenangaben lieber die in der Klasse<br />

Calendar (Version 1.1) denierten symbolischen Namen zu verwenden:<br />

Calendar.JANUARY fur Janner,<br />

Calendar.FEBRUARY fur Februar,<br />

Calendar.MARCH fur Marz, usw. bis<br />

Calendar.DECEMBER fur Dezember.<br />

Tage innerhalb der Monate werden wie gewohnt im Bereich 1 bis 31 angegeben.<br />

Wochentage werden im Bereich 0 bis 6 angegeben, dafur sollten aber lieber die<br />

symbolischen Namen<br />

Calendar.SUNDAY fur Sonntag,<br />

Calendar.MONDAY fur Montag, usw. bis<br />

Calendar.SATURDAY fur Samstag<br />

verwendet werden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 145


Stunden werden im Bereich 0 bis 23 angegeben, Minuten und Sekunden im<br />

Bereich 0 bis 59.<br />

Fur alle bisher genannten Zahlen wird der Typ int verwendet.<br />

Fur die Berechnung von Zeitdierenzen wird eine Groe in Millisekunden verwendet,<br />

deren Nullpunkt am 1. Janner 1970 um 0 Uhr liegt. Dafur wird der Typ long<br />

verwendet.<br />

Methoden<br />

int getTime()<br />

liefert den Zeitpunkt in Millisekunden (siehe oben).<br />

int getYear()<br />

liefert das Jahr (relativ zu 1900, siehe oben).<br />

int getMonth()<br />

liefert den Monat (0-11, siehe oben).<br />

int getDate()<br />

liefert den Tag innerhalb des Monats (1-31).<br />

int getDay()<br />

liefert den Wochentag (0-6, siehe oben).<br />

int getHours()<br />

liefert die Stunde (0-23).<br />

int getMinutes()<br />

liefert die Minuten (0-59).<br />

int getSeconds()<br />

liefert die Sekunden (0-59, bei Schaltsekunden auch 60).<br />

setTime(long)<br />

setzt Datum und Uhrzeit auf den angegebenen Zeitpunkt in Millisekunden<br />

(siehe oben).<br />

setYear(int)<br />

setMonth(int)<br />

setDate(int)<br />

setHours(int)<br />

setMinutes(int)<br />

setSeconds(int)<br />

andert jeweils nur das angegebene Feld (siehe oben).<br />

boolean after(Date)<br />

liefert true, wenn der Zeitpunkt spater als der angegebene liegt.<br />

boolean before(Date)<br />

liefert true, wenn der Zeitpunkt fruher als der angegebene liegt.<br />

boolean equals(Date)<br />

liefert true, wenn die beiden Zeiten gleich sind.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 146


String toString(Date)<br />

liefert einen TextString, der Datum, Uhrzeit und Zeitzone in dem auf Unix-<br />

Rechnern ublichen Format angibt.<br />

String toGMTString(Date)<br />

liefert einen TextString, der Datum und Uhrzeit in dem am Internet (z.B. im<br />

Date-Header von Electronic Mail) ublichen Format angibt.<br />

String toLocaleString(Date)<br />

liefert einen TextString, der Datum, Uhrzeit und Zeitzone in einer auf dem<br />

lokalen System (in der lokalen Sprache und Zeitzone) ublichen Format angibt.<br />

Auerdem gibt es eine statische Methode<br />

long Date.parse (String)<br />

mit der ein Datums-String in einem genormten Format (z.B. Unix- oder Internet-<br />

Format, siehe oben) in den entsprechenden Zeitpunkt in Millisekunden umgewandelt<br />

wird.<br />

Wenn man mit den vorgefertigten Ausgabeformaten nicht zufrieden ist, kann man<br />

eine eigene Version einer DateFormat-Klasse schreiben, die die gewunschte Datums-<br />

Darstellung liefert. Damit die Verwendung zur Klasse DateFormat von Version 1.1<br />

kompatibel ist, sollte diese Methode die folgende Signature haben:<br />

public String format (Date d)<br />

Beispiel fur ein einfaches, selbst geschriebenes DateFormat:<br />

import java.util.*;<br />

public class MyDateFormat { // Date Version 1.0<br />

public String format (Date d) {<br />

String s;<br />

// like SimpleDateFormat("d. M. yyyy")<br />

s = d.getDate() + ". " +<br />

(d.getMonth()+1) + ". " +<br />

(d.getYear()+1900);<br />

return s;<br />

}<br />

}<br />

Beispiel fur die einfache Verarbeitung von Datums-Angaben in Version 1.0:<br />

import java.util.*;<br />

public class Date10 { // Date Version 1.0<br />

public static void main (String[] args) {<br />

MyDateFormat df = new MyDateFormat();<br />

Date today = new Date();<br />

long todayInt = today.getTime();<br />

int currentYear = today.getYear() + 1900;<br />

System.out.println ("Today is " +<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 147


df.format(today) );<br />

System.out.println ("The current year is " +<br />

currentYear );<br />

long yesterdayInt = todayInt - 24*60*60*1000L;<br />

Date yesterday = new Date (yesterdayInt);<br />

System.out.println ("Yesterday was " +<br />

df.format(yesterday) );<br />

long next30Int = todayInt + 30*24*60*60*1000L;<br />

Date next30 = new Date (next30Int);<br />

System.out.println ("30 days from today is " +<br />

df.format(next30) );<br />

Date marriage = new Date (90, Calendar.FEBRUARY, 7);<br />

long marriageInt = marriage.getTime();<br />

int marriageYear = marriage.getYear() + 1900;<br />

System.out.println ("Married on " +<br />

df.format(marriage) );<br />

System.out.println ("Married for " +<br />

(currentYear-marriageYear) + " years." );<br />

System.out.println ("Married for " +<br />

(todayInt-marriageInt)/(24*60*60*1000L) +<br />

" days." );<br />

Date silver= new Date (marriageInt);<br />

silver.setYear( marriage.getYear()+25 );<br />

// works for all dates except Feb 29th<br />

System.out.println ("Silver marriage on " +<br />

df.format(silver) );<br />

if ( silver.getYear() == today.getYear() &&<br />

silver.getMonth() == today.getMonth() &&<br />

silver.getDate() == today.getDate() )<br />

System.out.println ("Congratulations!");<br />

}<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 148


11.3 Date und Calendar Version 1.1<br />

Klassen<br />

Im JDK 1.1 soll fur die "richtige",fur alle Lander der Welt brauchbare Verarbeitung<br />

von Datums- und Zeitangaben eine Kombination der folgenden Klassen verwendet<br />

werden:<br />

Calendar bzw. GregorianCalendar fur Datums- und Zeit-Berechnungen<br />

(mit Fehlerkontrollen)<br />

DateFormat bzw. SimpleDateFormat fur die Darstellung von Datum und<br />

Uhrzeit als Textstring<br />

TimeZone bzw. SimpleTimeZone fur die Zeitzone<br />

Locale fur das Land oder die Sprache<br />

Date fur Zeitpunkte<br />

Die Klasse Date soll in diesem Fall nur fur die Speicherung eines Zeitpunkts verwendet<br />

werden. Von den oben fur Version 1.0 angefuhrten get- und set-Methoden sollen<br />

nur diejenigen verwendet werden, die den Zeitpunkt in Millisekunden angeben. Fur<br />

die Angabe von Jahr, Monat, Tag und Uhrzeit sollen stattdessen die "besseren"<br />

Methoden des Kalenders verwendet werden.<br />

Die richtige Kombination und Verwendung dieser Klassen ist einigermaen kompliziert.<br />

Auerdem enthalten manche Implementierungen ein paar Fehler (Bugs) oder<br />

unterstutzen nicht alle Lander und Sprachen. Deshalb greifen viele <strong>Java</strong>-Benutzer<br />

auf die alte Version 1.0 oder auf selbst geschriebene Klassen wie z.B. BigDate zuruck.<br />

Hier wird nur ein kurzes Beispiel fur typische Anwendungen gegeben. Fur die Details<br />

wird auf die Online-Dokumentation und auf die Fragen und Antworten in den<br />

einschlagigen Usenet-Newsgruppen verwiesen (siehe Referenzen).<br />

Beispiel fur Datums- und Zeit-Angaben und -Berechungen in Version 1.1:<br />

import java.util.*;<br />

import java.text.*;<br />

public class Date11 { // Date Version 1.1<br />

public static void main (String[] args) {<br />

DateFormat df = new SimpleDateFormat ("d. MMMM yyyy",<br />

Locale.GERMANY);<br />

DateFormat tf = new SimpleDateFormat ("HH.mm",<br />

Locale.GERMANY);<br />

SimpleTimeZone mez = new SimpleTimeZone( +1*60*60*1000,<br />

"CET");<br />

mez.setStartRule (Calendar.MARCH, -1, Calendar.SUNDAY,<br />

2*60*60*1000);<br />

mez.setEndRule (Calendar.OCTOBER, -1, Calendar.SUNDAY,<br />

2*60*60*1000);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 149


Calendar cal = GregorianCalendar.getInstance (mez);<br />

cal.setLenient(false); // do not allow bad values<br />

Date today = new Date();<br />

System.out.println ("Heute ist der " +<br />

df.format(today) );<br />

System.out.println ("Es ist " +<br />

tf.format(today) + " Uhr");<br />

cal.setTime(today);<br />

int currentYear = cal.get(Calendar.YEAR);<br />

System.out.println ("Wir haben das Jahr " +<br />

currentYear );<br />

cal.add (Calendar.DATE, -1);<br />

Date yesterday = cal.getTime();<br />

System.out.println ("Gestern war der " +<br />

df.format(yesterday) );<br />

try {<br />

cal.set (1997, Calendar.MAY, 35);<br />

cal.setTime(cal.getTime()); // to avoid a bug<br />

Date bad = cal.getTime();<br />

System.out.println ("Bad date was set to " +<br />

df.format(bad) );<br />

} catch (Exception e) {<br />

System.out.println ("Invalid date was detected "<br />

+ e);<br />

}<br />

cal.set (1996, Calendar.FEBRUARY, 29);<br />

cal.setTime(cal.getTime()); // to avoid a bug<br />

Date marriage = cal.getTime();<br />

System.out.println ("geheiratet am " +<br />

df.format(marriage) );<br />

long todayInt = today.getTime();<br />

long marriageInt = marriage.getTime();<br />

long diff = todayInt - marriageInt;<br />

System.out.println ("seit " +<br />

diff/(24*60*60*1000L) +<br />

" Tagen verheiratet" );<br />

int marriageYear = cal.get(Calendar.YEAR);<br />

System.out.println ("seit " +<br />

(currentYear-marriageYear) +<br />

" Jahren verheiratet" );<br />

cal.setTime(marriage);<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 150


* bypass leap year error in add YEAR method: */<br />

if ( (cal.get(Calendar.MONTH) == Calendar.FEBRUARY) &&<br />

(cal.get(Calendar.DATE) == 29) ) {<br />

cal.add (Calendar.DATE, 1);<br />

}<br />

/* end of leap year error bypass */<br />

cal.add (Calendar.YEAR, 25);<br />

Date silverMarriage = cal.getTime();<br />

System.out.println ("Silberne Hochzeit am " +<br />

df.format(silverMarriage) );<br />

}<br />

}<br />

String todayDay = df.format(today);<br />

String silverDay = df.format(silverMarriage);<br />

// compare only day, not time:<br />

if ( silverDay.equals(todayDay) )<br />

System.out.println ("Herzlichen Glueckwunsch!");<br />

11.4 Zeitmessung<br />

Fur die Berechnung von Laufzeiten kann man entweder Date-Objekte (siehe oben)<br />

oder die folgende statische Methode verwenden:<br />

static long System.currentTimeMillis()<br />

liefert den aktuellen Zeitpunkt in Millisekunden.<br />

Beispiel:<br />

public static void main (String[] args) {<br />

long startTime = System.currentTimeMillis();<br />

... // do something<br />

long endTime = System.currentTimeMillis();<br />

long runTime = endTime - startTime;<br />

float runSeconds = ( (float)runTime ) / 1000.F;<br />

System.out.println ("Run time was " + runSeconds + " seconds." );<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 151


11.5 Ausdrucken (PrintJob, PrinterJob)<br />

PrintJob<br />

Das AWT Version 1.1 enthalt auch eine Klasse PrintJob, mit der ein Printout erzeugt<br />

und mit Hilfe des systemspezischen Printer-Selection-Dialog auf einem Drucker<br />

ausgedruckt werden kann.<br />

Dazu dienen die folgenden Methoden in den verschiedenen Klassen:<br />

Toolkit getToolkit()<br />

liefert bei einem Frame das Toolkit, das fur die Darstellung des Frame und<br />

der in ihm enthaltenen Komponenten auf dem System zustandig ist.<br />

PrintJob getPrintjob(Frame, String, Properties)<br />

erzeugt bei einem Toolkit einen Printjob fur das Frame, mit dem angegebenen<br />

Title-String und eventuellen Druckereigenschaften (oder null).<br />

Graphics getGraphics()<br />

liefert bei einem Printjob das Graphics-Objekt, das einen Printout enthalten<br />

kann. Fur jede neue Seite soll ein neues Graphics-Element angelegt werden.<br />

Dieses Graphics-Element kann mit beliebigen Graphik-Operationen gefullt<br />

werden. Meistens verwendet man aber nur die folgenden beiden Methoden:<br />

print (Graphics g)<br />

bei einer AWT-Komponente stellt einen Printout nur dieser Komponente in<br />

das Graphics-Objekt.<br />

printAll (Graphics g)<br />

bei einem AWT-Container wie z.B. Frame oder Applet stellt einen Printout<br />

dieses Containers mit seinem gesamten Inhalt in das Graphics-Objekt.<br />

dispose()<br />

fur das Graphics-Objekt setzt das fertig erstellte Graphics-Objekt (eine Seite<br />

des Printout) in den Printout.<br />

end()<br />

fur den PrintJob beendet den Printout. Nun wird er vom Print-Spooling des<br />

Systems an den Drucker gesendet, und danach kann der Drucker wieder fur<br />

andere Jobs verwendet werden.<br />

Beispielskizze:<br />

Frame f = new Frame ("Test");<br />

f.setLayout(...);<br />

f.add(...);<br />

...<br />

Toolkit t = f.getToolkit();<br />

PrintJob pJob = t.getPrintjob (f, "Test", null);<br />

Graphics g = pJob.getGraphics();<br />

f.printAll(g); // or g.drawxxx ...<br />

g.dispose();<br />

pJob.end();<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 152


Wenn man ein Applet ausdrucken will, mu man mit getParent() das zugehorige<br />

Frame bestimmen und dann dieses in getPrintJob angeben. Auerdem mu der<br />

Benutzer dem Applet mit dem SecurityManager die Erlaubnis zum Drucken am<br />

Client-Rechner geben.<br />

PrinterJob<br />

Ab JDK 1.2 gibt es eine neue Klasse PrinterJob mit den Interfaces Printable und<br />

Pageable im Package java.awt.print.<br />

Dazu dienen unter anderem die folgenden Klassen und Methoden:<br />

PrinterJob.getPrinterJob()<br />

liefert ein PrinterJopb-Objekt.<br />

setPrintable (Printable)<br />

gibt an, welches Objekt gedruckt werden soll. Dieses Objekt mu das Interface<br />

Printable implementieren, also eine print-Methode enthalten.<br />

Die print-Methode im PrinterJob bewirkt, da die print-Methode des<br />

Printable-Objekts aufgerufen und das Ergebnis an den Drucker gesendet wird<br />

(oder die PrintException geworfen wird).<br />

Die print-Methode des Printable-Objekts hat die folgenden Parameter:<br />

{ das Graphics-Objekt, das wie in der paint-Methode (oder durch Aufruf<br />

der paint-Methode oder der printAll-Methode) mit der graphischen Information<br />

gefullt werden mu, eventuell mit Verschiebung des Eckpunktes<br />

mittels translate,<br />

{ ein PageFormat-Objekt, und<br />

{ die Seitennummer (pageIndex).<br />

und mu einen der folgenden beiden Werte zuruckgeben:<br />

{ PrinterJob.PAGE EXISTS<br />

wenn eine Seite erzeugt wurde,<br />

{ PrinterJob.NO SUCH PAGE<br />

wenn keine Seite erzeugt wurde.<br />

Beispielskizze:<br />

public class Xxxx extends Frame<br />

implements ActionListener, Printable {<br />

...<br />

public void actionPerformed(ActionEvent e) {<br />

if (e.getSource() == printButton) {<br />

PrinterJob printJob = PrinterJob.getPrinterJob();<br />

printJob.setPrintable(this);<br />

try {<br />

printJob.print();<br />

} catch (PrintException ex) {<br />

}<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 153


Sonstige Moglichkeiten<br />

}<br />

}<br />

public int print(Graphics g, PageFormat pageFormat, int pageIndex) {<br />

if (pageIndex == 0) {<br />

g.translate(100, 100);<br />

paint(g); // or: this.printAll(g); or: g.drawxxx ...<br />

return Printable.PAGE_EXISTS;<br />

}<br />

return Printable.NO_SUCH_PAGE;<br />

}<br />

}<br />

Auerdem konnen mit PrinterJob auch Objekte, die das Interface Pageable implementieren,<br />

ausgedruckt werden, das sind Dokumente, die aus mehreren Seiten<br />

(Page) bestehen, mit Seiteninhalt, Kopf- und Fuzeilen und Seitennummern. Die<br />

Klasse Book ist eine Klasse, die dieses Interface implementiert.<br />

Weitere Alternativen zur Verwendung von PrintJob sind die Ausgabe auf das<br />

Pseudo-File mit den Filenamen "lpt1" oder die Verwendung der Print-Screen-<br />

Funktion durch den Benutzer, um den aktuellen Fensterinhalt (z.B. eine Web-Page<br />

mit einem Applet mit Benutzer-Eingaben) auszudrucken. In manchen Fallen kann<br />

es auch gunstig sein, die Information, die ausgedruckt werden soll, als HTML-File<br />

zu erzeugen, das dann vom Benutzer in seinem Web-Browser angezeigt und ausgedruckt<br />

werden kann.<br />

11.6 Ausfuhrung von Programmen (Runtime, exec)<br />

Mit der Klasse Runtime und deren Methode exec kann man innerhalb von Applikationen<br />

andere Programme (Hauptprogramme, Prozesse) starten. Dies hat den Vorteil,<br />

da man alle Funktionen des Betriebssystems ausnutzen kann, und den Nachteil,<br />

da die <strong>Java</strong>-Applikation dadurch nicht mehr Plattform- oder Rechner-unabhangig<br />

ist<br />

Applets konnen im allgemeinen keine anderen Programme starten.<br />

Fur die Verwendung von Runtime und Process mu das Package java.util importiert<br />

werden, im Fall von Ein-Ausgabe-Operationen auch java.io.<br />

Die fur diesen Zweck wichtigsten Methoden der Klasse Runtime sind:<br />

static Runtime Runtime.getRuntime()<br />

liefert das Runtime-Objekt der <strong>Java</strong> Virtual Machine<br />

Process exec(String)<br />

erzeugt einen Proze, der den im String enthaltenen Befehl (Befehlswort und<br />

eventuell Parameter) ausfuhrt.<br />

Process exec(String[])<br />

erzeugt einen Proze, der den im String-Array enthaltenen Befehl (Befehlswort<br />

und Parameter) ausfuhrt.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 154


Die exec-Methode kann die Fehlersituation IOException werfen, wenn es den Befehl<br />

(das Programm) nicht gibt.<br />

Die wichtigsten Methoden der Klasse Process sind:<br />

waitFor()<br />

wartet, bis der Proze fertig gelaufen ist.<br />

destroy()<br />

bricht den Proze ab.<br />

int exitValue()<br />

liefert den Return-Code (Exit-Status) des Prozesses (meist 0 fur okay, ungleich<br />

0fur Fehler)<br />

InputStream getInputStream()<br />

liefert einen InputStream zum Lesen der vom Proze geschriebenen Standard-<br />

Ausgabe.<br />

InputStream getErrorStream()<br />

liefert einen InputStream zum Lesen der vom Proze geschriebenen Fehler-<br />

Ausgabe.<br />

OutputStream getOutputStream()<br />

liefert einen OutputStream zum Schreiben der vom Proze gelesenen Standard-<br />

Eingabe.<br />

Die waitFor-Methode kann die Fehlersituation InterruptedException werfen, wenn<br />

das Programm wahrend des Wartens abgebrochen wird.<br />

Beispiel (Unix):<br />

try {<br />

Process p = Runtime.getRuntime().exec<br />

("/usr/local/bin/elm");<br />

p.waitFor();<br />

} catch (Exception e) {<br />

System.err.println("elm error " +e);<br />

}<br />

Das analoge Beispiel fur einen PC enthalt<br />

Process p = Runtime.getRuntime().exec<br />

("c:\\public\\pegasus\\pmail.exe");<br />

Befehlsnamen mussen im allgemeinen mit dem Pfad angegeben werden.<br />

Auf PCs mu man beachten, da man als Befehlsname nur "echte" exe- oder com-<br />

Programme angeben kann. Die meisten DOS-Befehle wie DIR oder COPY sind aber<br />

nicht eigene Programm-Files sondern werden von der "Shell" COMMAND.COM<br />

(unter DOS, Windows 3 und Windows 95) bzw. CMD.EXE (unter Windows NT)<br />

ausgefuhrt. Beispiel:<br />

Process p = Runtime.getRuntime().exec<br />

("command.com /c dir");<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 155


Wenn man unter Unix eine Eingabe- oder Ausgabe-Umleitung oder Pipe fur den<br />

Befehl angeben will, mu man analog zuerst eine Unix-Shell aufrufen und dieser<br />

Shell dann den kompletten Befehl (einschlielich der Umleitung) als einen einzigen<br />

String-Parameter angeben. Beispiel:<br />

Process p = Runtime.getRuntime().exec (new String[] {<br />

"/usr/bin/sh", "-c", "/usr/bin/ls > ls.out" } );<br />

Mit Hilfe der Methode getOutputStream kann man Eingaben vom <strong>Java</strong>-Programm<br />

an den Proze senden. Mit Hilfe der Methoden getInputStream und getErrorStream<br />

kann man die vom Proze erzeugte Ausgabe im <strong>Java</strong>-Programm verarbeiten. Beispiel:<br />

try {<br />

String cmd = "/usr/bin/ls -l /opt/java/bin";<br />

String line = null;<br />

Process p = Runtime.getRuntime().exec(cmd);<br />

BufferedReader lsOut = new BufferedReader<br />

(new InputStreamReader<br />

(p.getInputStream() ) );<br />

while( ( line=lsOut.readLine() ) != null) {<br />

System.out.println(line);<br />

}<br />

} catch (Exception e) {<br />

System.err.println("ls error " +e);<br />

}<br />

Wenn man allerdings zwei oder alle drei dieser Eingabe- und Ausgabe-Strome lesen<br />

bzw. schreiben will, mu man das in getrennten Threads tun, weil sonst ein auf<br />

Eingabe wartendes Read die anderen blockiert.<br />

11.7 Verwendung von Unterprogrammen (native methods, JNI)<br />

Man kann innerhalb von <strong>Java</strong>-Applikationen auch Unterprogramme aufrufen, die<br />

in einer anderen Programmiersprache geschrieben sind, insbesondere in den Programmiersprachen<br />

C und C++. Solche Unterprogramme werden als "eingeborene"<br />

(native) Methoden bezeichnet, das entsprechende Interface als <strong>Java</strong> Native Interface<br />

(JNI). Der Vorteil liegt darin, da man samtliche von dieser Programmiersprache<br />

unterstutzten Funktionen und Unterprogramm-Bibliotheken verwenden kann.<br />

Der Nachteil liegt darin, da die <strong>Java</strong>-Applikation dann im allgemeinen nicht mehr<br />

Plattform- oder auch nur Rechner-unabhangig ist.<br />

Der Vorgang lauft in folgenden Schritten ab:<br />

Zunachst wird eine <strong>Java</strong>-Klasse geschrieben, die folgende Elemente enthalt:<br />

die Deklaration der native Methode. Diese Deklaration enthalt nur die Signature,<br />

mit der zusatzlichen Angabe "native", und dann nur einen Strichpunkt,<br />

keinen Statement-Block. Dieser wird spater in der Programmiersprache C oder<br />

C++ geschrieben.<br />

einen statischen Block (static), der die zugehorige Laufzeit-Bibliothek ladt.<br />

Beispiel:<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 156


public class ClassName {<br />

public native void name() ;<br />

static {<br />

System.loadLibrary ("libname");<br />

}<br />

}<br />

Diese Klasse kann wie jede normale Klasse verwendet werden, d.h. man kann Objekte<br />

dieser Klasse mit new anlegen und ihre Methoden fur dieses Objekt aufrufen.<br />

Als nachstes werden mit dem Hilfsprogramm javah Header-Files und ein sogenanntes<br />

Stub-File erstellt. Diese Files enthalten die entsprechenden Deklarationen in C-<br />

Syntax, die dann vom C-Programm verwendet werden. Es gibt auch Umwandlungs-<br />

Programme fur die Umwandlung von <strong>Java</strong>-Strings in C-Strings und umgekehrt.<br />

Unter Verwendung dieser Hilfsmittel wird nun das C-Programm geschrieben und<br />

ubersetzt und in einer Library (Bibliotheks-File) fur dynamisches Laden zur Laufzeit<br />

gespeichert. Diese Library mu in die Environment-Variable LD LIBRARY PATH<br />

hinzugefugt werden.<br />

Schlielich werden die <strong>Java</strong>-Klassen mit dem <strong>Java</strong>-Compiler javac ubersetzt und<br />

mit dem Befehl java ausgefuhrt. Dabei wird das C-Programm automatisch aus der<br />

vorher erstellten Library dazugeladen.<br />

Fur die Details wird auf die Online-Dokumentation und auf die einschlagige Literatur<br />

verwiesen.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 157


12. Datenbanken<br />

Zu den wichtigsten Anwendungsgebieten von <strong>Java</strong> zahlen User-Interfaces zu Datenbanksystemen.<br />

Das <strong>Java</strong>-Programm kann dabei ein Applet, eine Applikation oder ein Servlet sein<br />

und kann am selben Rechner wie die Datenbank laufen oder auch auf einem anderen<br />

Rechner und von dort uber das Internet oder ein Intranet auf die Datenbank<br />

zugreifen (siehe Datenbank-Anwendungen uber das Internet).<br />

Die "<strong>Java</strong> Database Connectivity" (JDBC) ist im Sinne der Plattformunabhangigkeit<br />

von <strong>Java</strong> so aufgebaut, da das <strong>Java</strong>-Programm von der Hard- und<br />

Software des Datenbanksystems unabhangig ist und somit fur alle Datenbanksysteme<br />

(MS-Access, Oracle etc.) funktioniert.<br />

Mit den im JDBC enthaltenen <strong>Java</strong>-Klassen (Package java.sql) kann man Daten in<br />

der Datenbank so bequem speichern und abfragen wie beim Lesen und Schreiben<br />

von Dateien oder Sockets. Auf diese Weise kann man die Vorteile von <strong>Java</strong>, die<br />

vor allem bei der Gestaltung von (graphischen und plattformunabhangigen) User-<br />

Interfaces liegen, mit der Machtigkeit von Datenbanksystemen verbinden.<br />

12.1 Relationale Datenbanken<br />

Relationale Datenbanken bestehen aus Tabellen (Relationen). Die Tabellen entsprechen<br />

in etwa den Klassen in der Objektorientierten Programmierung. Beispiele:<br />

Eine Personaldatenbank enthalt Tabellen fur Mitarbeiter, Abteilungen, Projekte.<br />

Eine Literaturdatenbank entalt Tabellen fur Bucher, Zeitschriften, Autoren, Verlage.<br />

Diese Tabellen konnen in Beziehungen zueinander stehen (daher der Name "Relation").<br />

Beispiele: Ein Mitarbeiter gehort zu einer Abteilung und eventuell zu einem<br />

oder mehreren Projekten. Jede Abteilung und jedes Projekt wird von einem Mitarbeiter<br />

geleitet. Ein Buch ist in einem Verlag erschienen und hat einen oder mehrere<br />

Autoren.<br />

Beispielskizze fur eine Tabelle "Mitarbeiter":<br />

Abteilung Vorname Zuname Geburtsjahr Gehalt<br />

EDV-Zentrum Hans Fleiig 1972 24000.00<br />

EDV-Zentrum Grete Tuchtig 1949 32000.00<br />

Personalstelle Peter Gscheitl 1968 16000.00<br />

Jede Zeile der Tabelle (row, Tupel, Record) enthalt die Eigenschaften eines Elementes<br />

dieser Menge, entspricht also einem Objekt. In den obigen Beispielen also<br />

jeweils ein bestimmter Mitarbeiter, eine Abteilung, ein Projekt, ein Buch, ein Autor,<br />

ein Verlag. Jede Zeile mu eindeutig sein, d.h. verschiedene Mitarbeiter mussen sich<br />

durch mindestens ein Datenfeld (eine Eigenschaft) unterscheiden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 158


Jede Spalte der Tabelle (column, eld, entity) enthalt die gleichen Eigenschaften<br />

der verschiedenen Objekte, entspricht also einem Datenfeld. Beispiele: Vorname,<br />

Zuname, Geburtsjahr und Abteilung eines Mitarbeiters, oder Titel, Umfang, Verlag<br />

und Erscheinungsjahr eines Buches.<br />

Ein Datenfeld (z.B. die Sozialversicherungsnummer eines Mitarbeiters oder die ISBN<br />

eines Buches) oder eine Gruppe von Datenfeldern (z.B. Vorname, Zuname und<br />

Geburtsdatum einer Person) mu eindeutig sein, sie ist dann der Schlussel (key)<br />

zum Zugri auf die Zeilen (Records) in dieser Tabelle. Eventuell mu man dafur eigene<br />

Schlusselfelder einrichten, z.B. eine eindeutige Projektnummer, falls es mehrere<br />

Projekte mit dem gleichen Namen gibt.<br />

Die Beziehungen zwischen den Tabellen konnen auch durch weitere Tabellen (Relationen)<br />

dargestellt werden, z.B. eine Buch-Autor-Relation, wobei sowohl ein bestimmtes<br />

Buch als auch ein bestimmter Autor eventuell in mehreren Zeilen dieser<br />

Tabelle vorkommen kann, denn ein Buch kann mehrere Autoren haben und ein<br />

Autor kann mehrere Bucher geschrieben haben. Das gleiche gilt fur die Relation<br />

Mitarbeiter-Projekt.<br />

Das Konzept (Design) einer Datenbank ist eine komplexe Aufgabe, es geht dabei<br />

darum, alle relevanten Daten (Elemente, Entities) und alle Beziehungen zwischen<br />

ihnen festzustellen und dann die logische Struktur der Datenbank entsprechend festzulegen.<br />

Die logisch richtige Aufteilung der Daten in die einzelnen Tabellen (Relationen)<br />

wird als Normalisierung der Datenbank bezeichnet, es gibt dafur verschiedene<br />

Regeln und Grundsatze, ein Beispiel ist die sogenannte dritte Normalform.<br />

Fast alle Datenbanksysteme seit Ende der 70er- oder Beginn der 80er-Jahre sind<br />

relationale Datenbanksysteme und haben damit die in den 60er- und 70er-Jahren<br />

verwendeten, blo hierarchischen Datenbanksysteme abgelost.<br />

Eine zukunftweisende Weiterentwicklung der Relationalen Datenbanken sind die<br />

"Objektrelationalen Datenbanken", bei denen - vereinfacht gesprochen - nicht nur<br />

primitive Datentypen sondern auch komplexe Objekte als Datenfelder moglich sind,<br />

ahnlich wie in der objektorientierten Programmierung.<br />

Datenschutz und Datensicherheit<br />

Datenbanken enthalten meist umfangreiche und wichtige, wertvolle Informationen.<br />

Daher mu bei Datenbanksystemen besonderer Wert auf den Datenschutz und die<br />

Datensicherheit gelegt werden.<br />

Die Datenbank-Benutzer werden in 2 Gruppen aufgeteilt: den Datenbankadministrator<br />

und die Datenbankanwender.<br />

Der Datenbankadministrator legt mit der Data Denition Language (DDL) die<br />

logischen Struktur der Datenbank fest und ist fur den Datenschutz, die Vergabe der<br />

Berechtigungen an die Datenbankanwender und fur die Datensicherung verantwortlich.<br />

Die Datenbankanwender konnen mit einer Data Manipulation Language (DML)<br />

oder Query Language die Daten in der Datenbank speichern, abfragen oder<br />

verandern.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 159


Datenkonsistenz<br />

Mit der Hilfe von Usernames und Pawortern werden die einzelnen Benutzer identiziert,<br />

und der Datenbankadministrator kann und mu sehr detailliert festlegen,<br />

welcher Benutzer welche Aktionen (lesen, hinzufugen, loschen, verandern) mit welchen<br />

Teilen der Datenbank (Tabellen, Spalten, Zeilen) ausfuhren darf.<br />

Die in einer Datenbank gespeicherten Informationen stehen meistens in Beziehungen<br />

zueinander, bestimmte Informationen hangen in eventuell recht komplexer Weise<br />

von anderen, ebenfalls in der Datenbank gespeicherten Informationen ab. Es mu<br />

sichergestellt werden, da die gesamte Datenbank immer in einem gultigen Zustand<br />

ist, da also niemals ungultige oder einander widersprechende Informationen darin<br />

gespeichert werden.<br />

Dies wird mittels Transaktionen erreicht: Unter einer Transaktion versteht man<br />

eine Folge von logisch zusammengehorenden Aktionen, die nur entweder alle<br />

vollstandig oder uberhaupt nicht ausgefuhrt werden durfen.<br />

Beispiel: Wenn zwei Mitarbeiter den Arbeitsplatz tauschen, mu sowohl beim Mitarbeiter<br />

1 der Arbeitsplatz von A auf B als auch beim Mitarbeiter 2 der Arbeitsplatz<br />

von B auf A geandert werden. Wurde bei einer dieser beiden Aktionen ein Fehler<br />

auftreten, die andere aber trotzdem ausgefuhrt werden, dann hatten wir plotzlich 2<br />

Mitarbeiter auf dem einen Arbeitsplatz und gar keinen auf dem anderen.<br />

Ein anderes Beispiel: Wenn in der Datenbank nicht nur die Gehalter der einzelnen<br />

Mitarbeiter sondern auch die Summe aller Personalkosten (innerhalb des Budgets)<br />

gespeichert ist, dann mussen bei jeder Gehaltserhohung beide Felder um den gleichen<br />

Betrag erhoht werden, sonst stimmen Budgetplanung und Gehaltsauszahlung nicht<br />

uberein.<br />

Um solche Inkonsistenzen zu vermeiden, mussen zusammengehorende Aktionen jeweils<br />

in eine Transaktion zusammengefat werden:<br />

Wenn alle Aktionen erfolgreich abgelaufen sind, wird die Transaktion beendet<br />

(commit) und die Datenbank ist in einem neuen gultigen Zustand.<br />

Falls wahrend der Transaktion irgendein Fehler auftritt, werden alle seit Beginn<br />

der Transaktion ausgefuhrten unvollstandigen Anderungen ruckgangig<br />

gemacht (rollback), und die Datenbank ist wieder in demselben alten, aber<br />

gultigen Zustand wie vor Beginn der versuchten Transaktion.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 160


12.2 Structured Query Language (SQL)<br />

Datentypen<br />

SQL hat sich seit den 80er-Jahren als die von allen Datenbanksystemen (wenn auch<br />

eventuell mit kleinen Unterschieden) unterstutzte Abfragesprache durchgesetzt, und<br />

die Version SQL2 ist seit 1992 auch oziell genormt.<br />

SQL umfat alle 3 Bereiche der Datenbankbenutzung:<br />

die Denition der Datenbankstruktur,<br />

die Speicherung, Loschung und Veranderung von Daten und<br />

die Abfrage von Daten.<br />

Fur eine komplette Beschreibung von SQL wird auf die Fachliteratur verwiesen, hier<br />

sollen nur ein paar typische Beispiele gezeigt werden.<br />

SQL kennt unter anderem die folgenden Datentypen:<br />

CHAR (n) = ein Textstring mit einer Lange von genau n Zeichen (ahnlich wie<br />

String, wird mit Leerstellen aufgefullt)<br />

VARCHAR (n) = ein Textstring mit einer variablen Lange von maximal n Zeichen<br />

(n < 255)<br />

LONGVARCHAR (n) = ein Textstring mit einer variablen Lange von maximal n<br />

Zeichen (n > 254)<br />

DECIMAL oder NUMERIC = eine als String von Ziern gespeicherte Zahl (ahnlich<br />

wie BigInteger)<br />

INTEGER = eine ganze Zahl (4 Bytes, wie int)<br />

SMALLINT = eine ganze Zahl (2 Bytes, wie short)<br />

BIT = wahr oder falsch (wie boolean)<br />

REAL oder FLOAT = eine Fliekommazahl (wie oat)<br />

DOUBLE = eine doppelt genaue Fliekommazahl (wie double)<br />

DATE = ein Datum (Tag)<br />

TIME = eine Uhrzeit<br />

TIMESTAMP = ein Zeitpunkt (Datum und Uhrzeit, ahnlich wie <strong>Java</strong>-Date)<br />

Denition der Datenbankstruktur (DDL)<br />

CREATE = Einrichten einer neuen Tabelle.<br />

Beispiel:<br />

CREATE TABLE Employees (<br />

INT EmployeeNumber ,<br />

CHAR(30) FirstName ,<br />

CHAR(30) LastName ,<br />

INT BirthYear ,<br />

FLOAT Salary<br />

)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 161


deniert eine Tabelle "Employees" (Mitarbeiter) mit den angegebenen Datenfeldern.<br />

Die Erlaubnis dazu hat meistens nur der Datenbankadministrator.<br />

ALTER = Andern einer Tabellendenition.<br />

DROP = Loschen einer Tabellendenition.<br />

Anderungen an den Daten (Updates)<br />

Abfrage von Daten<br />

INSERT = Speichern eines Records in einer Tabelle.<br />

Beispiel:<br />

INSERT INTO Employees<br />

(EmployeeNumber, FirstName, LastName, BirthYear, Salary)<br />

VALUES ( 4710, 'Hans', 'Fleissig', 1972, 24000.0 )<br />

INSERT INTO Employees<br />

(EmployeeNumber, FirstName, LastName, BirthYear, Salary)<br />

VALUES ( 4711, 'Grete', 'Tuechtig', 1949, 32000.0 )<br />

speichert zwei Mitarbeiter-Records mit den angegebenen Daten.<br />

UPDATE = Verandern von Datenfeldern in einem oder mehreren Records.<br />

Beispiel:<br />

UPDATE Employees<br />

SET Salary = 36000.0 WHERE LastName = 'Tuechtig'<br />

setzt das Gehalt bei allen Mitarbeitern, die Tuechtig heien, auf 36000.<br />

DELETE = Loschen eines oder mehrerer Records<br />

Beispiel:<br />

DELETE Employees WHERE EmployeeNumber = 4710<br />

loscht den Mitarbeiter mit der Nummer 4710 aus der Datenbank.<br />

SELECT = Abfragen von gespeicherten Daten.<br />

Beispiele:<br />

SELECT * FROM Employees<br />

liefert alle Datenfelder von allen Records der Tabelle Employees.<br />

SELECT LastName, FirstName, Salary FROM Employees<br />

liefert die angegebenen Datenfelder von allen Records der Tabelle Employees.<br />

SELECT LastName, Salary<br />

FROM Employees WHERE BirthYear


SELECT * FROM Employees<br />

WHERE LastName = 'Fleissig' AND FirstName LIKE 'H%'<br />

liefert alle Daten derjenigen Mitarbeiter, deren Zuname Fleissig ist und deren Vorname<br />

mit H beginnt.<br />

12.3 Datenbank-Zugrie in <strong>Java</strong> (JDBC)<br />

Mit Hilfe der "<strong>Java</strong> Database Connectivity" (JDBC) kann man innerhalb von<br />

<strong>Java</strong>-Programmen auf Datenbanken zugreifen und Daten abfragen, speichern oder<br />

verandern, wenn das Datenbanksystem die "Standard Query Language" SQL verwendet,<br />

was bei allen wesentlichen Datenbanksystemen seit den 80er-Jahren der Fall<br />

ist.<br />

Im <strong>Java</strong>-Programm werden nur die logischen Eigenschaften der Datenbank und der<br />

Daten angesprochen (also nur die Namen und Typen der Relationen und Datenfelder),<br />

und die Datenbank-Operationen werden in der genormten Abfragesprache<br />

SQL formuliert (Version SQL 2 Entry Level).<br />

Das <strong>Java</strong>-Programm ist somit von der Hard- und Software des Datenbanksystems<br />

unabhangig. Erreicht wird dies durch einen sogenannten "Treiber" (Driver), der zur<br />

Laufzeit die Verbindung zwischen dem <strong>Java</strong>-Programm und dem Datenbanksystem<br />

herstellt - ahnlich wie ein Drucker-Treiber die Verbindung zwischen einem Textverarbeitungsprogramm<br />

und dem Drucker oder zwischen einem Graphikprogramm<br />

und dem Plotter herstellt. Falls die Datenbank auf ein anderes System umgestellt<br />

ist, braucht nur der Driver ausgewechselt werden, und die <strong>Java</strong>-Programme konnen<br />

ansonsten unverandert weiter verwendet werden.<br />

Der JDBC-Driver kann auch uber das Internet bzw. Intranet vom <strong>Java</strong>-Client direkt<br />

auf den Datenbank-Server zugreifen, ohne da man eine eigene Server-Applikation<br />

(CGI oder Servlet) schreiben mu.<br />

Das JDBC ist bereits im <strong>Java</strong> Development Kit JDK enthalten (ab 1.1), und zwar<br />

im Package java.sql. Mit JDK 1.2 kam eine neue Version JDBC 2.0 heraus, die<br />

eine Reihe von zusatzlichen Features enthalt. Im folgenden werden aber nur die<br />

(wichtigen) Features beschrieben, die sowohl in JDBC 1.x als auch in JDBX 2.0<br />

enthalten sind.<br />

Die Software fur die Server-Seite und die JDBC-Driver auf der Client-Seite mussen<br />

vom jeweiligen Software-Hersteller des Datenbanksystems erworben werden (also<br />

z.B. von der Firma Oracle). Dafur gibt es dann eigene Packages wie z.B. sun.jdbc<br />

oder com.rma.produkt. Das JDBC enthalt auch eine sogenannte JDBC-ODBC-<br />

Brucke fur den Zugri auf ODBC-Datenbanken (Open Database Connectivity, z.B.<br />

MS-Access).<br />

Beispielskizze fur eine Datenbank-Abfrage (select)<br />

Hier eine Skizze fur den Aufbau einer typischen Datenbank-Anwendung mit einer<br />

Abfrage von Daten. Mehr Informationen uber die darin vorkommenden Klassen<br />

und Methoden nden Sie in den nachfolgenden Abschnitten und in der Online-<br />

Dokumentation.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 163


import java.sql.*;<br />

...<br />

try {<br />

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");<br />

String username="admin";<br />

String password="";<br />

Connection con = DriverManager.getConnection<br />

("jdbc:odbc://hostname/databasename", username, password);<br />

con.setReadOnly(true);<br />

Statement stmt = con.createStatement();<br />

ResultSet rs = stmt.executeQuery<br />

("SELECT LastName, Salary, Age, Sex FROM Employees");<br />

System.out.println("List of all employees:");<br />

while (rs.next()) {<br />

System.out.print(" name=" + rs.getString(1) );<br />

System.out.print(" salary=" + rs.getDouble(2) );<br />

System.out.print(" age=" + rs.getInt(3) );<br />

if ( rs.getBoolean(4) ) System.out.print(" sex=M");<br />

else<br />

System.out.print(" sex=F");<br />

System.out.println();<br />

}<br />

stmt.close();<br />

con.close();<br />

} catch ...<br />

Beispielskizze fur einzelne Updates der Datenbank (insert, update, delete)<br />

import java.sql.*;<br />

...<br />

try {<br />

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");<br />

String username="admin";<br />

String password="";<br />

Connection con = DriverManager.getConnection<br />

("jdbc:odbc://hostname/databasename", username, password);<br />

Statement stmt = con.createStatement();<br />

int rowCount = stmt.executeUpdate<br />

("UPDATE Employees " +<br />

"SET Salary = 50000.0 WHERE LastName = 'Partl' ");<br />

System.out.println(<br />

rowCount + "Gehaltserhoehungen durchgefuehrt.");<br />

stmt.close();<br />

con.close();<br />

} catch ...<br />

oder bei mehreren Anderungen analog mit:<br />

int rowCount = 0;<br />

for (int i=0; i


owCount = rowCount + stmt.executeUpdate<br />

("UPDATE Employees SET Salary = " + newSalary[i] +<br />

" WHERE LastName = '" + goodPerson[i] + "' ");<br />

}<br />

System.out.println(<br />

rowCount + "Gehaltserhoehungen durchgefuehrt.");<br />

Beispielskizze fur umfangreiche Updates der Datenbank (PreparedStatement)<br />

import java.sql.*;<br />

...<br />

try {<br />

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");<br />

String username="admin";<br />

String password="";<br />

Connection con = DriverManager.getConnection<br />

("jdbc:odbc://hostname/databasename", username, password);<br />

con.setAutoCommit(false);<br />

PreparedStatement ps = con.prepareStatement<br />

("UPDATE Employees SET Salary = ? WHERE LastName = ? ");<br />

for (int i=0; i


12.5 Connection<br />

Die Klasse Connection dient zur Verbindung mit einer Datenbank. Erzeugt wird<br />

diese Verbindung vom JDBC DriverManager in der Form<br />

Connection con =<br />

DriverManager.getConnection (URL, username, password);<br />

Der URL hat eine der folgenden Formen:<br />

jdbc:protocol:databasename<br />

fur eine lokale Datenbank mit JDBC-Driver<br />

jdbc:protocol://hostname:port/databasename<br />

fur eine Datenbank auf einem anderen Rechner, mit JDBC-Driver<br />

jdbc:odbc:datasourcename<br />

fur eine lokale ODBC-Datenbank, mit JDBC-ODBC-Driver<br />

jdbc:odbc://hostname/datasourcename<br />

fur eine ODBC-Datenbank auf einem anderen Rechner, mit JDBC-ODBC-<br />

Driver<br />

Der Username und das Pawort sind als String-Parameter anzugeben. Aus Sicherheitsgrunden<br />

empehlt es sich, das Pawort nicht x im Programm anzugeben sondern<br />

vom Benutzer zur Laufzeit eingeben zu lassen, am besten in einem TextField<br />

mit setEchoCharacter('*') oder in Swing mit einem JPasswordField.<br />

Die wichtigsten Methoden der Klasse Connection sind:<br />

createStatement();<br />

erzeugt ein Statement fur die Ausfuhrung von SQL-Befehlen.<br />

prepareStatement (String sql);<br />

erzeugt ein Prepared Statement fur die optimierte Ausfuhrung von SQL-<br />

Befehlen.<br />

getMetaData();<br />

liefert die DatabaseMetaData (DDL-Informationen) der Datenbank.<br />

setReadOnly(true);<br />

es werden nur Datenbank-Abfragen durchgefuhrt, der Datenbank-Inhalt wird<br />

nicht verandert, es sind daher keine Transaktionen notwendig und der Zugri<br />

kann optimiert werden.<br />

setReadOnly(false);<br />

alle SQL-Statements sind moglich, also sowohl Abfragen als auch Updates<br />

(Default).<br />

setAutoCommit(true);<br />

jedes SQL-Statement wird als eine eigene Transaktion ausgefuhrt, commit()<br />

und rollback() sind nicht notwendig (Default).<br />

setAutoCommit(false);<br />

mehrere SQL-Statements mussen mit commit() und rollback() zu Transaktionen<br />

zusammengefat werden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 166


12.6 Statement<br />

commit();<br />

beendet eine Transaktion erfolgreich (alle Statements wurden ausgefuhrt).<br />

rollback();<br />

beendet eine Transaktion im Fehlerfall (alle Anderungen seit Beginn der Transaktion<br />

werden ruckgangig gemacht).<br />

close();<br />

beendet die Verbindung mit der Datenbank.<br />

Beispielskizze:<br />

String username="admin";<br />

String password="";<br />

Connection con = DriverManager.getConnection<br />

("jdbc:odbc://hostname/databasename", username, password);<br />

Statement stmt = con.createStatement();<br />

con.setReadOnly(true);<br />

...<br />

stmt.close();<br />

con.close();<br />

Innerhalb einer Connection konnen mehrere Statements geonet werden, eventuell<br />

auch mehrere gleichzeitig.<br />

Die Klasse Statement dient zur Ausfuhrung eines SQL-Statements oder von mehreren<br />

SQL-Statements nacheinander. Erzeugt wird dieses Statement von der Connection<br />

in der Form<br />

Statement stmt = con.createStatement();<br />

Die wichtigsten Methoden der Klasse Statement sind:<br />

ResultSet res = executeQuery( String sql )<br />

fuhrt ein SQL-Statement aus, das ein ResultSet als Ergebnis liefert, also z.B.<br />

ein SELECT-Statement.<br />

int rowCount = executeUpdate( String sql )<br />

fuhrt ein SQL-Statement aus, das kein ResultSet liefert, also z.B. ein INS-<br />

ERT, UPDATE oder DELETE-Statement. Der Ruckgabewert ist die Anahl<br />

der Records, fur die der Befehl durchgefuhrt wurde, oder 0.<br />

boolean anyResults = execute( String sql )<br />

fuhrt ein SQL-Statement aus, das mehrere Ergebnisse (ResultSets oder UpdateCounts)<br />

liefern kann, die man dann mit den Methoden getResultSet, get-<br />

UpdateCount und getMoreResults abarbeiten mu. Dies trit nur in seltenen<br />

Spezialfallen zu.<br />

setQueryTimeout ( int seconds )<br />

setzt ein Zeitlimit fur die Durchfuhrung von Datenbankabfragen (in Sekunden).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 167


12.7 ResultSet<br />

close()<br />

beendet das Statement.<br />

Beispielskizze fur eine Abfrage:<br />

Statement stmt = con.createStatement();<br />

ResultSet rs = stmt.executeQuery<br />

("SELECT LastName, Salary, Age, Sex FROM Employees");<br />

...<br />

stmt.close();<br />

Beispielskizze fur ein Update:<br />

Statement stmt = con.createStatement();<br />

int rowCount = stmt.executeUpdate<br />

("UPDATE Employees" +<br />

"SET Salary = 50000.0 WHERE LastName = 'Partl' ");<br />

...<br />

stmt.close();<br />

Innerhalb eines Statements darf zu jedem Zeitpunkt immer nur hochstens 1 Result-<br />

Set oen sein.<br />

Ein ResultSet ist das Ergebnis einer SQL-Abfrage, im allgemeinen das Ergebnis eines<br />

SELECT-Statements. Es enthalt einen oder mehrere Records von Datenfeldern und<br />

bietet Methoden, um diese Datenfelder ins <strong>Java</strong>-Programm hereinzuholen.<br />

Die wichtigsten Methoden der Klasse ResultSet sind:<br />

boolean next()<br />

setzt den "Cursor" auf den ersten bzw. nachsten Record innerhalb des Result-<br />

Set. Dessen Datenfelder konnen dann mit den getXXX-Methoden angesprochen<br />

werden.<br />

boolean getBoolean( String name )<br />

int getInt ( String name )<br />

float getFloat ( String name )<br />

double getDouble ( String name )<br />

String getString ( String name )<br />

usw. liefert den Wert des Datenfeldes mit dem angegebenen Namen (caseinsensitive),<br />

wenn der Name in der Datenbank eindeutig ist.<br />

boolean getBoolean( int n )<br />

int getInt ( int n )<br />

float getFloat ( int n )<br />

double getDouble ( int n )<br />

String getString ( int n )<br />

usw. liefert den Wert des n-ten Datenfeldes im Ergebnis (von 1, nicht von 0<br />

an gezahlt); wenn man im SELECT-Befehl Feldnamen angegeben hat, dann<br />

in der angegebenen Reihenfolge; wenn man im SELECT-Befehl * angegeben<br />

hat, dann in der in der Datenbank denierten Reihenfolge.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 168


java.sql.Date getDate ( String name )<br />

Time getTime ( String name )<br />

Timestamp getTimestamp ( String name )<br />

java.sql.Date getDate ( int n )<br />

usw. liefert analog ein Datums- bzw. Zeit-Objekt. Dabei ist zu beachten, da<br />

die Klasse java.sql.Date verschieden von java.util.Date ist, es gibt in diesen<br />

Klassen aber Methoden, um das eine Datum in das andere umzuwandeln (am<br />

einfachsten mit getDate und setDate).<br />

boolean wasNull()<br />

gibt an, ob das zuletzt gelesene Datenfeld leer war (d.h. den SQL-Nullwert<br />

enthielt).<br />

close()<br />

beendet die Abfrage vorzeitig.<br />

getMetaData();<br />

liefert die ResultSetMetaData (DDL-Informationen) zu diesem ResultSet.<br />

Beispielskizze:<br />

ResultSet rs = stmt.executeQuery<br />

("SELECT LastName, Salary, Age, Sex FROM Employees");<br />

System.out.println("List of all employees:");<br />

while (rs.next()) {<br />

System.out.print(" name=" + rs.getString(1) );<br />

System.out.print(" salary=" + rs.getDouble(2) );<br />

System.out.print(" age=" + rs.getInt(3) );<br />

if ( rs.getBoolean(4) ) System.out.print(" sex=M");<br />

else<br />

System.out.print(" sex=F");<br />

System.out.println();<br />

}<br />

Anmerkungen:<br />

Innerhalb eines Statements darf zu jedem Zeitpunkt immer nur hochstens 1 Result-<br />

Set oen sein. Wenn man mehrere ResultSets gleichzeitig braucht, mu man dafur<br />

mehrere Statements innerhalb der Connection onen (soferne das Datenbanksystem<br />

das erlaubt).<br />

Die Zugrie auf die Felder sollen in der Reihenfolge erfolgen, wie sie von der Datenbank<br />

geliefert werden, also in der Reihenfolge, in der sie im SELECT-Befehl bzw. bei<br />

* im Record stehen. Bei JDBC 1.x konnen die Records auch nur in der Reihenfolge,<br />

in der sie von der Datenbank geliefert werden, verarbeitet werden (mit next).<br />

Ab JDBC 2.0 enthalt die Klasse ResultSet zahlreiche weitere Methoden, die auch<br />

ein mehrmaliges Lesen der Records (z.B. mit previous) und auch Datenanderungen<br />

in einzelnen Records (z.B. mit updateString, updateInt) erlauben.<br />

Ansonsten kann man ein mehrmaliges Abarbeiten der Resultate erreichen, indem<br />

man sie in einem Vector zwischenspeichert. Beispielskizze:<br />

ResultSet rs = stmt.getResultSet();<br />

ResultSetMetaData md = rs.getMetaData();<br />

int numberOfColumns = md.getColumnCount();<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 169


int numberOfRows = 0;<br />

Vector rows = new Vector();<br />

while (rs.next()) {<br />

numberOfRows++;<br />

Vector newRow = new Vector();<br />

for (int i=1; i


12.9 DatabaseMetaData und ResultSetMetaData<br />

Mit den Klassen DatabaseMetaData und ResultSetMetaData kann man Informationen<br />

uber die Datenbank bzw. das ResultSet erhalten, also z.B. welche Tabellen<br />

(Relationen) deniert sind, wie die Datenfelder heien und welchen Typ sie haben,<br />

und dergleichen.<br />

Den Zugri auf die DatabaseMetaData erhalt man mit der Methode getMetaData<br />

in der Connection. Damit kann man dann alle moglichen Eigenschaften des Datenbanksystems,<br />

des JDBC-Drivers, der Datenbank und der Connection abfragen (siehe<br />

die Online-Dokumentation).<br />

Den Zugri auf die ResultSetMetaData erhalt man mit der Methode getMetaData<br />

im ResultSet. Ein paar typische Methoden der Klasse ResultSetMetaData sind:<br />

int getColumnCount()<br />

Anzahl der Datenfelder<br />

String getColumnName ( int n )<br />

welchen Namen das n-te Datenfeld hat<br />

int getColumnType ( int n )<br />

welchen der SQL-Datentypen das n-te Datenfeld hat (siehe die statischen Konstanten<br />

in der Klasse Types)<br />

boolean isSearchable ( int n )<br />

ob das n-te Datenfeld ein Suchfeld ist, das in der WHERE-Klausel angegeben<br />

werden darf<br />

int getColumnDisplaySize ( int n )<br />

wieviele Zeichen man maximal fur die Anzeige des n-ten Datenfeldes braucht<br />

String getColumnLabel ( int n )<br />

welche Bezeichnung man fur das n-te Datenfeld angeben soll (eventuell<br />

verstandlicher als der Datenfeldname)<br />

String getSchemaName ( int n )<br />

in welchem Datebank-Schema (DDL) das n-te Datenfeld deniert ist<br />

String getTableName ( int n )<br />

zu welcher Tabelle (Relation) das n-te Datenfeld gehort<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 171


12.10 Datenbank-Anwendungen uber das Internet<br />

Wie kann das Konzept bzw. die "Architektur" einer <strong>Java</strong>-Datenbank-Anwendung<br />

aussehen, wenn die Benutzer uber das Internet oder ein Intranet von ihren Client-<br />

Rechnern aus auf die Datenbank zugreifen sollen?<br />

Ein solches Client-Server-System kann z.B. aus folgenden Komponenten zusammengesetzt<br />

werden:<br />

einer <strong>Java</strong>-Applikation (oder Servlet) auf dem Server, die auf die Datenbank<br />

zugreift, und<br />

einem HTML-Formular oder einem <strong>Java</strong>-Applet, das innerhalb einer Web-Page<br />

auf den Clients lauft und das User-Interface realisiert.<br />

Die Applikation auf dem Server (bzw. das Servlet) greift auf das Datenbanksystem<br />

und damit auf die Daten zu. Es erhalt vom Client Abfragen oder Daten, fuhrt<br />

die entsprechenden Datenbank-Abfragen oder Daten-Eingaben durch und liefert die<br />

Ergebnisse an den Client.<br />

Das Applet stellt das User-Interface dar. Es sendet die Abfragen oder Dateneingaben<br />

des Benutzers an den Server und gibt die von dort erhaltenen Daten oder Meldungen<br />

an den Benutzer aus.<br />

Das Applet kann von den Benutzern als Teil einer Web-Page mit dem Web-Browser<br />

uber das Internet geladen werden. Der Benutzer braucht fur den Datenbankzugri<br />

also keine andere Software als nur seinen <strong>Java</strong>-fahigen Web-Browser.<br />

Die Kommunikation zwischen Applet und Server kann je nach der verfugbaren Software<br />

auf verschiedene Arten erfolgen:<br />

Am Server arbeitet ein Servlet innerhalb des Web-Servers, die Kommunikation<br />

mit dem Applet erfolgt uber HTTP.<br />

Am Server arbeitet eine <strong>Java</strong>-Applikation als CGI-Programm innerhalb des<br />

Web-Servers, die Kommunikation mit dem Applet erfolgt uber HTTP.<br />

Am Server arbeitet eine selbstandige <strong>Java</strong>-Applikation, die Kommunikation<br />

mit dem Applet erfolgt uber Sockets.<br />

Die Kommunikation zwischen Server-Applikation (bzw. Servlet) und Datenbank<br />

kann<br />

uber JDBC<br />

oder uber das JNI (native Interface) mit Hilfe von Unterprogrammen in C<br />

oder einer anderen Programmiersprache<br />

erfolgen. Dabei konnen das Server-Programm und das Datenbanksystem<br />

am selben Rechner laufen (Datenbank-Server mit Web-Interface)<br />

oder auf zwei verschiedenen Rechnern laufen, die uber das Internet oder Intranet<br />

verbunden sind (Applikations-Server und Datenbank-Server).<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 172


Eine weitere Moglichkeit ware es, da das Applet selbst mit JDBC uber das Internet<br />

direkt auf die Datenbank zugreift, mit einem geeigneten JDBC-Driver, der in diesem<br />

Fall allerdings auf jedem Client installiert sein oder mit dem Applet mitgeladen<br />

werden mu.<br />

Auerdem ware es auch moglich, statt eines Applet eine <strong>Java</strong>-Applikation am Client<br />

zu installieren, die dann wiederum entweder mit Umweg uber ein Server-Programm<br />

oder direkt mit einem JDBC-Driver auf die Datenbank zugreift.<br />

Fortgeschrittene <strong>Java</strong>-Programmierer konnen auch RMI (Remote Method Invocation)<br />

oder EJB (Enterprise <strong>Java</strong> Beans) oder CORBA (Common Object Request<br />

Broker Architecture) verwenden.<br />

Bei wichtigen oder sensiblen Daten mu jeweils auf die Datensicherheit und auf den<br />

Datenschutz geachtet werden (Pawort-Schutz, Verschlusselung der Daten bei der<br />

Ubertragung).<br />

12.11 Ubung: eine kleine Datenbank<br />

Vorbereitung<br />

Diese Ubung besteht aus mehreren Schritten und kann nur dann ausgefuhrt werden,<br />

wenn Sie ein Datenbanksystem und den zugehorigen JDBC-Driver auf Ihrem<br />

Rechner installiert haben und wenn Sie wissen, wie man mit diesem Datenbanksystem<br />

Datenbanken deniert und verwendet. Wenn dies nicht der Fall ist, konnen<br />

Sie "nur" das Konzept dieser Ubungsbeispiele uberlegen und die <strong>Java</strong>-Programme<br />

nur schreiben und compilieren, aber nicht ausfuhren.<br />

Fur diese Ubung werden die Datenbank und die <strong>Java</strong>-Applikationen am selben Rechner<br />

angelegt und ausgefuhrt, also ohne Internet-Verbindung.<br />

Legen Sie - zum Beispiel mit MS-Access - eine Datenbank an, die eine Tabelle<br />

"Mitarbeiter" mit den folgenden Datenfeldern enthalt: Abteilung (Text, String),<br />

Vorname (Text, String), Zuname (Text, String), Geburtsjahr (Zahl, int), Gehalt<br />

(Zahl, double).<br />

Fullen Sie diese Tabelle mit ein paar Datenrecords, etwa wie im Beispiel im Kapitel<br />

uber relationale Datenbanksysteme.<br />

Registrieren Sie diese Datenbank auf Ihrem Rechner, zum Beispiel mit dem ODBC-<br />

Manager der MS-Windows Systemsteuerung als DSN (Datenquellenname). Dann<br />

konnen Sie den einfachen JDBC-ODBC-Driver verwenden, der im JDK enthalten<br />

ist (aber manchmal unerklarliche Fehler liefert).<br />

Bei der Verwendung von anderen Datenbanksystemen mussen Sie sicherstellen, da<br />

ein entsprechender JDBC-Driver verfugbar ist, und die Datenbank dementsprechend<br />

anlegen und registieren.<br />

Einfache Ubrungsbeispiele<br />

1. Liste der Geburtsjahre<br />

Schreiben Sie eine einfache <strong>Java</strong>-Applikation, die eine Liste aller Mitarbeiter mit<br />

Vorname und Geburtsjahr auf den Bildschirm ausgibt.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 173


2. Berechnung des Durchschnittsgehalts<br />

Schreiben Sie eine einfache <strong>Java</strong>-Applikation, die das Durchschnittsgehalt der Mitarbeiter<br />

berechnet und auf den Bildschirm ausgibt. Zu diesem Zweck fragen Sie<br />

das Gehalt von allen Mitarbeitern ab, bilden die Summe, zahlen die Anzahl und<br />

dividieren schlieich die Summe durch die Anzahl.<br />

Komplizierte Ubrungsbeispiele<br />

3. Speichern<br />

4. Liste (Abfrage)<br />

Wenn Sie wollen, konnen Sie das einfache Beispiel auch durch die folgenderen, etwas<br />

aufwendigeren Aufgaben erganzen.<br />

Schreiben Sie eine einfache <strong>Java</strong>-Applikation, die ein paar (mindestens 3, hochstens<br />

10) Mitarbeiter-Records in dieser Datenbank speichert.<br />

Schreiben Sie eine einfache <strong>Java</strong>-Applikation, die eine Liste aller Mitarbeiter mit<br />

Vorname, Zuname und Alter (in Jahren) ausgibt.<br />

5. Berechnungen (Abfrage)<br />

Schreiben Sie eine einfache <strong>Java</strong>-Applikation, die die Anzahl der Mitarbeiter, das<br />

Durchschnittsalter und die Gehaltssumme (Summe der Monatsgehalter) ausgibt.<br />

6. Einfache GUI-Applikation (Abfrage)<br />

Schreiben Sie eine <strong>Java</strong>-GUI-Applikation, bei der der Benutzer in einem TextField<br />

einen Zunamen eingeben kann und dann entweder alle Daten uber diesen Mitarbeiter<br />

am Bildschirm aufgelistet erhalt oder eine Fehlermeldung, da es keinen Mitarbeiter<br />

mit diesem Namen gibt. Das GUI soll auch einen Exit-Button haben, mit dem man<br />

die Applikation beenden kann.<br />

Username und Pawort geben Sie der Einfachheit halber direkt im Programm an,<br />

auch wenn man das bei echten Datenbanken aus Sicherheitsgrunden nicht tun sollte.<br />

7. Aufwendigere GUI-Applikation (Updates)<br />

Schreiben Sie eine <strong>Java</strong>-GUI-Applikation, bei der der Benutzer zunachst mit 2 Textfeldern<br />

seinen Username und sein Pawort eingibt, um mit der Datenbank verbunden<br />

zu werden, und dann in einem neuen Fenster mit 4 Textfeldern alle Daten fur einen<br />

zusatzlichen Mitarbeiter eingeben und mit einem Store-Button in der Datenbank<br />

speichern kann. Jedes dieser Fenster soll auch einen Exit-Button haben, mit dem<br />

man die Applikation beenden kann.<br />

Fugen Sie mit dieser Applikation ein paar (mindestens 2, hochstens 5) weitere Mitarbeiter<br />

in die Datenbank ein und fuhren Sie dann die Ubungsprogramme 4, 5 und<br />

6 neuerlich aus, um zu testen, ob alle Mitarbeiter richtig gespeichert wurden.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 174


Wenn Sie sehr viel mehr Zeit investieren wollen, konnen Sie auch uberlegen, wie<br />

ein graphisches User-Interface aufgebaut sein mute, um damit nicht nur die Speicherung<br />

von neuen Records sondern auch Abfragen von gespeicherten Records,<br />

Datenanderungen an einzelnen Records und Loschungen von einzelnen Records<br />

durchfuhren zu konnen.<br />

8. Loschen<br />

Schreiben Sie eine einfache <strong>Java</strong>-Applikation, die alle Mitarbeiter-Records aus der<br />

Datenbank loscht.<br />

Fuhren Sie dieses Programm aus und testen Sie dann mit Programm 1 oder 4, ob<br />

tatsachlich keine Mitarbeiter mehr gespeichert sind.<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 175


13. Referenzen<br />

Online-Informationen uber <strong>Java</strong>:<br />

{ Online-Dokumentation (API) des JDK - auch on-line auf<br />

http://java.sun.com/docs/<br />

{ http://java.sun.com/ - auch unter http://www.javasoft.com/<br />

{ http://www.gamelan.com/<br />

{ http://www.sourceforge.net/<br />

{ http://codeguru.developer.com/java/<br />

{ <strong>Java</strong> Tutorial auf http://java.sun.com/docs/books/tutorial/index.html<br />

{ <strong>Java</strong> FAQ auf http://sunsite.unc.edu/javafaq/javafaq.html<br />

{ <strong>Java</strong> Programmers FAQ auf http://www.afu.com/javafaq.html<br />

{ <strong>Java</strong> Glossary in http://mindprod.com/gloss.html<br />

{ deutsche <strong>Java</strong>-FAQ auf http://www.os-visions.de/texte/java/faq/<br />

{ Bucher:<br />

3 <strong>Java</strong>-Einfuhrung von Hubert Partl auf<br />

http://www.boku.ac.at/javaeinf/<br />

3 Go to <strong>Java</strong> 2 von Guido Kruger auf http://www.gkrueger.com/<br />

3 <strong>Java</strong> ist auch eine Insel von Christian Ullenboom auf<br />

http://java-tutor.com/<br />

3 <strong>Java</strong> Dokumentation von Brit Schroter und Johann Plank auf<br />

http://www.selfjava.de/<br />

3 Thinking in <strong>Java</strong> von Bruce Eckel auf<br />

http://www.BruceEckel.com/javabook.html<br />

{ siehe auch http://www.yahoo.com/ (Suche)<br />

Online-Informationen uber Internet, WWW und HTML:<br />

{ Internet-Handbuch von H.Partl - auch online auf<br />

http://www.boku.ac.at/zid/hand/#internet<br />

{ HTML-Einfuhrung von H.Partl - auch online auf<br />

http://www.boku.ac.at/htmleinf/<br />

{ W3-Consortium - auf http://www.w3.org/<br />

{ siehe auch http://www.yahoo.com/ (Suche)<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 176


Newsgruppen uber <strong>Java</strong> und Web-Pages:<br />

{ comp.lang.java.help<br />

{ comp.lang.java.programmer<br />

{ comp.lang.java.gui<br />

{ und andere Spezialgruppen in der Hierarchie comp.lang.java.*<br />

{ comp.infosystems.www.authoring.html<br />

{ comp.infosystems.www.authoring.site-design<br />

{ und andere Gruppen in der Hierarchie comp.infosystems.*<br />

{ de.comp.lang.java<br />

{ de.comm.infosystems.www.authoring<br />

{ und andere Gruppen in den Hierarchien de.comm.* und de.comp.*<br />

{ siehe auch http://www.deja.com/ (Suche)<br />

Beilage:<br />

Musterlosungen der Ubungsaufgaben<br />

<strong>Java</strong>-Einfuhrung von H. Partl { Kursunterlage 177

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!