Java-Einführung
Java-Einführung
Java-Einführung
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ü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ä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