Java 2 Kompendium
Ralph Steyer
Java 2
Professionelle Programmierung mit J2SE Version 1.3
Markt+Tec Technik Verlag
Die Deutsche Bibliothek – CIP-Einheitsaufnahme Ein Titeldatensatz für diese Publikation ist bei Der Deutschen Bibliothek erhältlich. Die Informationen in diesem Buch werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie – zum Schutz vor Verschmutzung – ist aus umweltverträglichem und recyclingfähigem PE-Material.
10 9 8 7 6 5 4 3 2 1 05 04 03 02 01
ISBN 3-8272-6039-6 © 2001 by Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Einbandgestaltung: Grafikdesign Heinz H. Rauner, Gmund Lektorat: Jürgen Bergmoser,
[email protected] Herstellung: Elisabeth Egger,
[email protected] Satz: reemers publishing services gmbh, Krefeld (www.reemers.de) Druck und Verarbeitung: Bercker, Kevelaer Printed in Germany
Java 2 Kompendium 5 Inhaltsübersicht Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Hinweise zum Buch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Kapitel 1 What's new? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Kapitel 2 Schnuppertour Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Kapitel 3 Das JDK. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Kapitel 4 Unterschiede zwischen Java-Applikakkationen und -Applets . . . . . . . . . . 137 Kapitel 5 Java-Hintergründe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Kapitel 6 Java – die Hauptbestandteile der Sprache. . . . . . . . . . . . . . . . . . . . . . . . . 183 Kapitel 7 Grundlagen der Applet-Erstellllung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 Kapitel 8 Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Kapitel 9 Grafik und Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417 Kapitel 10 Das AWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517 Kapitel 11 Swing & Co . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .623 Kapitel 12 Debugging und Ausnahmebehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . 667 Kapitel 13 Ein- und Ausgabe in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .697 Kapitel 14 Java-Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755 Kapitel 15 Andere Sprachen in Verbindung mit Java. . . . . . . . . . . . . . . . . . . . . . . . . 777 Kapitel 16 Weiterführende Themen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 829 Anhang A. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Anhang B. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 955 Anhang C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1075 Anhang D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1101 Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1105 Java 2 Kompendium
5
Inhaltsverzeichnis
V o r w or t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
Hinweise zum Buch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
Kapitel 1
W h at ' s n ew ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
1.1
Java 1.2, Java 2.0, JDK 1.2 und JDK 1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
1.2
JavaSoft und Sun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
1.3
Die Java-Neuerungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kompatibilität und das Java-Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interoperabilität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anpassung einer Applikation an verschiedene Länderstandards . . . . . . . . . . . . . . . . . . . . Erweiterung der Sicherheitsschnittstelle von Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verschlüsselung in Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Abstract Window Toolkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java-Archive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbankunterstützung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verteilte Programmierung und Object Serialization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java IDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inner Classes und Anonymous Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Native Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reference Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multimedia-Unterstützung in Java 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Java-2D-API-Referenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Swing JDK 1.2/1.3 und die Java Accessibility API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Drag&Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Java-Standardklassen und die Datei classes.zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . Veränderungen bei den Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Neues Lizenzierungsmodell für Java 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34 34 39 40 40 41 42 43 44 44 45 45 46 46 47 47 47 48 49 50 51 51 53
1.4
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
Java 2 Kompendium
7
Inhaltsverzeichnis Kapitel 2
Schnup nuppertour Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
2.1
Was ist Java? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Internet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein kurzer Abriss der Internet-Geschichte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Organisation des Internets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Adressierung im Internet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die IP-Nummern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das DNS-Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Uniform Resource Locator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56 56 58 62 64 65 66 68 71
2.2
Die Geschichte von Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Erstes Java-Auftreten, HotJava und das JDK 1.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was macht Java so einzigartig? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Herkunft von Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73 75 77 79
2.3
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
86
Kapitel 3
D as J D K . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
3.1
Bezug des JDK. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
3.2
Installation des JDK. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . classes.zip, src.zip, src.jar, rt.jar & Co. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verzeichnisstruktur innerhalb des JDK-Verzeichnisses . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Java-Laufzeitumgebung jre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Java-Plug-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91 93 94 96 96
3.3
Die JDK-Dokumentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
3.4
Fehlervorbeugung und Fehlerbehebung beim JDK . . . . . . . . . . . . . . . . . . . . . . . . . . . Pfad-Angaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CLASSPATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verwendung von mehreren JDK-Versionen unter Windows . . . . . . . . . . . . . . . . . . . . . . . . »Class not found« und andere Fehlermeldungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Java-Umgebungsvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unbekannte Fehler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
103 103 105 109 112 116 116
3.5
Die wichtigsten JDK-Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein paar allgemeine Hinweise zu den JDK-Programmen . . . . . . . . . . . . . . . . . . . . . . . . . . Der Appletviewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Java-Compiler Javac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Java-Interpreter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
117 117 121 125 130
3.6
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
8
Java 2 Kompendium
Inhaltsverzeichnis Kapitel 4
Unterschiede zwischen Java-Applikat kationen un und -Applets . . . . . . . . . . . . . . . . . . . . . 137
4.1
Die technischen Unterschiede . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
4.2
Eine erste Beispielanwendung und ein erstes Applet. . . . . . . . . . . . . . . . . . . . . . . . . 141 Eine erste Applikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Übergabe von Aufrufargumenten an ein Java-Programm . . . . . . . . . . . . . . . . . . . . . . . . . 144 Ein erstes Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
4.3
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Kapitel 5
Java-Hintergründe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
5.1
Was ist OOP?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
5.2
Die Definition von Objektorientierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Objektmethoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Who's calling?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
5.3
Klassen und Instanzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Superklasse und Subklasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Metaklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Abstrakte Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
5.4
Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Mehrfachvererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
5.5
Überschreiben. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
5.6
Polymorphismus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
5.7
Binden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Frühes Binden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Spätes Binden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
5.8
Die Grundprinzipien der objektorientierten Programmierung . . . . . . . . . . . . . . . . . . . 166
5.9
Objektorientierte Analyse und objektorientiertes Design . . . . . . . . . . . . . . . . . . . . . . 167 Die objektorientierte Analyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Das objektorientierte Design. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
5.10
Die Objektorientierung von Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Java-Klassen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Polymorphismus und Binden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Schnittstellen und Pakete statt Mehrfachvererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Überladen, Überschreiben und Überschatten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 Globale Vereinbarungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Java 2 Kompendium
9
Inhaltsverzeichnis 5.11
Plattformunabhängigkeit von Java und die JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Die binäre Plattformunabhängigkeit von Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Die JVM-Architektur. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Die Datentypen der JVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Die Java-Plattformunabhängigkeit auf Quellebene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
5.12
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Kapitel 6
Java – die Haupt uptbestandt ndteile der Sprache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
6.1
Token. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Der Unicode-Zeichensatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Die UTF-8-Codierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Kleiner Vorgriff auf die Datentypen von Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Die Java-Token-Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Literale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Operatoren-Priorität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Kommentare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
6.2
Typen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Operationen mit den Datentypen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
6.3
Datenfelder (Arrays) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 Deklarieren von Datenfeldern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Erstellen von Datenfeldobjekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Dynamische Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Speichern und Zugreifen auf Datenfeldelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
6.4
Ausdrücke, Operatoren und Casting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Ausdrücke. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Typkonvertierungen und der Casting-Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Der Instanceof-Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
6.5
Anweisungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Blöcke und Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Leere Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Bezeichnete Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Deklarationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 Ausdrucksanweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
10
Java 2 Kompendium
Inhaltsverzeichnis Auswahlanweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 Iterationsanweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Java-Sprunganweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 Schutzanweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Unerreichbare Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 6.6
Klassen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Allgemeines zu Klassen in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Allgemeine Klassendeklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Klassen-Modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Der Klassenname . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Superklassen und das Schlüsselwort extends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Designregeln für Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Innere und anonyme Klassen bzw. Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 Adapterklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 Konstruktoren und der new-Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 Das Speichermanagement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Das Schlüsselwort this. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
6.7
Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Deklaration einer Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Die Zugriffsspezifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Die Methodenmodifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Die Rückgabewerte von Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Der Methodenname. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Die Parameterliste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 Der Methodenkörper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 Methoden überladen und überschreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
6.8
Schnittstellen und das Schlüsselwort implements . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Erstellung einer Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Namensregeln für Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Die Erweiterung anderer Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Der Körper einer Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Überschreiben und Verwenden von Schnittstellenmethoden . . . . . . . . . . . . . . . . . . . . . . . 322 Verwenden von Feldern einer Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 Beispiele mit Schnittstellen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Java 2 Kompendium
11
Inhaltsverzeichnis 6.9
Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Instanzvariablen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 Klassenvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 Klassenvariablen versus Instanzvariablen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Lokale Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Die Java-Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
6.10
Der Zugriff auf Java-Elemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
6.11
Pakete und die import-Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Die Verwendung von Paketen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Erstellung eines Paketes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 Das anonyme Default-Paket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 Zugriffslevel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
6.12
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
Kapitel 7
Grundlagen de der Applet-Erstellun llung ung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
7.1
Die Vorbereitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
7.2
Grundlagen der Einbindung von Java-Applets in HTML-Seiten. . . . . . . . . . . . . . . . . . 343 HTML-Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
7.3
Konkrete Referenzierung eines Java-Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Die <APPLET>-Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Die Parameter des <APPLET>-Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 Die <EMBED>-Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 Die -Syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Welches Tag ist sinnvoll? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Die ursprüngliche HotJava-Syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
7.4
Die interne Arbeitsweise eines Applets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Erstellung und Grundmethoden eines Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 Ein Musterapplet als Schablone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
7.5
Die Applet-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 Ausgabe in einem Applet mit der paint()-Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 Übergabewerte für ein Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 Bilder importieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 Importieren und Abspielen von Sound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Die Interaktion des Applets mit der Umgebung und den Lebenszyklus eines Applets verwalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Methoden zur Ereignisbehandlung in Applets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
12
Java 2 Kompendium
Inhaltsverzeichnis 7.6
Multithreading bei Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
7.7
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Kapitel 8
Multithread eading. ng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
8.1
Klassen Thread-fähig machen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Die Erweiterung der Klasse Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Implementation von Runnable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
8.2
Thread-Gruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 Eine Thread-Gruppe erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 Hinzufügen eines Threads zu einer Thread-Gruppe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
8.3
Dämonen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
8.4
Schutzmaßnahmen bei Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Methoden synchronisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 Vorsicht, Deadlock! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 Synchronisierte Blöcke. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414 Thread-sicherer Zugriff auf Datenstrukturen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . . 415
8.5
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
Kapitel 9
Grafik und und Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
9.1
Zeichnen, Update und neu zeichnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
9.2
Punkte, Linien, Kreise und Bögen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Das Koordinatensystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Eine Linie zeichnen – die drawLine()-Methode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 Ein Rechteck zeichnen – die drawRect()-Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 Ein gefülltes Rechteck zeichnen – fillRect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Löschen eines Bereichs – clearRect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Kopieren eines Bereichs – copyArea(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 Ein 3D-Rechteck zeichnen – die draw3dRect()-Methode . . . . . . . . . . . . . . . . . . . . . . . . . 425 Ein gefülltes 3D-Rechteck zeichnen – fill3dRect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425 Abgerundete Rechtecke – drawRoundRect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426 Abgerundete gefüllte Rechtecke – fillRoundRect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426 Zeichnen von Polygonen – drawPolygon() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 Zeichnen von gefüllten Polygonen – fillPolygon() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430 Zeichnen von Kreisen und Ellipsen – drawOval() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431 Zeichnen von gefüllten Kreisen und Ellipsen – fillOval() . . . . . . . . . . . . . . . . . . . . . . . . . . 432 Zeichnen von Bögen – drawArc() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433 Zeichnen von gefüllten Bögen – fillArc() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
Java 2 Kompendium
13
Inhaltsverzeichnis 9.3
Farbangaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 Die Color-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Farben setzen – setColor() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 Hintergrundfarben und Vordergrundfarben pauschal setzen – setBackground() und setForeground(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438 Ein Apfelmännchen als Java-Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 Abrufen von Farbinformationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 Textausgabe über den Zeichnen-Modus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 Erstellen von Fontobjekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 Abfragen der zur Verfügung stehenden Fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448 Informationen über einen speziellen Font abfragen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
9.4
Die Java-Zeichenmodi. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 Der Paint-Modus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 Der XOR-Zeichenmodus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
9.5
Zeichnen von Bildern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 Laden von Bildern – getImage() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 Anzeigen von Bildern – drawImage() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452 Der Imageobserver und der MediaTacker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
9.6
Animationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457 Aufbau eines Animationsrahmens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 Abspielen einer Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 Flimmereffekte in Animationen reduzieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468 Clipping. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474 Double-Buffering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
9.7
Das 2D-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 Java-2D-Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479 Zeichnen unter dem Java-2D-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 Komplexere Zeichnenoperationen im 2D-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 Text unter Java 2D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
9.8
Bilder unter Java 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 Anzeige von Bildern unter Java 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 Transparenz und Bilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 Rendering als Bestandteil von Java 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499 Kontrolle der Ausgabequalität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 Transformation von 2D-Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 Neue Formen kreieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
14
Java 2 Kompendium
Inhaltsverzeichnis Stroking Paths. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 Füllen von Formen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 Komposition von Bildern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 Transparenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 Text und Fonts unter Java 2D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 Farbmanagement unter Java 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 2D-Bildbearbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 Offscreen-Puffer unter Java 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 2D-Graphics Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 9.9
Die Java-2D-API-Referenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
9.10
Sound und Töne in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510 Das Abspielen und Stoppen eines Audio-Clips – play() . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 Die Sound-Möglichkeiten der JDK-Demos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 Das Java Media Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
9.11
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
Kapitel 10
Das AWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
10.1
Was ist das Abstract Window Toolkit? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
10.2
Woraus besteht das AWT? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 Was sind AWT-Komponenten? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522 Was versteht man unter AWT-Container? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 Container und Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 Der Aufbau der AWT-Klassenhierarchie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 Was ist ein AWT-Layoutmanager? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
10.3
Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525 Panels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526 Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527 Dialoge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
10.4
Schaltflächen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
10.5
Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
10.6
Kontrollkästchen und Optionsfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545 Kontrollkästchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 Optionsfelder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548 Reaktionen auf Kontrollfelder und Radiobuttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
Java 2 Kompendium
15
Inhaltsverzeichnis 10.7
Auswahlmenüs und Listenfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554 Einzeilige Listenfelder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555 Mehrzeilige Listenfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
10.8
Textbereiche und Textfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 Textbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 Textfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567 Gemeinsame Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569 Spezielle TextField-Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570 Spezielle TextArea-Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
10.9
Schieber und Bildlaufleisten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
10.10
Zeichenbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578
10.11
Menüs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
10.12
Eine Schablone für alle Fälle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
10.13
Layoutmanager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 Layout-Regeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592 Die Layoutmanager im Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593
10.14
Die Eventmodelle 1.0 und 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605 Der AWT-Event-Handler 1.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606 Tastaturereignisse des AWT-Event-Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607 Mausereignisse des AWT-Event-Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 Zentrale Aspekte des 1.0-Eventhandlings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 Das Eventhandling 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611 Der Umstieg vom 1.0-Eventmodell auf das 1.1-Modell. . . . . . . . . . . . . . . . . . . . . . . . . . . 618
10.15
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621
Kapitel 11
Swing & Co . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
11.1
Das Swing-API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
11.2
Swing und AWT im Vergleich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624 Einige Swing-Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626
11.3
Swing in der Praxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 Umschalten von Look and Feel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 Swing und Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
11.4
Eigenständige Applikationen und Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638 Eine Swing-Applikations-Schablone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
16
Java 2 Kompendium
Inhaltsverzeichnis 11.5
Swing-Komponenten im Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
11.6
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666
Kapitel 12
Debug bugging und und Ausnahmebehandlung ung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
12.1
Debugging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668 Fehler im Vorfeld abfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668 Vernünftige Sicherungsmaßnahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669 Fehler finden und beseitigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669 Fehlerlokalisierung ohne Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670 Fehlerlokalisierung mit Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
12.2
Ausnahmebehandlung und andere Fehlerbehandlungen . . . . . . . . . . . . . . . . . . . . . . 675 Die individuell programmierte Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676 Die Ausnahmebehandlung von Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677 Benutzerdefinierte Exceptions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687 Die RuntimeException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693
12.3
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 694
Kapitel 13
Ein- und und Ausgabe in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697
13.1
Allgemeines zur Ein- und Ausgabe unter Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697
13.2
Die Klasse InputStream. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701 Methoden zum Einlesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701 Blockaden vorher abfragen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 702 Überspringen von Daten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703 Positionen beim Lesen markieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703 Ressourcen freigeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
13.3
Die Klasse OutputStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704 Methoden zum Schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705 Den gepufferten Cache ausgeben. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706 Ressourcen freigeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707
13.4
Byte-Datenfeldströme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707
13.5
Der StringBufferInputStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708
13.6
Gefilterte Ströme. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708
13.7
Gepufferte Ströme. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709
13.8
Datenströme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 710 Die DataInput-Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 710
Java 2 Kompendium
17
Inhaltsverzeichnis Die DataOutput-Schnittstelle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 Die DataInputStream- und DataOutputStream-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 13.9
Die PrintStream-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713
13.10
Pipe-Ströme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
13.11
Objektströme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715
13.12
Einige spezielle Utility-Ströme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716 Die LineNumberInputStream-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716 Die SequenceInputStream-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716 Die PushbackInputStream-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717 Die StreamTokenizer-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717
13.13
Die File-Klasse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718 Überprüfung, ob Datei oder Verzeichnis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718 Lese- und Schreiberlaubnis überprüfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719 Die letzte Änderung überprüfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719 Die Existenz eines Objekts überprüfen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719 Pfadkontrolle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719 Namen und Pfad einer Datei oder eines Verzeichnisses ermitteln . . . . . . . . . . . . . . . . . . . 719 Eine Datei oder ein Verzeichnis umbenennen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720 Dateien löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720 Verzeichnisse erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720 Den Inhalt eines Verzeichnisses angeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720
13.14
Dateiströme – FileInputStream und FileOutputStream . . . . . . . . . . . . . . . . . . . . . . . . 721 Die RandomAccessFile-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 722
13.15
Praktische Java-Beispiele mit Datenströmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 723
13.16
Drucken unter Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744 Drucken unter dem JDK 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744 Drucken unter dem SDK 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 748
13.17
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 751
Kapitel 14
Java-Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755
14.1
Das Java-Sicherheitskonzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755 Die Missbrauchsfähigkeiten einer Sprache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 756 Viren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760 Unkontrollierte Systemzugriffe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760 Verifizierung des Bytecodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761 Der Verifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761
18
Java 2 Kompendium
Inhaltsverzeichnis Der Classloader. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762 Der Sicherheitsmanager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 763 Digitale Unterschriften eines Applets und Verschlüsselung in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765 Native Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765 Weitere unerwünschte Aktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 14.2
ActiveX-Sicherheitskonzept im Vergleich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 Was sind ActiveX-Controls? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 Sicherheitskonzept von ActiveX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769
14.3
Bekannte Sicherheitslücken der Java-Vergangenheit . . . . . . . . . . . . . . . . . . . . . . . . 771 Der Bytecode-Bug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 772 Schwarze Witwen und der DNS-Bug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 773 Der CLASSPATH-Bug. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 773 Weitere Bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 774 Informationen zur Sicherheit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775
14.4
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775
Kapitel 15
Andere Sprachen in Ve Verbindu ndung mit Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777
15.1
C/C++ – Unterschiede und Gemeinsamkeiten sowie die Einbindung . . . . . . . . . . . . 777 Unterschiede und Gemeinsamkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777
15.2
Die Verbindung von Java und nativem Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784 Konventioneller Einbau von C-Code in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 785 Das Java Native Interface (JNI) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 790 JNI-Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 791 Datenaustausch zwischen Java und C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 793 Java-C++-Verbindung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 794 Alternativen zum direkten Einbinden von nativen Methoden . . . . . . . . . . . . . . . . . . . . . . . 795
15.3
Verbindung von Java zu JavaScript und anderen Scriptsprachen . . . . . . . . . . . . . . . 795 Kleiner Exkurs zu JavaScript-Interna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797 Das Objektmodell von JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807 Verbindung von Java und JavaScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 811 Applets dynamisch schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 823 Verbindung mit weiteren Techniken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 826
15.4
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 827
Java 2 Kompendium
19
Inhaltsverzeichnis Kapitel 16
Weiterführ ührende nde Th Themen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 829
16.1
Reflection und Serialization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 829 Reflection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 830 Serialization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 831
16.2
JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 832 Wie passen JavaBeans in Java? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 833 Beans erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 838 Spezielle Anwendungen von JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 841 Beans einer IDE bereitstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 842
16.3
Verteilte Systeme – RMI, IDL und CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 842 Java IDL oder wie ist RMI in Bezug auf CORBA zu sehen? . . . . . . . . . . . . . . . . . . . . . . . . 844 Entwicklung einer CORBA-Anwendung in Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 846
16.4
Netzwerkzugriffe, Sockets und Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 853 Java-Servlets, JSP und SSI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 853 Allgemeine Netzwerkzugriffe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 870 Sockets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 874
16.5
Datenbanken und JDBC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 880 Was sind relationale Datenbanken?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 881 Was ist SQL?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 883 JDBC versus ODBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 883 Grundaufbau von JDBC und des JDBC-Managers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 884 Woraus besteht das JDBC-API? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 885 Die JDBC-Treiber. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 888 Schematischer Aufbau einer Datenbank-Applikation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 889 Praktischer Einsatz von JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 891
16.6
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 904 Anhang A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905
A.1
Ergänzungen zu den JDK-Tools. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Erweiterte Basisprogramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Internationalization Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 927 Security Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 928 Java IDL- und RMI-Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 936
20
Java 2 Kompendium
Inhaltsverzeichnis A.2
IDEs für Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 938 JCreator für Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 938 Forte 2.0 for Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 941 JBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948 Kawa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 951 Anhang B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 955
B.1 B.2
Das Java-1.3-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 956 Beschreibung der Pakete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959 java.applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 960 java.awt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 960 java.awt.color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 966 java.awt.datatransfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967 java.awt.dnd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967 java.awt.event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 968 java.awt.font . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 970 java.awt.geom. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 971 java.awt.im . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 972 java.awt.im.spi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 973 java.awt.image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 973 java.awt.image.renderable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976 java.awt.print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976 java.beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 977 java.bean.beancontext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978 java.io. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 979 java.lang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983 java.lang.ref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 988 java.lang.reflect. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 988 java.math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 989 java.net. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 989 java.rmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 991 java.rmi.activation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992 java.rmi.dgc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992 java.rmi.registry. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993 java.rmi.server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993 java.security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 995 java.security.acl. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997
Java 2 Kompendium
21
Inhaltsverzeichnis java.security.cert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997 java.security.interfaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 998 java.security.spec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 998 java.sql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 999 java.text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1000 java.util . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1002 java.util.jar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1004 java.util.zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1004 javax.accessibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1005 javax.naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1006 javax.naming.directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1007 javax.naming.event, javax.naming.ldap und javax.naming.spi . . . . . . . . . . . . . . . . . . . . . . 1007 javax.rmi und javax.rmi.CORBA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1008 javax.sound.midi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1008 javax.sound.midi.spi, javax.sound.sampled und javax.sound.sampled.spi . . . . . . . . . . . . . 1009 javax.swing & Co . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1009 javax.swing.event. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1014 javax.swing.undo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1016 Die CORBA-Pakete. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1016 Nicht enthalten – das Servlets-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1017 B.3
Die veralteten Elemente des Java-API 1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1017 Klassen (deprecated) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1018 Interfaces (deprecated). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1018 Exceptions (deprecated) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1018 Felder (deprecated) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1018 Methoden (deprecated) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1019 Constructors (deprecated) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1025
B.4
HTML-Elemente und -Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1025 HTML-Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1025 Die HTML 4.0-Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1030
B.5
JavaScript- Token . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1070 Anhang C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1075
C.1
JAR-Archive oder wie arbeiten Komprimierungstechnologien? . . . . . . . . . . . . . . . . . 1075 Komprimierungsverfahren und Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1075 Der Huffman-Algorithmus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1078
22
Java 2 Kompendium
Inhaltsverzeichnis Selbstextrahierende Programme. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1082 Wie groß ist die Reduzierung der Datenmenge?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083 C.2
Wie funktionieren Verschlüsselungsverfahren? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083 Verschlüsselungs- bzw. Kryptographieprogramme. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1084 Einige Verschlüsselungsverfahren. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1086 PGP oder wie Java verschlüsselt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1089 Die heutigen Standard-Algorithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1089 Eine kleine Abschlussbemerkung zum Thema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1090
C.3
Von der Dezimalrechnung abweichende Rechenarten . . . . . . . . . . . . . . . . . . . . . . . . 1091 Binärrechnung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1091 Oktalrechnung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1092 Hexadezimalrechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1093
C.4
Die Theorie des Zweierkomplements bei ganzen Zahlen . . . . . . . . . . . . . . . . . . . . . . 1095
C.5
Farbangaben in Java und JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097 Die direkte Angabe eines Farbnamens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097 Die Farbangabe mittels RGB-Werten in Hexadezimalform. . . . . . . . . . . . . . . . . . . . . . . . . 1097
C.6
Erläuterung der Kurzschreibweisen von Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . 1098
C.7
Java-Quellen im Internet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1099 Anhang D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1101
D.1
Neuerungen der Java-2-Plattform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1101 Stichwortverzeichni hnis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1105
Java 2 Kompendium
23
Vorwort
Wíllkommen zu Java! Vielleicht stellen Sie sich gerade die Frage: »Was kann ich mit Java machen?« Eine einfache Antwort: Fast alles! Zumindest, wenn Sie an Programmierung denken. Grafische Animationen, Chats im Rahmen von Webseiten, Spiele, Verschlüsselungsprogramme, interaktive Webseiten, Musik, Textverarbeitungen, kleine und große Internet-Applets, riesige Programmpakete, Programme zur Bildverarbeitung, neuartige Benutzeroberflächen, Übersetzungsprogramme, Bestellsysteme, Lernanwendungen, Uhren, Office-Programme und noch viel mehr. Mit anderen Worten: Mit der Programmiersprache Java kann man jedes denkbare Programm schreiben. Zuerst profitieren natürlich das Internet und das WWW davon – auf allen möglichen WWW-Seiten werden Java-Applets eingesetzt. Aber auch jenseits des Internets gibt es einen unerschöpflichen Fundus an potenziellen Anwendungen. Sie finden mittlerweile zahlreiche in Java erstellte Applikationen auf den verschiedensten Computersystemen. Das Einsatzgebiet von Java ist jedoch nicht nur auf reine Computersysteme beschränkt, sondern erstreckt sich insbesondere auch auf die Programmierung von einer Vielzahl verwandter Geräte, die einen Prozessor beinhalten. Das sind einmal naheliegende Beispiele wie Mobiltelefone, insbesondere solche, die den neuen UMTS-Standard – Universal Mobile Telecommunication System (universelles mobiles Telekommunikationssystem) – unterstützen sollen und Videorecorder, aber auch viele andere Geräte des täglichen Gebrauchs, von denen einige auch erst in der Zukunft eine Zielplattform für eine umfangreiche Programmierung bieten. Sei es der voll programmierbare Kühlschrank, der mit einem Warenmanagementsystem selbst seinen Inhalt verwaltet und bei Bedarf selbstständig eine Bestellung per Internet aufgibt oder die Mikrowelle, die aus dem Auto heraus via Handy und Internet angeschaltet werden kann. Diese und viele andere Geräte sind keine Fiktion, sondern bereits Realität, und es ist nur noch eine Frage der Zeit, wann sie zu selbstverständlichen Gebrauchsgegenständen werden. Und mit Java steht die Technik bereit, den damit verbundenen Anforderungen der Programmierung zu begegnen.
erstellt von ciando
Auf jeden Fall ist Java »hipp«, ist heiß. Fast alle wichtigen Firmen der Computerbranche setzen seit längerer Zeit verstärkt auf Java. Zwar hatte sich die anfängliche Euphorie um Java zwischenzeitlich etwas gelegt, aber mittlerweile ist die Bedeutung von Java wieder erheblich gestiegen (nicht zuletzt Java 2 Kompendium
25
Vorwort durch die Möglichkeiten bei der Programmierung von intelligenten Geräten des täglichen Gebrauchs). Java hat sich als eine feste Größe in der EDV etabliert und wenn die Visionäre Recht behalten, wird Java bereits in naher Zukunft in fast allen datenbasierenden Geräten zu finden sein. Die immer stärker werdende Nachfrage nach Java-Programmierern zeigt zudem, wie viel Potenzial die Wirtschaft in Java sieht. Seit der Version 1.0 wurden Java und das zugehörige Entwicklungspaket JDK (Java Development Kit) immer weiter verbessert. Vor allem kann man seit dem JDK 1.2 davon ausgehen, dass Kinderkrankheiten der ersten beiden Versionen 1.0/1.1 (vor allem der Version 1.0) der Vergangenheit angehören. Das JDK 1.3 als aktuelle Basis der Java-2-Plattform hat sich insbesondere noch einmal der Performance von Java-Programmen angenommen und Java ist damit zu einer der leistungsfähigsten Entwicklerplattformen überhaupt geworden. Vor allem ist Java aber spannend und eine der innovativsten Entwicklungen der EDV-Welt seit vielen Jahren. Viel Spaß beim Erforschen, Erlernen und Programmieren wünscht Ihnen Ralph Steyer HTTP://WWW.RJS.DE
26
Java 2 Kompendium
Hinweise zum Buch
Um sich die Arbeit mit dem Buch und den Beispielen zu erleichtern, sollten Sie folgende Hinweise beachten: Beachten Sie die Tipps, Warnungen und Hinweise außerhalb des Fließtextes, ebenso besonders hervorgehobene Textpassagen. Sie finden die Beispiele und die dort verwendeten Dateien (Bilder, Datenbanken usw.) allesamt auf der Buch-CD. Aus didaktischen Gründen ist jedoch ein explizites Abtippen der Quelltexte immer sinnvoller. Aus satztechnischen Gründen ist es in einigen Listings notwendig, Strings (in Hochkommata eingeschlossene Texte) auf mehrere Zeilen aufzuteilen. Das darf im Editor bei der Eingabe des Quelltextes aber nicht gemacht werden. Mit anderen Worten – Strings müssen unbedingt in eine Zeile geschrieben werden. Zwischen den Versionen von Java bestehen erhebliche Differenzen und teilweise Inkompatibilitäten. Darauf wird an diversen Stellen im Buch hingewiesen. Die Entwicklungen rund um Java sind permanent im Fluss. Deshalb sollten Sie immer aktuelle Entwicklungen im Internet verfolgen und neueste Programme und Dokumentationen aus dem Internet bei Bedarf parat haben.
Java 2 Kompendium
27
1
What's new?
Lassen Sie uns gleich damit beginnen, uns an die faszinierende Welt von Java heranzutasten. Bevor wir jedoch zur eigentlichen Java-Schnuppertour kommen, sollen für die Leser, die Java bereits kennen, kompakt die Neuerungen von Java 2.0 und dem JDK 1.2/1.3 aufgeführt werden. In diesem Abschnitt wird eine gewisse Vertrautheit mit den wichtigsten Begriffen von Java und seinem Umfeld vorausgesetzt. Wer sich mit Java noch nicht auskennt, kann gerne später auf diesen Abschnitt zurückkommen.
1.1
Java 1.2, Java 2.0, JDK 1.2 und JDK 1.3
Java 2.0! Erheblich verspätet, aber dafür mit umso lauterem Getöse ging Java nach dem fulminanten 1.0-Einstieg und den Zwischenversionen 1.1 und 1.2 (Beta) Anfang 1999 in die zweite Runde. Im Dezember 1998 hatte Sun Microsystem (der »Eigentümer« von Java) endlich die bereits Anfang 1998 angekündigte und mehrfach verschobene Finalversion des JDK 1.2 (Java Development Kit) – der Java-Entwicklungsumgebung – freigegeben. Kurz danach gab Sun auf der Java Business Expo bekannt, dass es nicht nur ein neues JDK, sondern ein vollständiges Plattform-Update unter dem Namen Java 2.0 gibt. Diese Namenspolitik überraschte zum damaligen Zeitpunkt doch ziemlich, denn es schien bis dahin klar, dass das vollständige Update der bis dahin vertriebenen JDK-Finalversion 1.1 und seiner ergänzenden Tools als Version 1.2 in Umlauf kommt. So ganz überzeugt von seiner Namenspolitik scheint auch Sun nicht gewesen zu sein, denn das erste JDK von Java 2 – Kern der Java-2.0-Plattform – wurde innerhalb der Java-2.0-Plattform als JDK 1.2 eingeführt und auch das neue JDK von Java 2 läuft als Version 1.3. Sogar Publikationen zur Gesamtplattform wurden von Sun Microsystems noch Anfang 1999 unter dem Titel »Java 1.2« veröffentlicht. Aber um es gleich vorab festzuhalten – die Veränderungen des Java-APIs (API ist die Abkürzung für Application Programming Interface -Programmier- und Anwendungsschnittstelle), die sich noch zwischen den Betaversionen des JDK 1.2 und der als Final freigegebenen Version ergeben haben, erzwangen eine solche Namenspolitik fast unweigerlich. Es war leider so, dass beiJava 2 Kompendium
29
Kapitel 1
What's new? spielsweise das API der dritten Betaversion 1.2 und das 1.2/2.0-Final-API extrem viele Unterschiede aufwiesen. Der Oberbegriff »Java 2« macht den Break zu den Vorgängerversionen (insbesondere den inkompatiblen Betaversionen) deutlich. Mit der Einführung des JDK 1.2 und der Java-2-Plattform hatte Sun endlich einen Stand geschaffen, von dem aus es weitgehend um die Verbesserung der Stabilität (ein rigoroses Qualitätssicherungsprogramm) und Performance (Vervollkommnung der virtuellen Maschine) ging. Davor lag der Hauptfokus auf dem Ausbau und der Entwicklung von neuen Features und der Beseitigung von Schwachstellen. Zwischen dem JDK 1.2 und dem Mitte 2000 eingeführten JDK 1.3 (Codename Kestrel) hingegen sind die Unterschiede nicht mehr so gravierend, weshalb Java 2 ohne gravierende Probleme als Obermenge für beide JDK-Welten fungieren kann. Vor allem sind die Veränderungen von dem JDK 1.3 fast nur als echte Erweiterungen und Verbesserungen zu sehen, die keine gravierenden Inkompatibilitäten zum JDK 1.2 nach sich ziehen. Dementsprechend werden das JDK 1.3 wie auch das JDK 1.2 und die dazwischen liegenden Versionen JDK 1.2.1 und 1.2.2 zur Java-2-Plattform gezählt. Die vielleicht bedeutendste Erweiterung des JDK 1.3 ist die Einführung der HotSpotTechnologie. Diese beinhaltet im Wesentlichen eine so genannte adaptive Compilertechnologie, bei der interpretierte Programmteile bei Bedarf zur Ausführungszeit des Programms in Maschinencode übersetzt werden kann. Dazu zählt ebenso eine geschwindigkeitsoptimierte virtuelle Maschine für den Client und die zugehörigen, mit dem JDK 1.3 neu eingeführten neuen Optionen bei einigen Programmen des JDK. Der Mischmasch der Versionen führt bei vielen Betrachtern zu Verwirrung. Deshalb zur Klärung – wir werden uns in dem Buch mit Java 2.0 und vor allem dem dazu gehörenden JDK 1.3 beschäftigen, aber die Aussagen gelten auch meist für das JDK 1.2. Allgemein wird das gesamte Konzept zur Entwicklung von Applikationen für Java 2 mit dem JDK 1.3 unter »Java 2 SDK« zusammengefasst (SDK steht für Software Development Kit). Wesentlicher Unterschied zwischen der vollständigen Java-Plattform und dem JDK ist, dass die Plattform weitere APIs, Programme, Tools und Konzepte enthält. Hierzu zählen das JSDK (Java Servlet Development Kit), das bis zur Beta 4-Version des JDK 1.2 noch zu diesem gezählt hatte, oder auch andere Tool-Pakete, die die Funktionalität des JDK erweitern. Die aktuelle Java-2-Plattform und das Java 2 SDK (Java 2 Software Development Kit) beinhalten unter anderem folgende Basiselemente: Sichere und signierte (d.h. eindeutig identifizierbare) Applets Ein Collections Framework, d.h. eine einheitliche Architektur für die Darstellung und Manipulation von Collections, unabhängig von den Details ihrer Repräsentation
30
Java 2 Kompendium
Java 1.2, Java 2.0, JDK 1.2 und JDK 1.3
Kapitel 1
JavaBeans, d.h. Komponenten, die in Java erstellt sind und innerhalb von Java-Entwicklungsumgebungen verwendet werden können Die Unterstützung von Ein- und Ausgabe Verfahren zur Internationalisierung Umfangreiche Mechanismen zur Arbeit im Rahmen von Netzwerken Reflection, ein Verfahren, um in Java-Code Informationen über Felder, Methoden und Konstruktoren von geladenen Klassen verfügbar zu machen Sound- und Multimedia-Unterstützung Referenz-Objekte für den limitierten Zugriff auf die Garbage Collection (das Speichermanagement von Java) Object Serialization, um Objekte speichern und anschließend wieder seriell auslesen zu können Zugriff auf JAR-Files (Java-Archive) – ein besonderes Komprimierungsformat für Java Das Java Native Interface (JNI) für die Verbindung zu C/C++-Sourcen Sprach- und Utility-Packages Remote Method Invocation (RMI) für die Arbeit mit verteilten Anwendungen und CORBA (Common Object Request Broker Architecture), den Standard, der die Kommunikation zwischen Objekten und Programmen regelt Unterstützung von mathematischen Vorgängen mit großen Zahlen und hoher Genauigkeit Identifikation von Package-Versionen Plattformneutraler Zugriff auf Systemressourcen Der Extension Mechanism, um einfachen Zugriff auf Pakete zu gewährleisten, die nicht zu den Java-Standard-Packages gehören Die Version 1.3 des Java-2-SDK und der Java-2-Laufzeitumgebung beinhaltet diverse Verbesserungen zur Beschleunigung der Performance Das Konzept der zur Java-2-Plattform gehörenden Java Foundation Classes (JFC) beinhaltet folgende Details: Das Abstract Window Toolkit (AWT) zur Erstellung von einfachen grafischen Benutzeroberflächen Swing-Komponenten zur Erweiterung des AWTs Unterstützung von 2D-Graphics und -Imaging
Java 2 Kompendium
31
Kapitel 1
What's new? Das Input Method Framework für die Zusammenarbeit zwischen texteditierenden Komponenten und Eingabemethoden in den unterschiedlichsten Sprachen und verschiedensten Eingabemedien (Tastatur, Sprache oder auch handschriftlich per Schrift und sensitivem Display) Das Java-Accessibility-API, womit Java-Applikationen mit unterstützenden Technologien wie Spracherkennungssystemen oder Eingabebildschirmen interagieren können Drag&Drop-Datentransfer zum Datenaustausch zwischen Java- und nativen Applikationen, zwischen verschiedenen Java-Applikationen oder auch nur innerhalb einer einzelnen Java-Applikation Zu den erweiterten Features des Java-2-SDKs zählen die folgenden Konzepte: Als Erweiterung des Remote Method Invocation (RMI) die RMI-IIOPTechnik und Interface Definition Language (IDL) für die Erstellung von CORBA-kompatiblen Schnittstellen. RMI-IIOP ist eine neu eingeführte Technologie, die Java RMI und Java IDL verbindet und CORBA-kompatible Schnittstellen direkt in Java erstellen lässt. In dem neuen SDK verwendet Java IDL eine neue Version des Java-to-IDLCompilers. Dieser Compiler unterstützt einen neuen CORBA-Standard. Java Database Connectivity (JDBC) für den leichten und plattformneutralen Zugriff auf Datenbanken unter Java Das Java Naming and Directory Interface (JNDI) für die Angabe von Ressourcen (Verzeichnisse, Drucker usw.) über einen plattformunabhängigen Namen aus einer Java-Applikation heraus. Die JNDI-Architektur basiert auf einem eigenen API und einem SPI (Service Provider Interface). Neu in der aktuellen Java-2-Plattform ist, dass das vorher nur als Standarderweiterung vorhandene Interface nun voll integriert ist. JNDI beinhaltet u.a. Support für LDAP-v3-Erweiterungen sowie das Lightweight Directory Access Protocol (LDAP), den CORBA Object Services Naming Service (COS) und das Java Remote Method Invocation Registry (RMI). Das Java-2-SDK beinhaltet zudem einen Tool Support, der folgende Konzepte enthält: Die Java Platform Debugger Architecture (JPDA) zur Bereitstellung von drei Schnittstellen, die von Debuggern in Entwicklungsumgebungen verwendet werden können. Das Java Virtual Machine Debugger Interface definiert die Dinge, die eine JVM (Java Virtual Machine) zur Unterstützung bereitstellen muss. Das Java Debug Wire Protocol definiert die geforderten Formate und das Java Debug Interface die Informationen und Anworten auf User-Ebene.
32
Java 2 Kompendium
JavaSoft und Sun
Kapitel 1
Das Java Virtual Machine Profiler Interface (JVMPI) als eine experimentelle, nicht standardisierte Schnittstelle zum Profiling (Anpassen von Programmen an unterschiedliche Bedürfnisse) Die wesentlichen Neuerungen der Java-2-Plattform gegenüber den Vorgängerversionen konzentrieren sich auf die Bereiche Sicherheit, Interoperabilität mit anderen Systemen, Plattformneutralität, Geschwindigkeitssteigerung, Internationalisierung und Vereinfachung der Entwicklungstätigkeit. Prinzipiell sollte man dabei festhalten, dass schon im Schritt von 1.0.x auf die Final 1.1.x-Versionen erhebliche Veränderungen stattfanden. Leider gab es aber auch viele Veränderungen im Laufe der vier Betaversionen des JDK 1.2, weshalb diese Betaversionen in vielen Bereichen nicht mehr mit dem Finalrelease 1.2 (und natürlich erst recht nicht dem JDK 1.3) übereinstimmen. Gerade der Wechsel von der Beta-3-Version auf die wenig beachtete Beta-4-Version des JDK 1.2 beinhaltete zahlreiche und sehr massive Modifikationen, insbesondere auf Ebene des API, aber auch bei Tools. Viele Umsteiger von einem JDK 1.1.x oder einer der drei ersten Betaversionen 1.2 hatten deshalb ziemliche Umstellungsprobleme. Die wichtigsten dieser Reformen und Erweiterungen von Java und des JDK bis zu der aktuellen Version sollen im Rahmens dieses Buchs näher erläutert werden. Dabei sind die Änderungen im Detail natürlich so umfangreich, dass wir sie hier nicht allesamt ansprechen können. Glücklicherweise sind eine Menge von Veränderungen auch so speziell, dass »normale« Programmierer davon kaum berührt werden.
1.2
JavaSoft und Sun
»Verantwortlich« für Java ist Sun Microsystems (http://java.sun.com) bzw. JavaSoft – eine Tochterfirma der Firma Sun Microsystems. Wir werden im Folgenden nicht so genau zwischen Sun und JavaSoft trennen, da diese organisatorischen Strukturen für Sie nur am Rande interessant sein dürften. Wie dem auch sei – Sun und JavaSoft halten im Internet permanent die aktuellsten Informationen um Java bereit. Die wichtigsten Informationen kann man in folgende Bereiche klassifizieren: Neues und Aktuelles zu Java, Veränderungen u.ä. (http://java.sun.com/ products/jdk/1.3/relnotes.html bzw. http://java.sun.com/products/ jdk/1.3/docchanges.html) Bugs (http://java.sun.com/products/jdk/1.3/bugs.html) Tipps für Entwickler und FAQs (häufig gestellte Fragen) (http:// java.sun.com/products/jdk/faq.html) Kompatibilitätsfragen (http://java.sun.com/products/jdk/1.3/compatibility.html)
Java 2 Kompendium
33
Kapitel 1
What's new? Downloadmöglichkeiten für diverse Produkte (http://java.sun.com/ products/jdk/1.3/index.html bzw. http://java.sun.com/products/) Die
offizielle
Java-Sprachspezifikation
(http://java.sun.com/docs/
books/jls/html/index.html)
Die Spezifikation der virtuellen Maschine (http://java.sun.com/docs/ books/vmspec/2nd-edition/html/VMSpecTOC.doc.html) Informationen zur Java-Laufzeitumgebung und dem Java-Plug-In (http://java.sun.com/products/jdk/1.3/jre/)
1.3
Die Java-Neuerungen
Behandeln wir zuerst die Neuerungen, die Java im weiteren Sinn betreffen.
1.3.1
Kompatibilität und das Java-Plug-In
Im Allgemeinen gilt, dass Entwicklungen, die mit einer älteren Version von Java erstellt wurden, ebenso in der virtuellen Maschine der Folgeversionen ohne Probleme laufen sollten. Dies gilt sowohl auf binärer Ebene als auch auf Ebene des Quelltextes (allerdings definitiv ohne Gewährleistung durch Sun). Ausnahmen sind explizit diejenigen Java-Programme, die mit einer der Java-Vorgängerversionen erstellt wurden und die auf Klassen zurückgreifen, in welchen sicherheitsrelevante Löcher festgestellt wurden. Auch einige Java-Programme, die auf Klassen mit Implementations- oder Designbugs zurückgreifen, können unter neuen Versionen unter Umständen nicht mehr laufen. Solche Applikationen müssen bei einer Portierung von älteren auf eine neuere JVM neu kompiliert werden. Bei der Neukompilierung von älterem Java-Quellcode werden dann ziemliche Schwierigkeiten auftreten, wenn dort Java-Pakete importiert werden, die in dem neuen Konzept nicht mehr vorhanden sind (das ist zwar selten, aber möglich) oder verlagert und/oder umbenannt wurden (das ist leider sehr oft der Fall). Beispielsweise sind die Pakete des gesamten Swing-Konzeptes ab dem JDK 1.2 gegenüber der bisherigen Konzeption (Version 1.1 und sogar Beta 1.2) vollständig verlagert und umbenannt worden. In solchen Fällen muss in dem Java-Quelltext die import-Struktur dem neuen API natürlich angepasst werden. Sie finden dazu im Anhang eine Tabelle. Insgesamt gab es in der 1.1.1-Version als erste richtige Finalversion nach dem 1.0.x-Standard eine ganze Menge an neuen Funktionalitäten. Innerhalb der einzelnen Zwischenvarianten der 1.1-Versionen fanden dahingegen keine echten Erweiterungen statt, sondern weitestgehend nur Fehlerbereinigungen und interne Optimierungen.
34
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
Die erste öffentliche JDK-Version 1.2 Beta wurde während des Jahreswechsels 1997/98 vorgestellt und enthielt doch einige Überraschungen. Insbesondere wurden einige 1.1-Entwicklungen bzw. Features der Vorgänger wieder zu den Akten gelegt, weil sie nicht ganz die Erwartungen erfüllt hatten (ein Sicherheitstool und einige Optionen). Dies bedeutet, dass in der Sicherheitsfunktionalität von Java eine gewisse Inkompatibilität zwischen Java 1.1.x und den Folgeversionen besteht. Zwischen der JDK-Version 1.2 und 1.3 wurden dann kaum noch solche Änderungen durchgeführt, die zu echten Inkompatibilitäten führen können. Applets Eine gewisse Schwierigkeit bei Java-Applets ist die Integration von JavaVersionen jenseits von Java 1.0.2 (!) in die gängigen Browser. Applets, die neuere APIs nutzten, setzen einen entsprechend kompatiblen Browser oder Viewer voraus. Dies war (und ist!) ein nicht ganz unbeträchtliches Problem, denn viele der heute noch im Internet verwendeten Browser unterstützen maximal Java 1.0.2, können also mit auf dem 1.1-API (oder Folgeversionen) basierenden Funktionalitäten nichts anfangen. Die meisten Programme, die Java unterstützen, wurden erst Anfang 1998 auf die Unterstützung von Java 1.1.3 upgedatet. So kann der Netscape Communicator in den Versionen 4.03-4.05 nur mit Java-1.1-Funktionalität umgehen, wenn er mit dem JDK-1.1-Patch ausgestattet ist. Ab der Version 4.06 ist JDK-1.1-Unterstützung dann teilweise (!) integriert. Der Microsoft Internet Explorer kann ab der Version 4.01 mit Java-1.1-Funktionalität umgehen (mit den üblichen Einschränkungen durch die Auffassung von Microsoft, was Java genau sein soll). Java 2.0 und das JDK 1.2 bzw. 1.3 mit den zugehörigen Klassen erzeugen nun aber erneut das Problem. Zusammenfassend muss man festhalten: Es gibt eine Vielzahl von Problemen, wenn Sie Applets mit Funktionalitäten erstellen, die über die Version 1.0.2 hinausgehen. Die ganze Problematik bedeutet dennoch nicht unbedingt, dass Sie für die Erstellung von Applets mit einem alten JDK arbeiten müssen. Sofern Applets mit einem beliebigen JDK erstellt und kompiliert wurden und nur auf Java-Standard-1.0.2 basierende Funktionalitäten nutzten, sollten sie auch in nur diesen Standard unterstützenden Browsern/Containern dargestellt werden können. Diese Abwärtskompatibilität wird allerdings von Sun nicht ausdrücklich garantiert. Das Java-Plug-In Die Java-2.0-Plattform beugt – im Gegensatz zu den Vorgängerversionen – Inkompatibilitäten mit Browsern vor und beinhaltet ein Java-Plug-In für Webbrowser (ehemals bekannt als Activator), das automatisch von der Installationsroutine des JDK bzw. der Laufzeitumgebung mit installiert wird. Mittels dieses Tools kann die Java-Laufzeitumgebung eines Browsers durch eine beliebige andere Java-Laufzeitumgebung ersetzt werden. Damit
Java 2 Kompendium
35
Kapitel 1
What's new? ist im Prinzip immer eine vollständig zu einer beliebigen JVM kompatible Laufzeitumgebung für Applets vorhanden. Das Java-Plug-In wurde erstmals mit dem JDK 1.2 bzw. der zugehörigen Laufzeitumgebung JRE 1.2 ausgeliefert und installierte unter Windows in das Startmenü eine Aufrufmöglichkeit.
Abbildung 1.1: Das Java-Plug-In, das mit dem JDK 1.2 ausgeliefert wurde
Im JDK 1.3 hat sich die Situation insoweit verändert, als dass das Java-PlugIn unter Windows nun über die Systemsteuerung zur Verfügung steht. Abbildung 1.2: Das Java-Plug-In des JDK 1.3 lässt sich über die Systemsteuerung starten
Nachdem Sie das Java-Plug-In gestartet haben, können Sie das als Laufzeitmanager konzipierte Tool über verschiedene Registerblätter konfigurieren.
36
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
Am wichtigsten ist wohl, dass man in dem Registerblatt ADVANCED bzw. ERWEITERT verschiedene Java-Laufzeitumgebungen (alle auf Ihren Rechner vorhandenen) einstellen kann, die als Java-Plug-In für Browser fungieren. Es ist also nicht nur möglich, zwischen verschiedenen bei Ihnen aktuell auf dem Rechner installierten Java-Laufzeitumgebungen zu wechseln. Sie können darüber hinaus jederzeit die neueste Java-Laufzeitumgebung auf Ihrem Rechner installieren und diese steht dann theoretisch denjenigen Browsern zur Verfügung, die eine externe Java-Laufzeitumgebung verwenden können. Abbildung 1.3: Einstellen der Laufzeitumgebung
Leider funktioniert das Plug-In nicht bei allen Browsern und sie können sich nicht unbedingt darauf verlassen, dass die Browser mit dem 1.3-API oder sogar schon viel früher eingeführten Techniken wie Java 2D oder Swing tatsächlich zurechtkommen. Insbesondere Sicherheitsrestriktionen der Browser hebeln neuere Techniken immer wieder aus (Firewalls, keine Installationen von Plug-Ins auf Clientrechnern erlaubt, allgemeine Sicherheitsbedenken usw.). Die hauptsächlichen Probleme mit dem Java-Plug-In beruhen aber darauf, dass Sie bei Anwendern nicht voraussetzen können, dass das Plug-In und vor allem eine passende andere Java-Laufzeitumgebung auch wirklich installiert ist1. Ein Problem kann darin bestehen, dass die Verwendung des Java-Plug-Ins die Einbindung von Applets in Webseiten mittels des oder <EMBED>-Tags voraussetzt. Meist wird jedoch das einfachere <APPLET>Tag verwendet, und dann kann das Java-Plug-In nicht genutzt werden. Es gibt zwar von Sun einen vollständig in Java geschriebenen HTML-Konverter (zu laden von der Sun-Plug-In-Homepage http://java.sun.com/products/ 1
Dies betrifft z.B. Anwender mit einem Internet Explorer, die nicht zusätzlich eine JRE von Sun installiert haben (das ist meist der Fall).
Java 2 Kompendium
37
Kapitel 1
What's new? plugin), der aus einer Webseite mit dem <APPLET>-Tag eine solche mit -Tag (für den Internet Explorer) bzw. <EMBED>-Tag (für den Net-
scape Navigator) macht. (Defaulteinstellung ist, dass beide Versionen in die Webseite eingefügt werden). Dies hilft jedoch keinem Anwender unmittelbar, wenn er eine Seite mit einer <APPLET>-Referenz aus dem Netz lädt. Abbildung 1.4: Die Plug-In-Downloadseite von Sun
Auf Seite 35 finden Sie den Einsatz des Java-Plug-Ins konkret besprochen. Zusammenfassend kann man sagen, dass es theoretisch möglich ist, in einem moderneren Browser Applets zu verwenden, die die gleichen APIs nutzen wie eine eigenständige Java-Applikation. Das setzt aber beim Anwender erhebliche Faktoren voraus:
38
1.
Es muss eine passende Java-Laufzeitumgebung vorhanden sein. Die Java-Umgebung, die vom Browser mitgeliefert wird, reicht in der Regel nicht aus. Entweder ist also die Laufzeitumgebung des Betriebssystems ausreichend oder der Anwender muss explizit eine Laufzeitumgebung nachinstalliert haben. Das kann man bei den meisten Anwendern definitiv nicht voraussetzen.
2.
Das Java-Plug-In muss vorhanden sein oder zumindest bei Bedarf nachinstalliert werden können. Letzteres wird in professionell gemanagten Netzwerken mit Firewall und zentraler Verwaltung natürlich verhindert. Aber auch im Bereich der Standalone-Rechner verhindern viele
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
fortgeschrittene Anwender diese Nachinstallation (Sicherheits- und Stabilitätsbedenken, unerwünschter Ressourcenverbrauch auf dem eigenen Rechner, hohe Downloadkosten usw.). 3.
Der Ersteller einer Webseite muss das veraltete und – im Vergleich zum <APPLET>-Tag – recht komplizierte <EMBED>-Tag zum Einbinden von Applets verwenden, wenn er den Navigator unterstützen will. Der Internet Explorer verlangt gar das -Tag, das die meisten Anwender wegen seiner ActiveX-Verbindung generell nicht akzeptieren. Sollen beide Browservarianten unterstützt werden, müssen (wie in unserem Beispiel gezeigt) beide Varianten in einer Webseite notiert und getrennt werden. Und damit hat man ältere Browser und einige Browser von anderen Herstellern explizit ausgeschlossen.
In einem Intranet können die genannten Faktoren leicht vorausgesetzt werden, weshalb dort Java-Applets voll ausgereizt werden können. Im Internet wird es noch einige Zeit dauern, bis die Voraussetzungen akzeptabel sind. Was heißt deprecated? Über die Entwicklung von Java wurden von Sun immer wieder Java-Elemente als »deprecated« bezeichnet, was übersetzt in etwa »missbilligt«, »veraltet« oder »verworfen« bedeutet2. Dies bedeutet aber nicht, dass Sie diese Elemente vergessen können oder nicht mehr verwenden dürfen. Diese Methoden lassen sich durchaus noch anwenden und sogar mit neueren Methoden – mit der nötigen Vorsicht – mischen. Und nicht nur das – es gibt Situationen, in denen zwingend als deprecated gekennzeichnete Techniken verwendet werden müssen! Insbesondere bei der Entwicklung von JavaApplets werden Sie normalerweise gezwungen sein, das als veraltet gekennzeichnete Eventmodell 1.0 zu verwenden. Wir werden im Abschnitt über die Ereignisbehandlung von Java sowie den Applets noch genauer darauf eingehen.
1.3.2
Interoperabilität
Es gibt mittlerweile zahlreiche Java-APIs, nicht nur von Sun, sondern von diversen Herstellern, die sich mit Java beschäftigen. Um das Zusammenspiel zwischen diesen verschiedenen APIs zu gewährleisten (die so genannte Interoperabilität), wurde das Java Collection Framework, eine formalisierte Schnittstelle zum Einbinden von neuen Java-Technologien, definiert. Dieses gehört in der Java-2-Plattform zu den Kerntechnologien.
2
Das gleiche Verfahren findet man auch bei HTML.
Java 2 Kompendium
39
Kapitel 1
What's new?
1.3.3
Anpassung einer Applikation an verschiedene Länderstandards
Eine der wichtigsten Neuerungen im Sprung von den 1.0.x-Versionen aufwärts war die mögliche Anpassung einer Java-Applikation an verschiedene Länderstandards. Eine Applikation kann so beispielsweise landesspezifische Schreibweisen berücksichtigen, wie zum Beispiel die Zeit oder das Datum. Des Weiteren ist es nun erlaubt, Texte in Menüs und Dialogen in verschiedenen Sprachen auszugeben. Der 16 Bit große Unicode kann vollständig angezeigt werden, soweit dieser bisher mit Zeichen gefüllt ist (da ist noch viel Platz). Dieser Vorgang, der von Sun mit Internationalisierung beschrieben wird, betrifft im Wesentlichen das java.text-Package und das java.ioPackage. Das zugehörige, in der Version 1.1 neu hinzugekommene Programm native2ascii konvertiert native-verschlüsselte 8-Bit-Zeichen in Unicode.
1.3.4
Erweiterung der Sicherheitsschnittstelle von Java
Java ist eine der sichersten Programmiersprachen bzw. Plattformen der EDV-Welt. Aber natürlich nicht perfekt. In der Geschichte von Java wurden – wie bei jeder vergleichbaren Umgebung – immer wieder Sicherheitslücken aufgedeckt. Die immer wieder nachgeschobenen kleinen Releasewechsel beseitigten nach und nach bekannt gewordene Sicherheitslücken (so etwa 23 der 24 in der Version 1.1 im Frühsommer 97 durch Forscher der University of Washington im Rahmen des Kimera Project entdeckten Sicherheitsrisiken) und sonstige Bugs. Eine wichtige Erweiterung der ersten Java-Plattform betraf die Sicherheitsschnittstelle von Java. Diese verbindet ab der Version 1.1 so genannte Low-Level- und High-Level-Sicherheitsfunktionalität. So können ab diesem Release Applets und Daten mit einer digitalen Unterschrift versehen werden. Das Konzept wurde im Laufe der Updates noch erweitert um abstrakte Schnittstellen für die Verwaltung von Schlüsseln, das Zertifikats-Management und die Zugriffskontrolle. Spezifische APIs zur Unterstützung von X.509 v3-Zertifikaten und anderer Zertifikatformate sowie eine umfangreiche Funktionalität im Bereich der Zugriffskontrolle sind weitere Sicherheits-Highlights der neuen JDK-Versionen. Seit der JDK 1.1-Version ist im JDK-Paket ein Tool enthalten, mit dem Sie so genannte Java-Archive (Erweiterung .jar) signieren können. JARDateien sind neu in der Version 1.1 eingeführt worden und fassen einzelne Java-Dateien zu einem Paket zusammen – später mehr dazu. Der Appletviewer erlaubt jedem aus dem Netz geladenen Applet in Form einer JARDatei, die als vertrauenswürdig eingestuft und mit diesem Tool entsprechend signiert wurde, mit denselben Rechten auf dem lokalen Rechner zu
40
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
laufen wie eine lokale Applikation. Dies hat extrem weitreichende Konsequenzen, denn ein solches Applet ist nicht mehr Bestandteil des »Laufstalls«, in den das Java-Sicherheitsmodell Applets normalerweise zwingt. Das zugehörige Java-Sicherheitsprogramm der JDK-Version 1.1 heißt javakey. Dieses Tool ist als eine der bedeutendsten Neuerungen in der Version 1.2 durch die Programme keytool und jarsigner ersetzt worden. Im JDK 1.3 wurden die beiden Tools nochmals um eine neue Option erweitert (-provider). Daneben wurden bereits im JDK 1.2 die Sicherheitsprogramm jar und policytool hinzugefügt. Das JDK 1.2 erweiterte den Umfang der Tools, die von dem Sicherheitsmodell von Java betroffen sind, in der Finalversion um ein weiteres Programm (oldjava). Dies ist zwar nur ein Interpreter, aber dessen Hauptfunktion ist es, Applikationen zu unterstützen, die über einen eigenen Security Manager verfügen, der auf dem originalen Sicherheitsmodell von Java 1.0/1.1 basiert. Dieser wird unter der Java-2-Plattform eine Exception auswerfen und nicht starten. Solche Applikationen können mit dem Programm oldjava als Interpreter jedoch weiterverwendet werden.
1.3.5
Verschlüsselung in Java
Die Sicherheitsschnittstelle von Java bietet seit der Version 1.1 eine Unterstützung für die so genannte Public-Key-Verschlüsselung. Bekanntestes Beispiel für eine Public-Key-Verschlüsselung ist wohl PGP (Pretty Good Privacy). Die Public-Key-Verschlüsselung ist eine relativ neue und extrem zuverlässige Verschlüsselungsvariante, die mit zwei Schlüsseln arbeitet: einem privaten Schlüssel, der nur beim Sender verbleibt, und einem öffentlichen Schlüssel, der verschickt wird. Diesen zweiten Schlüssel darf jeder kennen, denn er wird ausschließlich zum Kodieren einer Nachricht benutzt. Zum Dekodieren kann er nicht verwendet werden. Die Folge ist, dass bis jetzt nur der Empfänger des Schlüssels an den Sender des Schlüssels eine kodierte Botschaft senden kann, die ausschließlich dieser dann mit seinem privaten Schlüssel dekodieren kann. Will der potenzielle Sender eine kodierte Nachricht verschicken, muss er also erst von dem potenziellen Empfänger den öffentlichen Schlüssel erhalten. Dieses Verfahren hat den riesigen Vorteil, dass der Dekodierungsschlüssel niemals verteilt werden muss und es äußerst sicher ist. Nachteil ist andererseits unleugbar, dass man einen großen Aufwand mit dem Verschicken und Verwalten der verschieden Kodierungs-Schlüssel betreiben muss. Durch die Kombination der digitalen Unterschrift und der Public-Key-Verschlüsselung können selbst sensible Daten in einer Java-Applikation verarbeitet und im Internet bereitgestellt werden.
Java 2 Kompendium
41
Kapitel 1
What's new? Zu der Funktionsweise von Verschlüsselungsverfahren im Allgemeinen finden Sie im Anhang einen Beitrag, der auf einige Grundlagen eingeht.
1.3.6
Das Abstract Window Toolkit
Als ein großer Nachteil von Java in der Version 1.0 wurde oft angeführt, dass Java durch seine Plattformunabhängigkeit für alle Architekturen und Betriebssysteme Vorsorge treffen muss und deshalb sehr oft nur den kleinsten gemeinsamen Nenner aller Fähigkeiten der einzelnen Plattformen nutzen kann. Java-Applets können immer nur die Möglichkeiten verwenden, die in ihrer internen Laufzeitbibliothek verankert sind (z.B. die Grafik-, Kommunikations-, Multithreading-Klassen bzw. die Klassen für die grafische Benutzeroberfläche). Da die Klassenbibliothek für den Entwurf einer grafischen Benutzeroberfläche – das AWT (Abstract Window Toolkit) – in der Version 1.0 relativ klein und allgemein gehalten wurde, konnten die Applets zu dieser Zeit nur eine Auswahl der unter Windows bekannten Elemente bieten. Hauptargument der Kritiker war, dass auf der WINTEL-Plattform (Windows und INTEL) basierende Computer die verbreitetsten Rechner im Internet sind (über 80 % der angeschlossenen Rechner) und Java für weniger als 20 % der Internetteilnehmer die vollständige Windowsfunktionalität aufgab. Das AWT hat in der Version 1.1 sehr weitreichende Erweiterungen erfahren. Dazu zählen eine einheitliche Druckerschnittstelle, damit Applikationen darüber plattformunabhängig drucken können (selbst dies war in der Version 1.0 noch nicht gegeben), aber auch schnelleres und einfacheres Scrolling, bessere Grafikmöglichkeiten sowie flexiblere Font-Unterstützung. Eine Unterstützung von Pop-up-Menüs und der Zwischenablage waren weitere wichtige Erweiterungen. Das 1.2/1.3-API hat gerade hier noch einmal zugelegt und viele weitere neue Funktionalitäten und Erweiterungen folgen lassen. Das neue Paket beinhaltet die erste vollständige Implementation der Java Foundation Classes (JFC), einem Satz von APIs und vorkompilierten Komponenten. Die JFC schließt nun Java 2D zur Erstellung von 2D-Grafiken, UI Components (Swing Package), Zugriffsmöglichkeiten auf diverse Hilfstechnologien (Accessibility), Drag&Drop und Application Services ein. Insbesondere das Swingkonzept erlaubt statt der davor recht rustikalen Oberfläche von JavaAnwendungen ein mehr dem durch Windows geprägten Massengeschmack angepasstes Aussehen. Das in der Version 1.0 noch sehr starr ausgelegte Eventhandling (also die Reaktion auf Ereignisse) wurde bereits für die Java-Version 1.1 völlig überarbeitet und wurde damit wesentlich flexibler. Das 1.1-Eventmodell arbeitete als Neuerung mit so genannten Delegates, d.h. Objekten, die die »Delegierten« von anderen Objekten sind. Ein Fenster erhält zum Beispiel ein 42
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
Delegate-Objekt, an das dann eine Menge von Methoden geschickt wird, die das Delegate dann abarbeiten kann. Je nach dem Rückgabewert der Methode in dem Delegate wird das Fensterobjekt dann unterschiedlich reagieren. Das Delegate-Konzept an sich ist nicht neu und bereits ziemlich ausgereift, denn es wird schon seit Jahren unter dem Betriebsystem Nextstep, aber auch unter Windows NT und in der Entwicklungsumgebung OpenStep verwendet. Die Win-32-lmplementation des AWT wurde ebenfalls komplett überarbeitet, da die alte Version zu langsam war und viele Inkonsistenzen im Vergleich mit anderen Plattformen hatte. Damit war bereits das AWT 1.1 insgesamt erheblich schneller und stabiler geworden. Zu der Erweiterung des AWTs zählt gleichfalls das so genannte Input Method Framework. Darunter versteht man die Eingabe und Verwendung von Text, der in beliebigen Sprachen (etwa Japanisch, Chinesisch oder Koreanisch) geschrieben sein kann. Das Besondere daran ist, dass diese Zeichen über Tastenkombinationen eingegeben werden können. Sie können Tausende von Zeichen aus den unterschiedlichsten Sprachen mit Tastenkombinationen erzeugen und Java kann damit umgehen (sowohl bei der Eingabe, aber auch im AWT allgemein oder anderen Ausgaben). Die Technik ist wichtig, um Geräte zu unterstützen, denen einige Tasten fehlen (etwa Handheld-Computern). Damit wird ein wichtiger Schritt in Richtung Plattformunabhängigkeit gemacht.
1.3.7
Java-Archive
Netscape hatte bereits im Navigator der Version 3.0 das Packen mehrerer Java-Kompilate (also .class-Dateien) in eine Datei implementiert. Umgesetzt hat Sun diese Idee seit der Version 1.1 in den so genannten JARDateien (Java-Archive sind Dateien mit der Erweiterung .jar). In diesen JAR-Archiven können neben .class-Dateien gleichermaßen Image- und Sound-Dateien verpackt werden. Statt vieler einzelner und unkomprimierter Dateien wird beim Laden aus dem Netz ein gepacktes Archiv übertragen. Der Vorteil dieses Konzepts liegt darin, dass die Applikation in einer einzigen HTTP-Transaktion übertragen wird und nicht in vielen einzelnen Übertragungsschritten. Natürlich kann durch die Komprimierung der Daten zusätzlich die Transferzeit erheblich gesenkt werden. Die JAR-Funktionalität wird in dem ab der Version 1.1.x neu hinzugekommenen Package java.util.jar realisiert. Das zugehörige Java Archive Tool heißt jar. Das Tool wurde für das JDK 1.3 nochmals erheblich überarbeitet und arbeitet gegenüber den Vorgängerversionen bedeutend schneller.
Java 2 Kompendium
43
Kapitel 1
What's new?
1.3.8
Datenbankunterstützung
In Version 1.0 war für Java-Applikationen noch keine Datenbankunterstützung implementiert, was sich ab der Version 1.1 änderte. Das JDK bot nun die Möglichkeit, auf SQL-Datenbanken zuzugreifen. Bemerkenswert an dem JDK 1.2 waren insbesondere die neuen Zugriffsmöglichkeiten auf SQL-Datenbanken (inklusive SQL-3-Datentypen). Dazu dient auf der Seite von Java 2.0 die JDBC-2.0-Schnittstelle (Java Database Connectivity). Diese wiederum greift über die standardisierte ODBC-Schnittstelle auf eine SQLDatenbank zu. Die ODBC-Schnittstelle (Open Database Connectivity) stammt von Microsoft und basiert auf dem gleichen Konzept wie JDBC – dem X/Open SQL CLI (Call Level Interface). In dem Package java.sql steckt die wesentliche JDBC-Funktionalität von Java.
1.3.9
Verteilte Programmierung und Object Serialization
Im Bereich der verteilten Programmierung entwickelte sich Java über die verschiedenen Versionen erheblich. Das Remote Method Invocation Interface (RMI) bietet die Möglichkeit, beliebige Java-Klassen, die auf einer anderen virtuellen Maschine laufen, anzusprechen. Dabei ist es egal, ob die virtuelle Maschine lokal vorhanden ist oder irgendwo im Internet ausgeführt wird. Die Erweiterung des RMI-Konzeptes 1.2 erlaubt es nun, Objekte anhand einer Referenz zu reaktivieren, wenn diese zuvor persistent (dauerhaft gespeichert) gemacht wurden (Remote Object Activation). Zwei neue Programme, rmic – der Java RMI Stub Compiler, der übrigens im JDK 1.3 diverse neue Optionen hinzugefügt bekam – und rmiregistry (Java Remote Object Registry) dienen ab der Version 1.1.x zur programmiertechnischen Umsetzung des RMI-Konzeptes. Neu im JDK 1.2 ist das Tool rmid (Java RMI Activation System Daemon). In diesem Zusammenhang wurde gleichfalls das Konzept der so genannten Object Serialization aufgenommen. Es ermöglicht das Abspeichern der Inhalte eines Objekts in einen Stream. Dieser kann z.B. eine beliebige Datei sein. Ein Objekt kann in einem Stream zwischengespeichert und zu einem späteren Zeitpunkt daraus wieder aufgebaut werden. Die Lebensdauer eines Objekts kann also über die eigentliche Laufzeit eines Programms hinaus verlängert werden. Hauptanwendung hierfür ist das Versenden von Objekten über das Netzwerk im Zusammenhang mit dem RMI-Konzept. Das Package java.io ist von den entsprechenden Erweiterungen betroffen. Das JDK 1.3 erlaubt es mittlerweile, dass auch Strings, die länger als 64 KByte sind, serialisiert werden können. Das Object Serialization Tool für Java heißt serialver. 44
Java 2 Kompendium
Die Java-Neuerungen
1.3.10
Kapitel 1
Java IDL
Als eine logische Fortsetzung dieser RMI-Entwicklung folgte die Java IDL (Interfaces Definition Language), die es Java ermöglicht, eine Verbindung zu anderen Verteilungsplattformen wie zum Beispiel CORBA aufzubauen, d.h. entfernte Schnittstellen über IDL zu definieren. IDL ist eine Definitionssprache, die die Kommunikation zwischen verschiedenen Programmiersprachen über Schnittstellen ermöglicht und in das CORBA-Konzept (Common Object Request Broker Architecture) integriert. CORBA liegt derzeit in der Version 2.0 vor und ist ein plattformunabhängiger Standard, der die Kommunikation von Objekten im Netzwerk definiert. Java 2.0 bietet vollständigen CORBA-Support, indem der CORBA-Standard mithilfe des CORBA IDL Compilers integriert wird. Die Internetadresse und einige andere interessante Links zu CORBA folgen in der Tabelle: URL
Beschreibung
http://siesta.cs.wustl.edu/~schmidt/ corba.html
Detaillierte Informationen zu CORBA
http://siesta.cs.wustl.edu/~schmidt/ corba-urls.html
Eine CORBA-Link-Sammlung
http://www.sun.com/
Die Homepage von Sun lässt ebenfalls eine Suche nach dem Begriff CORBA zu.
Tabelle 1.1: CORBA-Quellen
Seit der Finalversion des JDK 1.2 haben sich in der Java IDL zahlreiche Veränderungen ergeben, die im Wesentlichen auf Grund der 2.3 OMGSpezifikation notwendig waren. Das neue API des JDK 1.3 berücksichtigt die Neuerungen mit neuen Paketen bzw. Erweiterungen der bestehenden OMG-Pakete.
1.3.11
JavaBeans
In den letztgenannten RMI-Kontext fallen ebenso die so genannten JavaBeans – Java-Komponenten innerhalb eines Objektmodells. JavaBeans ist ein portables, plattformunabhängiges, in Java geschriebenes Komponentenmodell, das von JavaSoft in Kooperation mit führenden Industrieunternehmen der Computerbranche (klangvolle Beispiele sind Apple, Borland, IBM, JustSystem, Microsoft, Netscape, Rogue Wave, SunSoft, Symantec und viele andere) entwickelt wurde. Erstmals wurde das Modell am 4. September 1996 im Internet als Konzept vorgestellt, die konkrete Realisierung dauerte natürlich länger. Die JavaBeans sind eine der wichtigsten Erweiterungen des Java-SDK 1.1 (SDK steht für Software Development Kit). In das JDK 1.2 gehörte die nächste Generation der JavaBeans (Codename Glasgow) als fes-
Java 2 Kompendium
45
Kapitel 1
What's new? ter Bestandteil. Vergleichbar sind JavaBeans mit ActiveX-Controls oder OCX-Controls. Sie können wie diese visuell manipuliert werden und bieten im Allgemeinen über so genannte Bridges eine Schnittstelle zu Komponenten wie ActiveX-Controls oder OLE-Komponenten an. Im Gegensatz zu diesen Komponenten sind JavaBeans jedoch explizit plattformunabhängig und vor allen Dingen im Sicherheitskonzept von Java integriert. Häufig wird gefragt, ob JavaBeans nicht dasselbe wie Applets sind. JavaSoft gibt als wesentlichen Unterschied die Möglichkeit der visuellen Erstellung und eine relativ eng ausgelegte Zielfunktionalität von Beans an. Allerdings stellt JavaSoft ebenso fest, dass Applets so entwickelt werden können, dass sie wie Beans aussehen und arbeiten. Um JavaBeans entwickeln und dann zu komplexen Anwendungen kombinieren zu können, musste ein eigenes Beans Developement Kit (BDK 1.0) von Sun dem JDK 1.1 (und folgende) beigefügt werden. Dieses gehört nicht zum JDK 1.2 und ist eine der Erweiterungen, die den Unterschied zwischen der vollständigen Plattform und dem JDK ausmachen. Mittlerweile sind alle wichtigen kommerziellen Java-Entwicklungstools in der Lage, JavaBeans zu erstellen. Einmal entwickelte Beans werden üblicherweise in die oben beschriebenen JAR-Dateien verpackt und beim Enduser in das Applet oder die Applikation integriert.
1.3.12
Servlets
Das Java Servlet API erlaubt die Erstellung von so genannten Java Servlets. Eingeführt wurde diese Technologie während der 1.1.x-Upgrades und richtig manifestiert in der Version 1.2. Allerdings zählt im Rahmen der Java-2Plattform auch das Servlet-API (javax.servlet.*) nicht mehr zum JDK (wie noch bis zur JDK-1.2-Beta-3-Version), sondern gilt als eigenständiges Produkt – das Java Servlet Development Kit. Es ist wie das JDK frei von Sun zur Verfügung gestellt und kann von der Servlet Product Page unter http:// java.sun.com/products/servlet/index.html heruntergeladen werden. Servlets bedeuten eine Verlagerung von Funktionalität vom Client auf den Server. Die Assoziation zu CGI-Scripts ist naheliegend. Servlets verbrauchen jedoch viel weniger Ressourcen und sind – da sie in Java geschrieben sind – im Gegensatz zu CGI-Scripts plattformunabhängig.
1.3.13
Inner Classes und Anonymous Classes
Neu in 1.1 wurden die so genannten Inner Classes eingeführt. Klassen und Interfaces können damit innerhalb anderer Klassen eingebettet werden. Solche Klassen werden innere Klassen genannt. Sie können ausschließlich die Klassen unterstützen, in die sie integriert sind.
46
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
Damit unterstützt Java die bisher schon bei vielen Programmiersprachen praktizierte Blockstruktur innerhalb einer Klasse bzw. das dort verwendete Konstrukt. Anonymous Classes steht für eine Abart der inneren Klassen. Es handelt sich um eine Kurzform von inneren Klassen. Sie haben allerdings keinen Namen, nur eine Implementation mit new. Der Compiler generiert bei den anonymen Klassen eine namenlose Klasse, die wie spezifiziert eine bestehende Klasse dann überschreibt. Das Ende einer anonymen Klasse wird durch das Ende des mit new eingeleiteten Ausdrucks festgelegt.
1.3.14
Native Methoden
Das API, um C-Implementationen für Java-Methoden zu schreiben, ist seit der Version 1.1.x komplett gegenüber der Version 1.0.x geändert worden. Das Mapping wurde einheitlich geregelt und es ist nur ein innerer Bestandteil der Java Virtual Machine. Das Java Native Interface (JNI) ist viel einfacher anzuwenden und zu lernen als das davor verwendete Konzept. Das JNI ist eine Standardprogrammierschnittstelle, um native Java-Methoden zu schreiben und die JVM in native Applikationen einzubetten. Das primäre Ziel ist die binäre Kompatibilität von nativen Methodenbiliotheken über alle JVM-Implementationen auf den unterstützten Plattformen. JDK 1.2 erweiterte gegenüber dem JDK 1.1 das Java Native Interface mit einige neuen Features, es bleibt jedoch weitgehend gleich. Wichtig ist, dass es nun getrennte Unterstützung von dem Impelemntation von Native-Code über das JNI und älteren Schnittstellen gibt. Der resultierende Code ist erheblich effizienter als zuvor.
1.3.15
Reference Objects
Neu im JDK 1.2 wurde das Reference-Objects-Konzept eingeführt. Darunter versteht man, dass die Referenz auf ein Objekt wie ein Objekt selbst behandelt wird und damit genauso manipuliert und untersucht werden kann (siehe auch RMI). Dies funktioniert sogar noch dann, wenn auf das Objekt selbst gar nicht mehr zugegriffen werden kann (etwa, weil der Garbage Collector das Objekt gelöscht hat). Eine potenzielle Anwendung für diese Referenzobjekte ist der Aufbau eines einfachen Caches.
1.3.16
Multimedia-Unterstützung in Java 2
Multimedia nimmt in der Java-2-Plattform großen Raum ein. Mit der neuen Java-Version wird beispielsweise die Audio-Unterstützung erweitert. Sowohl in Applikationen als auch in Applets lassen sich nun MIDI-Dateien (Typ 0 und Typ 1) sowie RMF-, WAVE-, AIFF-, und AU-Dateien in hoher
Java 2 Kompendium
47
Kapitel 1
What's new? Tonqualität abspielen und zusammenmischen. Das JDK 1.3 stellt insbesondere für die Arbeit mit MIDI-Dateien einige neue Pakete zur Verfügung. Das vollständige Java Sound API bleibt bei dieser Erweiterung weitgehend erhalten, nur die Engine wurde ausgetauscht. Sie wird als eigene Sammlung ausgeliefert. Allgemein wird die Multimedia-Unterstützung von Java immer mehr in ein eigenes Framework verlagert. Zu der Java-2-Plattform zählt als eigenes Paket das Java Media Framework (JMF), das eine sehr komfortable Verbindung von verschiedenen Mediatypen mit Java-Applets und -Applikationen erlaubt (http://java.sun.com/products/java-media/jmf/). Das JMFAPI unterstützt eine einfache und vereinheitlichte Synchronisation, Kontrolle, Verarbeitung und Präsentation von komprimierten, Zeit-basierenden Mediadaten. Dies beinhaltet sowohl Javastreams als auch MIDI, Audio und Video auf allen Java-Plattformen.
1.3.17
Die Java-2D-API-Referenz
Das im JDK 1.3 enthaltene 2D-API bietet umfangreiche Klassen für die Erstellung und Entwicklung von grafischen Applikationen und Applets. Der Anspruch dieses APIs geht erheblich über das hinaus, was davor in der Grund-Java-Grafik vorgesehen war. So stehen dort primitive Grafikformen (etwa die verschiedensten Geometrieformen) sowie transparente Images (Alpha Channel) direkt als vorgefertigte Methoden zur Verfügung. Die 2DAPI lässt sich zudem zur elektronischen Bildbearbeitung oder für Präsentationen in Java verwenden. Leider muss man festhalten, dass das Java-2D-API seit der Finalversion des JDK 1.2 vielfach inkompatibel zu den davor verbreiteten Java-2D-APIs ist (sogar späten JDK-1.2-Betaversionen). Es gibt diverse Methoden, Felder und ganze Klassen, die nicht nur verlagert, sondern teilweise vollständig abgelöst wurden. Und nicht etwa, indem sie als deprecated erklärt wurden wie bei sonstigen Bestandteilen des JDK-APIs. Es gibt sie teilweise einfach nicht mehr. Man findet keinen Hinweis darauf, dass sie in einer Vorgängerversion verwendet wurden und was jetzt als Ersatz für die Funktionalität zu verwenden ist. Wenn Sie beispielsweise die Klasse java.awt.font.StyledString – eine finale Subklasse von font in der Beta 3-Version des JDK 1.2 – suchen, werden sie in der gesamten Dokumentation des JDK 1.2 bzw. 1.3 keinen Hinweis mehr darauf finden. Zwar werden das Konzept von Java 2D und die allgemeinen Veränderungen über die einzelnen Versionen davon in der offiziellen Dokumentation recht ausführlich behandelt. Dies hilft aber herzlich wenig, wenn Sie einen Java-Quelltext nach dem alten Konzept erstellt haben, ihn mit dem neuen Compiler übersetzen und nur die nichtssagende Fehlermeldung erhalten, ein bestimmtes Element sei nicht vorhanden. Es gibt keinen Hinweis auf eine Veränderung der API, und der Anwender steht da, als ob er einen Fehler 48
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
gemacht hätte. Obwohl das neue Java-2D-Konzept mit einigen Detailmängeln der Vorgängerversionen aufgeräumt hat (insbesondere in der Darstellung des Hintergrundes bei Rotationen), werden viele Anwender ihren Wortschatz an Flüchen herauskramen, wenn bisher fehlerfreie Quelltexte scheinbar ohne Grund nicht mehr zu übersetzen sind.
1.3.18
Swing JDK 1.2/1.3 und die Java Accessibility API
Swing ist der Teil der Java Foundation Classes (JFC), der einen vollständigen Satz von GUI-Komponenten (Graphical User Interface = grafische Benutzerschnittstelle) implementiert. Das Look and Feel von Java-Benutzerschnittstellen passt sich immer mehr den Standards der GUI-Welt an. Das Swing-Konzept geht jedoch noch weiter. Swing ist vollständig in reinem Java entwickelt und dort ohne Widersprüche implementiert. Swing basiert auf dem JDK 1.1 Lightweight UI Framework und versetzt Sie in die Lage, einen Satz von GUI-Komponenten zu entwickeln, die sich automatisch zur Laufzeit dem passenden Look and Feel für jede Betriebssystemplattform (Windows, Solaris, Macintosh) anpassen – wenn Sie es wollen. Swing-Komponenten beinhalten alle bereits vorher existierenden AWT-Komponentensätze (Button, Scrollbar, Label usw.) sowie einen großen Satz von HigherLevel-Komponenten (Baumansicht, Listboxen usw.). Mit dem Java Accessibility API (ab 1.2) können Entwickler Java-Applikationen generieren, die mit innovativen Hilfstechnologien (etwa Spracheingabesystemen oder Blindensprache-Terminals) interagieren können. Die daraus resultierenden Applikationen sind nicht auf bestimmte technische Plattformen beschränkt, sondern können auf jeder Maschine eingesetzt werden, die die virtuelle Javamaschine unterstützt. Die neue Java Accessibility API ist nun eines der Kernbestandteile der Java Foundation Classes. Die Finalversion des JDK 1.2 hat bezüglich der Swing- und AccessibilityPackages eine erhebliche Veränderung gegenüber den Vorgängerversionen (auch den Betaversionen des JDK 1.2 bis Beta 3) erfahren. Die vorher in dem Namensraum com.sun.java.* (oder kurz java.*) untergebrachten Pakete wurden samt und sonders in den Namensraum javax.* verlagert. Außerdem wurde die Paketstruktur erheblich verändert. Die alte SwingAPI-Referenz (vor dem JDK 1.2 Final) sah wie folgt aus: java.awt.swing java.awt.swing.basic java.awt.swing.beaninfo java.awt.swing.border java.awt.swing.event java.awt.swing.jlf java.awt.swing.motif java.awt.swing.multi
Java 2 Kompendium
49
Kapitel 1
What's new? java.awt.swing.plaf java.awt.swing.table java.awt.swing.target java.awt.swing.text java.awt.swing.undo
Die ehemalige Accessibility-API.Referenz war Folgende: java.awt.accessibility
Ab dem JDK 1.2 Final und im JDK 1.3 gilt (inklusive der anderen in dem Namensraum javax.* vorhandenen Pakete) folgende Struktur (auch die wurde gegenüber dem JDK 1.2 Beta erweitert): javax.accessibility javax.naming javax.naming.directory javax.naming.event javax.naming.ldap javax.naming.spi javax.rmi javax.rmi.CORBA javax.sound.midi javax.sound.midi.spi javax.sound.sampled javax.sound.sampled.spi javax.swing javax.swing.border javax.swing.colorchooser javax.swing.event javax.swing.filechooser javax.swing.plaf javax.swing.plaf.basic javax.swing.plaf.metal javax.swing.plaf.multi javax.swing.table javax.swing.text javax.swing.text.html javax.swing.text.html.parser javax.swing.text.rtf javax.swing.tree javax.swing.undo javax.transaction
1.3.19
Drag&Drop
Java unterstützt den Datenaustausch zwischen Programmen per Drag&Drop (kurz DnD). Das Drag&Drop-API der Java-2-Plattform zählt ebenfalls zu der JFC und ermöglicht den Datentransfer zwischen Java und 50
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
Native-Applikationen. Die Integration in das Swingkonzept wurde bereits in den ersten Betaversionen des 1.2-JDK vollzogen. Es gab dort jedoch durch einen Fehler in dem Swing-Eventhandling in den ersten 1.2-Betaversionen noch diverse Probleme, sodass erst ab dem 1.2-Final von einer echten Implementation gesprochen werden kann. Vollständig unterstützt werden Drag&Drop für Win32 und OSF/Motif (auf Solaris), d.h., der Datentransfer innerhalb einer JVM, zwischen verschiedenen JVMs und sogar zwischen einer JVM und einer nativen Plattform, die ihrerseits DnD-fähige Applikationen beinhaltet. Vollständig implementiert, getestet und unterstützt sind u.a. DnD-Transfers von Text (ASCII, ISO8859-1, Unicode). Transfer von Text der Form X11 Window System mit COMPOUND_TEXT-Verschüsselung wird nicht unterstützt (nicht kompatibel zu Unicode). Daneben können auch Dateien und Klassen per DnD transferiert werden (bis auf wenige Situationen getestet und vollständig unterstützt). DnD von Datentypen (plattformspezifisch oder selbst definiert), Instanzen oder serialisierten Java-Objekten sind in der Java-2-Plattform ebenfalls möglich.
1.3.20
Die Java-Standardklassen und die Datei classes.zip
Zwischen der Version 1.1 des JDK bzw. den ersten drei Betaversionen des JDK 1.2 auf der einen Seite und der Finalversion 1.2ff auf der anderen Seite hat sich der Zugriff auf die Laufzeitumgebung von Java erheblich verändert. Insbesondere wird seit dem JDK-1.2-Final die Datei classes.zip nicht mehr benötigt (sie wird auch nicht mehr zur Verfügung gestellt – Ersatz ist im Wesentlichen die Datei rt.jar). Diese hatte in den ersten Versionen von Java die Standardklassen von Java enthalten und war dementsprechend zwingend notwendig. Jedoch hat sich die Laufzeitumgebung von JDK 1.2 vollständig geändert. Seit dem JDK 1.2 verwendet das JDK für den Zugriff auf die Systemklassen nun einen Bootstrap Class Loader, der seinen eigenen Pfad für die Suche der Systemklassen verwendet. Die Folge ist, dass im neuen JDK auch nur noch selbst erstellte Klassen bei Bedarf in den CLASSPATH aufgenommen werden müssen, wobei diese Bemerkung noch ausführlicher diskutiert werden muss. Das soll aber erst bei der Besprechung der JDK-Tools erfolgen.
1.3.21
Veränderungen bei den Tools
Nicht nur neue Klassen und Methoden kamen von der Java-Einführung bis hin zu der aktuellen Java-Version hinzu. Einige der neuen Java-Fähigkeiten konnten damit praktisch nutzbar gemacht werden, indem die bereits vorhandenen JDK-Programme erweitert wurden. Aber viele der neuen Funktionalitäten machten gänzlich neue Java-Tools notwendig. Die Programme
Java 2 Kompendium
51
Kapitel 1
What's new? werden ausführlich im Rahmen des Abschnitts über die JDK-Tools beschrieben. Hier ist jedoch schon einmal vorab eine Liste der Programme, die ab der Version 1.1 hinzukamen: Das Java Archive Tool (jar) Das Digital Signing Tool (javakey) – nur in der Version 1.1 vorhanden Der Native-To-ASCII Converter (native2ascii) Der Java RMI Stub Converter (rmic) Das Tool Java Remote Object Registry (rmiregistry) Das Serialisierungstool Serial Version Command (serialver) Das Konvertierungstool AWT 1.1 Conversion Tool (updateAWT) Das Programm extcheck, ein Diagnose-Tool für Jar-File-Versionskonflikte Mit oldjava bzw. oldjavaw stehen zwei Versionen eines Javainterpreters zur Verfügung, der zum Ausführen von älteren Java-Applikationen genutzt werden kann. Dies ist unter anderem dann vonnöten, wenn diese über einen eigenen Sicherheitsmanager verfügen, der auf dem alten Sicherheitsmodell von Java beruht. Das Tool tnameserv erlaubt den Zugriff auf den benannten Service. Selbstverständlich wurden auch die bestehenden Tools im Laufe der Releasewechsel immer wieder überarbeitet, sodass hier nur ein paar besonders wichtige Details genannt werden sollen. Der Java-Compiler javac wurde für das JDK 1.3 komplett überarbeitet und bzgl. der Performance verbessert. Bereits seit dem JDK 1.2 gibt es die Option -target version. Über die Versionsangaben kann festgelegt werden, auf welcher virtuellen Maschinen eine Applikation laufen soll. Der Java-Interpreter und einige weitere Tools verstehen im JDK so genannte Non-Standard-Options. Neben dem normalen Satz von Standardoptionen gibt es die Möglichkeit, einen Satz von weitergehenden Kommandozeilenoptionen zu verwenden. Diese Non-Standard-Options beginnen fast immer mit einem -X, etwa -Xdebug oder -Xverify. Wichtigster Unterschied zwischen den Standardoptionen und den Nicht-Standardoptionen ist, dass die Unterstützung für die Standardoptionen im JDK 1.2 und allen zukünftigen Versionen der JVM von Sun garantiert wird. Eine Unterstützung für die Nicht-Standardoptionen wird jedoch ausdrücklich für zukünftige Versionen der JVM nicht garantiert.
52
Java 2 Kompendium
Die Java-Neuerungen
Kapitel 1
In Bezug auf die Sicherheit von Java haben sich über die verschiedenen Versionen des JDK häufig Veränderungen ergeben. Besonders wichtig war die Ersetzung des javakey-Tools durch keytool, jarsigner und policytool im JDK 1.2.
1.3.22
Neues Lizenzierungsmodell für Java 2.0
Mit der neuen Java-Plattform 2.0 und dem JDK 1.2 wurde auch ein neues Lizenzierungsmodell eingeführt, das die Java-Entwicklung weiter vorantreiben sollte. Dieses erleichterte insbesondere die Unterstützung von nichtkommerziellen Entwicklungen. Die Idee beruhte darauf, dass der Sourcecode des Java Runtime Environment im Internet bereitgestellt wird und von Entwicklern kostenlos benutzt und für eigene Zwecke erweitert werden darf. Und dies ohne die bis dahin vorhandene Verpflichtung, die Neuerungen von Sun wieder kostenlos zur Verfügung zu stellen. Für nichtkommerzielle Anwendungen beinhaltete das Lizenzierungsmodell auch keinerlei weitere Lizenzgebühren, wohingegen bei kommerziellen Entwicklungen – aber erst beim konkreten Vertrieb dieser Produkte – weiterhin Lizenzgebühren an Sun fällig wurden. Sun machte diese neue Lizenzpolitik folgendermaßen schmackhaft: »Das neue Modell ist eine Investition in die Zukunft unserer Kunden. Unter diesem neuen Modell verdienen auch wir kein Geld, bis diese mit Java Geld verdienen.« Sun behielt sich ansonsten eine Kompatibilitätskontrolle von Weiterentwicklungen ihrer Java-Umgebung vor. Beides – die offene Lizenzpolitik auf der einen Seite und die Kontrolle von Kompatiblitätsstandards auf der anderen Seite – sollte nach Aussage von Sun eine Balance zwischen einer offenen Weiterentwicklung von Java und einem harmonischen Plattformstandard gewährleisten. Diese Lizenzpolitik erwies sich aber entgegen der Marketingaussagen von Sun nicht als Initialzündung für das JDK 1.2 und Java 2, sondern das Gegenteil war der Fall. Die Industrie konnte sich mit dem Lizenzierungsmodell überhaupt nicht anfreunden und dementsprechend wurde der Java-2Standard nur sehr langsam umgesetzt. Da das JDK 1.2 in Bezug auf Performance nicht das hielt, was man sich davon versprochen hatte, dauerte es bis zur Einführung des JDK 1.3, bis die Euphorie der ersten Java-Versionen die Java-2-Plattform erreichte. Das JDK 1.3 hat aber dann auch bei der bis dahin skeptischen Industrie für Java den endgültigen Durchbruch geschafft.
Java 2 Kompendium
53
Kapitel 1
What's new?
1.4
Zusammenfassung
Zusammenfassend wollen wir festhalten, dass Java 2.0 sehr viele Neuerungen gebracht hat. Zum großen Teil sind sie nur für fortgeschrittene Programmierer interessant, die vor allem im professionellen Bereich Anwendungen erstellen. Dazu zählen RMI, Sicherheitsaspekte, Datenbankzugriffe oder Reflection. Andere Neuerungen sind jedoch auch schon für den OttoNormal-Programmier und sogar den Einsteiger sehr interessant. Insbesondere sollte die HotSpot-Technologie des JDK 1.3 zur Beschleunigung von Java-Prozessen den letzten echten Mangel von Java beseitigt haben.
54
Java 2 Kompendium
2
Schnuppertour Java
Obwohl Java noch nicht alt ist, hat es bereits eine bewegte Vergangenheit hinter sich. So hat Java Gegner zu gemeinsamen Projekten vereint, die ohne diese revolutionäre Technik sich wahrscheinlich nie an einen Tisch gesetzt hätten. Apple und Microsoft kooperieren beispielsweise seit geraumer Zeit bei der Entwicklung ihrer virtuellen Java-Maschinen. Aber Java erzeugt auch Unfrieden. Bekanntlich laufen diverse Klagen zwischen Sun und Microsoft. Diversen Quellen zufolge ist der Java-Erfinder Sun Gegner Nummer 1 von Microsoft. Dies macht sicher deutlich, wie mächtig Java ist, welches gewaltige Sprengpotenzial sich hinter diesem kleinen Wort verbirgt. Ob in Kooperation oder ohne Partner – zahlreiche Giganten der Computerbranche setzen mittlerweile auf Java. Die Liste liest sich wie das »Who is who« der EDV-Welt. Aber auch außerhalb der EDV-Kernbranche gibt es mehr und mehr Java-Projekte: Industrie, Banken, Versicherungen, Kreditkartenfirmen. Es gibt wahrscheinlich keine Branche, wo keine großen Java-Projekte laufen. Insbesondere nach der Jahrtausendwende und dem Freiwerden der davor in Altprojekten gebundenen Ressourcen haben Java-Projekte erheblich zugenommen. Java hat sich als eine der wichtigsten Programmiertechniken der Gegenwart etabliert. Und obwohl niemand in die Zukunft sehen kann, riskiert man wohl keine Fehlaussage, wenn man Java als die Programmiersprache der Zukunft bezeichnet. Bevor wir mit Java als Programmiersprache beginnen, soll auf die Java-Welt und das Java-Umfeld im weiteren Sinn eingegangen werden. Java unterscheidet sich in vielerlei Hinsicht von anderen Programmiersprachen wie COBOL, FORTRAN, BASIC, PASCAL oder aber auch SMALL TALK und C/C++. Die Unterschiede beschränken sich nicht auf die oft als Hauptkriterium genannte Objektorientierung von Java. Die Objektorientierung gilt zwar als eine der herausragenden Eigenschaften von Java und dürfte ein entscheidender Grund für den phänomenalen Erfolg von Java sein. Die Differenzen umfassen jedoch die komplette Java-Welt und das Java-Umfeld selbst. Immerhin gab es auch schon vor Java objektorientierte Sprachen wie Lisp oder Small Talk, die allerdings nie über ein »Mauerblümchendasein« hinaus kamen. Java muss also mehr bieten als nur Objektorientierung. Java ist für eine heterogene Welt, sei es das Internet mit seinen diversen Rechnermodellen, sei es ein PC, ein Mac, ein Unix-Rechner, sei es nur eine Kaffeemaschine oder ein Videorecorder, entwickelt worden. Die damit zusammenJava 2 Kompendium
55
Kapitel 2
Schnuppertour Java hängende Plattformunabhängigkeit ist das zweite wichtige Kriterium, um die Bedeutung von Java einschätzen zu können. Deshalb ist die Beschäftigung mit der Java-Welt sicher ein guter und gewinnbringender Einstieg in die Materie.
2.1
Was ist Java?
Java ist eng mit dem Begriff Internet verbunden. Vielfach wird Java sogar als eine reine Internet-Sprache bezeichnet. So stimmt das aber nicht, zumal Java ursprünglich gar nicht auf das Internet zielte. Internet-Sprache als Charakterisierung für Java fasst einfach nicht das ungeheure Potenzial, das in der Technologie steckt. Das oft zitierte Beispiel eines Java-Betriebssystems für eine Kaffeemaschine oder eine Waschmaschine macht die allgemeinere Bedeutung sicher deutlich. Trotzdem nimmt das Internet eine zentrale Stelle in der Java-Welt ein. Vielleicht kann man das Internet etwas unseriös als »Hebamme« für die Geburt von Java bezeichnen. Wir wollen uns Java aus diesem Grund über die Geschichte des Internets näheren.
2.1.1
Das Internet
Das Internet und seine Firmenableger – die Intranets – wachsen permanent. Das Internet boomt! Der Computer als eigenständige, unabhängige Recheneinheit gehört selbst im Privatbereich der Vergangenheit an. Kontakt zu einem Netzwerk und/oder zum Internet ist die Regel. Insbesondere sind über das Internet unzählige Rechner unterschiedlichster Bauart und mit den verschiedensten Betriebssystemen zusammengeschlossen. Das World Wide Web und die anderen Internet-Dienste sind ein riesiges, geniales, dezentrales, dynamisches, unstrukturiertes und- im besten Sinn des Wortes – chaotisches System, das sämtliche Bereiche des täglichen Lebens durchdrungen hat. Eine E-Mail-Adresse und eine Homepage sind für jedes wichtigere Unternehmen Pflicht, aber auch im Privatbereich selbstverständlich. Besonders beeindruckend ist vor allem das immer noch anhaltende rasende Wachstum des Internets. Und ein Ende ist noch nicht abzusehen. Da das Internet immer mehr von Nichtfachleuten genutzt wird, kennen auch prozentual gesehen immer weniger Anwender Details davon. Früher nutzten das Internet hauptsächlich Experten. Heute sind die Experten absolut in der Minderheit. Und so kommt es, dass das Internet von Laien oft mit dem World Wide Web (WWW) gleichgesetzt wird (so wie viele Amerikaner Bayern mit Deutschland gleichsetzen und viele Deutsche Holland mit den Niederlanden :-)). Dies kommt nicht zuletzt daher, dass die Geschichte und die anderen Dienste des Internets kaum bekannt sind. Obwohl das WWW inzwischen unbestreitbar die wichtigste Säule ist, besteht das Internet natür56
Java 2 Kompendium
Was ist Java?
Kapitel 2
lich aus mehr Diensten, ist mehr als nur das populäre WWW. Das Internet ist ein gigantisches, weltweites Computernetzwerk, das die unterschiedlichsten Dienstleistungen anbietet, die vielfach weit älter sind als das WWW. Abbildung 2.1: Das News-Fenster des Netscape Navigators
Elektronische Post, Möglichkeiten von weltweiter Werbung und Repräsentation, Diskussionsforen, das Suchen von Informationen in einer riesengroßen Informationsquelle, das Ausführen von Programmen auf entfernten Computern oder das Laden von Dateien und Programmen von – über die ganze Welt verteilten – Rechnern auf den eigenen Computer und wieder zurück sind nur einige dieser Dienste. Dazu kommen Internet-Telefonie, die Verzahnung von Arbeit auf dem lokalen Rechner und permanenten Zugriffen auf Internet-Server, Online-Bankgeschäfte und einkaufen per Internet. Wer will, kann sein ganzes Leben rund um das Internet aufbauen. Viele dieser Möglichkeiten haben primär nichts mit dem WWW zu tun (obwohl sie oft darüber mittels Verweisen genutzt werden können). Im Internet gibt es natürlich nicht nur Licht. Diverse Probleme werfen dort Schatten. Gerade die Heterogenität der Plattformen und Rechner ist sicher ein Hauptproblem für Software im Internet. Andere wesentliche Probleme betreffen die Interaktion zwischen Anwendern an ihren Clients und den Servern sowie Sicherheitsfragen. Java bietet dafür und für viele andere InternetFragen einen wichtigen Lösungsansatz.
Java 2 Kompendium
57
Kapitel 2
Schnuppertour Java
2.1.2
Ein kurzer Abriss der Internet-Geschichte
Die Geschichte des Internets zeigt eines der wenigen nützlichen Resultate des kalten Kriegs der vergangenen Jahre. Die Furcht amerikanischer Militärs vor einem Atomschlag durch die ehemalige UdSSR veranlasste in den späten Sechzigerjahren die Vereinigten Staaten von Amerika, eine Organisation namens Advanced Research Projects Agency (ARPA) zu beauftragen, für das US-Verteidigungsministerium mit großem finanziellem Aufwand ein Rechnersystem zu entwickeln, das selbst nach einem atomaren Erstschlag der UdSSR noch funktionieren sollte und den Gegenschlag organisieren konnte. Erstes Resultat war im Jahre 1969 ein Forschungsnetzwerk aus vier miteinander verbundenen Großrechnersystemen. Ein zentraler Großrechner als Mittelpunkt dieses Rechnersystems kam nicht in Frage, weil bei seinem Versagen ein Gesamtausfall des Rechnersystems die Folge gewesen wäre. Kleinere und unabhängig voneinander aufgebaute Rechnersysteme mussten entwickelt werden. Dabei war es unmöglich, nur homogene Rechnersysteme zu fordern. Die Verbindung von heterogenen Rechnersystemen war notwendig. Diese Verbindung zwischen den einzelnen Systemen sollte unter allen Umständen funktionieren – sogar beim Ausfall eines beliebigen Rechners im Netz. Da feste Standleitungen mit Sicherheit bei einer solchen Katastrophe wie einem Atomschlag zerstört würden, reichten diese als einzige Verbindung nicht aus. Zusätzlich musste das Netzwerk – ursprünglicher Name ARPANET bzw. gelegentlich ARPNET genannt – über flexible Leitungen, etwa Telefonleitungen, kommunizieren können. Für eine maximale Fehlertoleranz und Sicherheit des Netzes sollten immer mehrere Wege zwischen sämtlichen Computern im Netzwerk möglich sein. Nachrichten im Netz mussten in der Lage sein, quasi selbstständig den Weg zum Adressaten zu finden. An jedem Knotenpunkt von Informationswegen sollte eine Nachricht selbstständig den optimalen freien Weg zum nächsten Knotenpunkt finden. Dies erzwang als eine Konsequenz die Zerlegung von Informationen in kleinere Datenpakete, die unabhängig voneinander verschickt werden konnten. Für die Datenhaltung auf den einzelnen Rechnern sah das ursprüngliche Konzept folgende Logik vor: Die Daten und Funktionalitäten sollten nicht nur auf einem Rechner, sondern auf allen unabhängigen Rechnern gehalten werden (eine Art Backup-Verfahren). In regelmäß igen Abständen sollten die Daten abgeglichen werden. Dabei wurden in der Anfangsphase immer nur komprimierte Datenpakete übermittelt, die man dann offline auswerten musste. Online-Übertragung mit direkter Verwendung der Daten, wie sie heute etwa im WWW praktiziert wird, kannte man in der Anfangszeit des Internets noch nicht. Online-Anwendungen kamen erst später hinzu.
58
Java 2 Kompendium
Was ist Java?
Kapitel 2
In der Anfangsphase wuchs das ARPANET langsam (was auf Grund der zu dieser Zeit immensen Kosten sicher verständlich ist) und bestand 1972 aus ungefähr 50 Systemen. Insbesondere zwang der Kostendruck die Militärs, das Netz für zivile Zwecke zu öffnen. Besonders die National Science Foundation (NSF), eine Dachorganisation verschiedener Bildungseinrichtungen in den USA, zeigte Interesse am Internet und sorgte dafür, dass im Laufe der Zeit zahlreiche Universitäten und andere Forschungseinrichtungen an das Internet angeschlossen wurden. Damit erlangten immer mehr Personen Zugang zum Netz, die nicht unbedingt als militärisch zuverlässig zu betrachten waren. Die Militärs begannen um die Sicherheit ihrer Geheimnisse zu bangen. Große Teile des militärischen Bereichs wurden deshalb Anfang der Achtzigerjahre in ein eigenes Netz, das MILNET, ausgegliedert. Der zivile Teil wurde Internet genannt. Woher der Name »Internet« kommt, ist nicht ganz unumstritten. Es gibt einige Varianten. Folgende ist aber die wahrscheinlichste: Das Internet wird oft als das »Netz der Netze« bezeichnet. Warum gerade »Netz der Netze« und nicht »Zusammenschluss vieler Netzwerke« oder ähnlich? Der Begriff Internet steht für Interconnected Networks. Übersetzt heißt das »Netz der verbundenen Netze«. Da zentrale Ideen des Internets flexible Möglichkeiten der Datenübertragung und die Unterstützung heterogener Rechnerplattformen waren, mussten verschiedene Protokolle entwickelt werden, über die sich die Rechner verständigen konnten und die unabhängig von der eigentlichen Rechnerarchitektur und dem normalen Befehlssatz des jeweiligen Betriebssystems waren. Ein Protokoll ist allgemein als eine Vereinbarung zu verstehen, wie bestimmte Prozesse ablaufen. Das kann sowohl auf der Ebene von zwischenmenschlichen Beziehungen (etwa einem Staatsempfang) notwendig sein, aber erst recht, wenn verschiedene Computersysteme an einer Aufgabe beteiligt sind. Andere Protokolle mussten die Verbindung zwischen den Systemen regeln. Es war ja durchaus vorgesehen, dass Verbindungen über unterschiedlichste Wege aufgebaut werden, etwa einen Telefonanschluss. Und da muss beispielsweise ein kontaktierter Rechner einen Anruf eines anderen Rechners von einem Telex-, Fax- oder Sprachanruf unterscheiden können. Zusätzlich Vereinbarungen innerhalb von Protokollen regeln die konkrete Datenübertragung und überprüfen die übertragenen Daten auf Fehlerfreiheit. Da bei jeder Datenübertragung Fehler entstehen können, sind bessere Protokolle ebenfalls in der Lage, fehlerhafte Daten zu erkennen und gegebenenfalls während der Übertragung vom Sender noch einmal anzufordern.
Java 2 Kompendium
59
Kapitel 2
Schnuppertour Java Viele im Internet gebräuchliche Protokolle basieren auf Unix-Protokollen. Grund ist, dass das ursprünglich im ARPANET hauptsächlich verwendete Betriebssystem Unix war und so waren die am Anfang verwendeten Protokolle natürlich Unix-Datenübertragungsprotokolle. 1973 wurde mit IP (Internet Protocol) ein Transportprotokoll präsentiert, das plattformunabhängigen Transport von Daten garantieren sollte. Bereits Anfang 1974 erschien eine Verbesserung – das auf IP basierende Erweiterungsprotokoll TCP (Transmission Control Protocol), das eine noch fehlerfreiere Übertragung gewährleistete. TCP funktioniert nur mit IP als Unterbau, gibt aber diesem erst seine Übertragungssicherheit. Und so kommt es, dass heute beide Protokolle meist nur noch in Verbindung verwendet werden (TCP/IP). Seit 1983 ist TCP/IP das Internet-Standard-Protokoll für Direktverbindungen und dient sogar zur Definition der Begriffe Internet/Intranet (alle auf dem TCP/IP-Protokoll basierenden Netzwerke). Es löste das bis dahin verwendete Internet-Standard-Protokoll NCP (Network Control Protocol) ab. TCP/IP ist ein sehr leistungsfähiges Transportprotokoll, aber eben nur ein reines Transportprotokoll. Man kann sich die Situation ganz gut vorstellen, wenn man sie mit dem Eisenbahnverkehr vergleicht. TCP/IP ist in dieser Vorstellung das Schienennetz, über das der eigentliche Verkehr rollt. Auf diesen Schienen rollen in unserem Gedankenmodell also Züge, die als Dienstprotokolle oder Internet-Dienste bezeichnet werden. Je nach Aufgabe gibt es Personenzüge, Güterzüge, Postzüge, Wartungszüge oder kombinierte Varianten. Für verschiedene Aufgaben werden verschiedene Zugarten (Dienste) eingesetzt. Aber so, wie man in einem Personenzug auch Waren transportieren kann, so können manche Dienste im Internet auch vielfältig eingesetzt werden. Vielleicht nicht so effektiv wie die Spezialvariante, aber dennoch mit Einschränkungen möglich. Auf das Internet bezogen stellt man sich TCP/IP als untere Schicht, Dienstprotokolle als eine Schicht darüber vor. Man spricht im Zusammenhang mit dem Internet-TCP/IP-Protokoll auch von einem so genannten Schichtprotokoll. Die Dienstprotokolle, die auf dem TCP/IP-»Schienennetz« aufsetzen, sind Dienste wie Telnet, FTP oder auch das WWW. Das aus HTML aufgebaute World Wide Web wurde im Mai 1991 auf den Rechnern des Kernforschungszentrums CERN (European Organisation for Nuclear Research, Genf) erstmals offiziell vorgestellt. Die ersten Ansätze dieses Projekts gehen allerdings bereits bis in den März 1989 zurück. Damals schlug ein Mitarbeiter von CERN, Tim Berners-Lee, ein Hypertext-Projekt für das Internet vor, um darüber verteilte Inhalte miteinander zu verbinden. Es sollte ein vernetztes Hypertext-System geschaffen werden, in dem die vielen Informations-
60
Java 2 Kompendium
Was ist Java?
Kapitel 2
quellen von CERN über eine gemeinsame und vor allem einfach zu bedienende Oberfläche verfügbar sein sollten. Eigens für dieses Projekt wurde eine Organisation namens W3C (http://www.w3.org) gegründet, deren ursprüngliches Ziel es also war, Wissenschaftlern aller Fachbereiche eine leicht zu bedienende Struktur zu schaffen. Viele Wissenschaftler aus EDV-fremden Sparten waren Ende der Achtzigerjahre nicht in der Lage oder gewillt, sich mit der relativ komplizierten Befehlsstruktur von FTP, Telnet oder den anderen Diensten auseinander zu setzen. Das WWW sollte auch Nicht-EDV-Freaks unter den Wissenschaftlern die Möglichkeit eröffnen, Daten und Informationen auszutauschen und in weltweiten Datenbeständen zu recherchieren. Dabei war von vornherein vorgesehen, über reinen Text hinausgehende Daten mit einzubeziehen. Basis für eine Sprache zu Beschreibung eines solchen Hypertext-Systems war SGML (Standard Generalized Markup Language – siehe: http:// www.w3.org/MarkUp/SGML/), eine bereits seit den Sechzigerjahren verwendete Beschreibungssprache zur Darstellung von Inhalten auf unterschiedlichen Plattformen. Daraus entstand die neue Beschreibungssprache HTML (Hypertext Markup Language), die mit einer geeigneten Darstellungssoftware (dem so genannten Browser) diesen Anforderungen genügte. Mit der ersten Version von HTML präsentierte das W3C zwar nur einen aus heutiger Sicht sehr einfachen Standard, in dem zunächst nur die Möglichkeit bestand, relativ simple HyperText-Systeme im Internet aufzubauen. Diese konnten jedoch bereits wie geplant neben einfachem Text und Hyperlinks bereits Grafiken enthalten. Insbesondere war damit das daraus und dem zusätzlich entwickelten Protokoll HTTP (Hypertext Transfer Protocol) entstehende WWW bereits den bisherigen Internet-Diensten in Bezug auf Anwenderfreundlichkeit überlegen. Richtig populär wurde das Internet freilich erst durch den Mosaic-Browser, den ersten WWW-Browser mit einer grafischen Oberfläche. Die gemeinsame Erfolgsstory von WWW und dem Browser begann im Jahr 1993, als dieser von Marc Andreessen am National Center for Supercomputing Applications (NCSA – http://www.ncsa.uiuc.edu/) an der Universität von Illinois zum ersten Test freigegeben wurde. Erstmals nahm neben den bisherigen Internet-Anwendern (Militärs, Wissenschaftler und EDV-Experten) eine private Öffentlichkeit Notiz vom Internet und begann eine erste Erkundungstour mit diesem Browser. Lange Zeit stand der NSCA-Mosaic als Synonym für die Darstellungssoftware des WWW. Insbesondere ist er der Vorfahr des Netscape Navigators, den Marc Andreessen 1994 entwickelt hatte, nachdem er NSCA verlassen und mit Jim Clark die Firma Netscape gegründet hatte.
Java 2 Kompendium
61
Kapitel 2
Schnuppertour Java
2.1.3
HTML
HTML ist wie gesagt die Abkürzung für Hypertext Markup Language und wurde aus der in der ISO-Norm 8779:1986 festgeschriebenen Sprache SGML (Standard Generalized Markup Language) entwickelt. HTML ist als Ableger von SGML im Gegensatz zu SGML speziell auf Hypertext-Funktionen ausgerichtet (wie man bereits aus dem Namen ableiten kann). HTML ist für die Arbeit mit Java eine zentrale Grundlage, denn die Funktionalität von Java-Applets basiert auf einer Verknüpfung mit HTML. HTML ist keine (!) Programmiersprache wie Java, PASCAL oder C/C++, sondern eine so genannte Dokument-Beschreibungssprache (oder Dokumentenformat genannt). Mit einer Dokument-Beschreibungssprache werden die logischen Strukturen eines Dokuments beschrieben und kein Programm im eigentlichen Sinn erstellt. Insbesondere fehlen HTML Variablen und Programmfluss-Anweisungen, die zentrale Bestandteile einer Programmiersprache sind. Im Grunde gibt ein Dokumentenformat nur unverbindliche Empfehlungen an eine Darstellungssoftware (bei HTML Browser genannt), wie eine bestimmte Dokumentenstruktur darzustellen ist, damit sie dem geplanten Layout und der vorgesehenen Funktionalität entspricht. Es gibt allerdings keine absolute Darstellungsvorschrift, weswegen sich Darstellungen von HTML-Seiten in verschiedenen Browsern oft erheblich unterscheiden können (eine Folge der geplanten Plattformunabhängigkeit). Zu einer durch HTML beschriebenen logischen Dokumentenstruktur gehören Verweise, aber auch Kapitel, Unterkapitel, Absätze usw. HTMLDateien bestehen dabei aus reinem Klartext. Dadurch bleiben HTMLDokumente plattformunabhängig. Wie später bei Java war diese Plattformunabhängigkeit neben der extrem einfachen Benutzerführung per Hyperlinks in einer so heterogenen Welt wie dem Internet der wichtigste Schlüssel für den Erfolg des WWW. Plattformabhängig ist im WWW immer nur die Software zum Interpretieren der HTML-Dateien (der Browser). Da von Anfang an ein in HTML geschriebenes Dokument mit den Texten, Grafiken sowie einigen weiteren multimedialen Elementen (Sound, Video usw.) verknüpft werden sollte, mussten entsprechende Techniken entwickelt werden. Elemente, die jenseits von Textanweisungen zu sehen sind, werden in einer Webseite als Referenz auf eine entsprechende externe Datei notiert. Wenn diese in einer Webseite dargestellt werden soll, muss natürlich die Präsentations-Software entsprechende Softwaremodule und die Hardware die zugehörigen Komponenten (beispielsweise eine Soundkarte für akustische Daten) verfügbar haben. Eine weitere wichtige Eigenschaft von HTML ist, Verbindungen zu anderen Internet-Diensten in eine Webseite aufnehmen zu können. Diese werden als
62
Java 2 Kompendium
Was ist Java?
Kapitel 2
Referenz in einer Webseite notiert, weshalb unter der Oberfläche des WWW viele Dienste wie E-Mail oder FTP verfügbar gemacht werden können. Es ist sogar eingeschränkt möglich, mit HTML Datenbankabfragen zu formulieren, die Resultate optisch aufzubereiten und Menüstrukturen aufzubauen. Auch Interaktion mit Anwendern ist – allerdings mit erheblichen Einschränkungen – in purem HTML zu realisieren. Hinter der Normung von HTML stand und steht auch heute noch das World Wide Web-Consortium (W3C – http://www.w3.org) mit Sitz in Genf. HTML beinhaltete in der Version 1.0 nur wenige der heute im Web zu findenden Möglichkeiten. Da bereits der Mosaic-Browser diverse eigene Features implementiert hatte, die von dem einfachen HTML-1.0-Standard stark abwichen, und sich der Browser (und noch einige andere grafische Browser) rasend schnell verbreitete, versuchte das W3C relativ zügig, einen um einige dieser neuen Möglichkeiten erweiterten HTML-Standard zu schaffen. Der im November 1993 gestartete Versuch – ein Diskussionspapier mit dem Namen »HTML + Discussion Document« – konnte sich allerdings nicht als neuer Standard durchsetzen. Das W3C hatte sich bereits als Forum von unterschiedlichsten Interessengruppen von einer effektiven Arbeit verabschiedet. Erst im September 1995 konnte der nächste HTML-Standard, die Version 2.0, verabschiedet werden. Dieser 2.0-Standard enthielt eine ganze Menge Gestaltungsmöglichkeiten für das WWW, die sich seit dem 1.0-Standard schon in diversen Browsern als zusätzliche Features etabliert hatten. Dazu gehörten unter anderem die Elemente der äußeren Dokumentenstruktur (zum Beispiel Kopfteil mit Meta- und Titelzeile, die Body-Struktur), verschiedene Arten der Überschrift, Hyperlinks, Hervorhebungen, Befehlsstrukturen zu einer flexiblen Grafikeinbindung, aber auch bereits Tabellen, Listen und Formulare. Dies waren nur ein Teil der potenziellen HTML-Möglichkeiten, denn durch die Trägheit des W3C (in Bezug auf das unglaublich dynamische Internet) hatten sich derweil verschiedenste Browser-spezifische Dialekte gebildet, unter denen eine Standardisierung des WWW auch heute noch krankt. Die nächste HTML-Version (3.0) wurde wegen der mangelnden Konsensfähigkeit der am W3C beteiligten Organisationen und Unternehmen nie offiziell verabschiedet. Allerdings war die Version 3.0 durch viele mehrfach vorhandene, aber syntaktisch unterschiedliche Anweisungen so aufgebläht, dass die in der Ende 1996 offiziell verabschiedete Version 3.2 vorgenommene Straffung dringend notwendig war. Zwar hatte HTML 3.2 nicht mehr alle in 3.0 versuchten Möglichkeiten. Dafür wurde nun offiziell die Fähigkeit integriert, Objekte aus anderen Internet-Techniken in eine Webseite einzubauen. Insbesondere lassen sich seit dem 3.2-Standard Java-Applets in jede beliebige Webseite integrieren.
Java 2 Kompendium
63
Kapitel 2
Schnuppertour Java Der HTML-Standard 3.2 hatte ungefähr ein Jahr Bestand. Ende 1997 fand die offizielle Verabschiedung eines neuen HTML-4.0-Standards statt, der auch heute noch aktuell ist. Dieser neue HTML-Standard beinhaltet einige interessante Details, die in großen Teilen von der Java-Entwicklung beeinflusst wurden oder zumindest parallel dazu gehen.
Abbildung 2.2: Der HTML-4.0Standard wird auf den W3C-Seiten erstmals postuliert.
2.1.4
Die Organisation des Internets
Das Internet ist im besten Sinne ein chaotisches System. Das bedeutet, es gibt keine oberste Instanz, kein Kontrollorgan, keine Organisation zur Zensur. Zwar gehören einzelne Teile des Internets (Hosts, WANs, LANs, der private Rechner,...) irgendwelchen Besitzern, jedoch das ganze Netz selbst gehört niemandem. Es gibt keine zentrale Gesellschaft, die das Internet überwacht und lenkt. Es existieren jedoch einige Gruppen und Organisationen, die sich mit Entwicklungen im Internet befassen, versuchen Standards zu definieren, Absprachen zur Kontrolle zu treffen und das Internet (in gewissen Grenzen) lenken. Sie sind allerdings auf relativ freiwillige Kooperation der InternetTeilnehmer (vor allem der einflussreichen kommerziellen Unternehmen) angewiesen. Hier ist eine kleine Liste von wichtigen Organisationen (ohne Anspruch auf Vollständigkeit).
64
Java 2 Kompendium
Was ist Java?
Kapitel 2
Bezeichnung
Bedeutung
Beschreibung
ISOC
Internet Society
Eine nicht-kommerzielle Vereinigung von freiwilligen Mitgliedern. Sie beschäftigt sich im Rahmen von diversen Unterorganisationen mit den unterschiedlichsten Aspekten des Internets. De facto ist sie das Management des Internets (http://www.isoc.org).
IAB
Internet Architecture Diese Organisation (http://www.iab.org) hat die technische Entwicklung des Board Internets im Auge und ist in mehrere Gruppierungen unterteilt. Neue Technologien werden beobachtet und ggf. gefördert, neue Standards werden festgelegt. Dazu zählt als eine der wichtigsten Aktionen die Vergabe der IP-Adressen (vgl. folgenden Abschnitt).
DE-NIC
Deutsches Network Information Center
Für eine eindeutige Vergabe von Rechneradressen ist in jedem Land eine eigene Organisation verantwortlich. In Deutschland ist dies DE-NIC (http:// www.denic.de).
W3C
World Wide WebConsortium
Das W3C (http://www.w3c.org) mit Sitz in Genf ist für die Standards im WWW verantwortlich und hat sich mit diesem und HTML ein (Internet-)Denkmal geschaffen. Allerdings ist das W3C in vielen Bereichen eine zahnloser Tiger, denn die Browser-Hersteller kümmern sich oft nicht um die Empfehlungen des W3C.
NIC bzw. InterNIC
Internet Network Information Center
Dies ist die internationale Dachorganisation der regionalen Vertretungen und die oberste Ebene zur Verwaltung von Domainnamen (http://www.internic.net).
2.1.5
Tabelle 2.1: Organisationen im Internet
Die Adressierung im Internet
Unbestritten ist das Internet ein äußerst großes und komplexes Gebilde. Mainframes, eigenständige Netzwerke, einzelne Rechner – alle sind zu dem Netz der Netze zusammengeschlossen. Wie finden Daten in solch einem scheinbaren Chaos den Weg vom Sender zum Empfänger? Und bei einer Anfrage den Weg wieder zurück? Für diese Weiterleitung von Daten gibt es
Java 2 Kompendium
65
Kapitel 2
Schnuppertour Java im Internet spezielle Server mit Adressinformationen und einer Weiterleitungsfunktionalität – so genannte Router. Router erledigen die Weiterleitung von Daten durch das Netz, indem sie ein Datenpaket jeweils in die optimale Richtung schicken, damit das Datenpaket dem Ziel »näherkommt«. Wenn die kürzeste Wegstrecke jedoch verstopft ist (also fast immer :-)), kann die optimale Wegstrecke ein Datenpaket physikalisch vom Ziel entfernen. »Näherkommen« ist also in Bezug auf die Ankunftszeit zu sehen und irgendwann kommen die meisten Daten beim Adressat dann doch an. Wie aber sieht die Verarbeitung von Adressinformationen auf den Routern aus? In einem derartig komplizierten Computernetzwerk ist eine Orientierung und Navigation nur dann möglich, wenn es dort ein eindeutiges Adresskonzept gibt. Dabei müssen sowohl die einzelnen Rechner, aber auch die Softwarebestandteile eindeutige Adressen haben.
2.1.6
Die IP-Nummern
Zunächst zu den Computern selbst: Für jeden einzelnen Rechner innerhalb eines Netzwerks muss eine eindeutige Zuordnung existieren. Dies gilt selbstverständlich auf für das Internet. Diese Zuordnung geschieht im Internet über eine eindeutige Adresse, die unter dem Transportprotokoll TCP/IP genau vier Byte lang ist. Sie wird als IP-Nummer bezeichnet. Da in einem Byte 256 verschiedene Zeichen binär dargestellt werden können (2 hoch 8 = 256), lässt sich in jedem der vier Byte eine Zahl zwischen 0 und 255 verschlüsseln. Insgesamt sind so also rein theoretisch 4.294.967.296 (256 hoch 4) Computer im Internet adressierbar. Gewöhnlich werden die IP-Nummern im Dezimalsystem darstellt und jedes Byte mit einem Punkt abgetrennt (zur besseren Lesbarkeit). Eine fiktive IP-Nummer eines Host wäre also so darstellbar: 123.187.111.189 Das Adresskonzept der IP-Nummern sieht eine Gliederung der vier Byte in logische Abschnitte vor. Die Gliederung ist hierarchisch und in zwei wesentliche logische Abschnitte unterteilt. Der erste Teil der vier Byte ist die eindeutige Adresse eines Netzwerks, das mit dem Internet verbunden ist (der so genannte Netzwerkidentifikator). Der zweite Teil ist die eindeutige Adresse des einzelnen Rechners innerhalb dieses von dem ersten Byte eindeutig bestimmten lokalen Netzwerks (Hostidentifikator). Ein Datenpaket wird nur dann in einem lokalen Netzwerk weitergeroutet, wenn der Netzwerkidentifikator korrekt ist. Wie viele Bytes dabei für die Adresse des Netzwerks und wie viele Bytes für die Adresse des einzelnen Rechners verwendet werden, ist vom Typ des Netzwerks, d.h. der Grö ß e des lokalen Netzwerks, abhängig. Ein weltweit gültiges Regelwerk sorgt für die eindeutige Zuordnung und Klassifizierung. Zwar klingt das im ersten Moment ziemlich kompliziert und willkürlich, es
66
Java 2 Kompendium
Was ist Java?
Kapitel 2
ist dennoch gut durchdacht und bei näherem Hinsehen logisch. Lokale Netzwerke werden im Internet in drei Klassen unterteilt. Klasse-C-Netz: Das kleinste Netzwerk. Für die Adresse dieses Netzwerks im Internet werden die ersten drei Bytes der IP-Nummer herangezogen. Da dann nur noch ein Byte für die Adressen der einzelnen Rechner innerhalb dieses lokalen Netzwerks übrig ist, ergibt sich zwingend die maximale Grö ß e diese Netzwerktyps. Maximal 256 Rechner sind innerhalb eines C-Netzes theoretisch adressierbar. Davon gehen dann zwei reservierte Nummern noch ab. Klasse-B-Netz. Das B-Netz benutzt die ersten zwei Bytes für Adresse des Netzwerks innerhalb des Internets. Die übrigen zwei Bytes werden für eine Adressierung im lokalen Netz verwendet. Also stehen darin dann maximal 65.536 (256 * 256) eigenständige Rechneradressen im Rahmen der lokalen Netzwerks zur Verfügung (wieder abzüglich zweier reservierter Nummern, was die verfügbaren Hosts auf 65.534 reduziert). Klasse-A-Netz: Das A-Netz kann die grö ß te Anzahl von Rechnern beinhalten. Hier wird als konkrete Netzwerkadresse nur noch ein Byte genommen. Damit stehen drei Bytes zur lokalen Adressierung zur Verfügung (in der Realität bedeutet das 16.777.214 verfügbare Hostadressen pro Netzwerk). Wann eine IP-Adresse welchem Typ zuzuordnen ist, wird durch ein Konzept von Zahlengruppen festgelegt, die das erste Byte betreffen. Es muss ja eindeutig festgelegt sein, ob das zweite und dritte Byte bereits den lokalen Rechner adressiert. Das erste Byte von einem Klasse-A-Netz hat immer einen Wert zwischen 1 und 126. Dementsprechend gibt es maximal 126 verfügbare Netzwerke dieser Klasse. Der B-Netz-Bereich geht von 128 bis 191 (daraus resultieren maximal 16.3841 verfügbare Adressen für B-Netzwerke) und der Wert des ersten Byte von einem C-Netz liegt zwischen 192 und 223, was maximal über zwei Millionen verfügbare Adressen für C-Netzwerke bedeutet. Außer den Nummernkreisen ist keine andere Zuordnung festgelegt. Die Lücken in den Nummernkreisen sind für diverse Sondernetze reserviert. So entspricht die IP-Nummer 127.0.0.0 immer dem lokalen Host in einem Netzwerk. Aber auch einige Nummern, die mit einem der gerade beschriebenen Werten anfangen, werden nicht im Internet verwendet. IP-Nummern, die mit 192.168 beginnen, sind für lokale Adressierungen innerhalb eines Intranets reserviert.
1
16.384 = 64 * 256.
Java 2 Kompendium
67
Kapitel 2
Schnuppertour Java Durch die hierarchische Struktur der IP-Nummern wird ein Datenblock auf seinem Weg vom Sender zum Empfänger von einem Router zuerst nur in eine Grobrichtung weitergeleitet, die sich aus der ersten logischen Adressangabe (je nach Klasse dem ersten, den ersten beiden oder den ersten drei Bytes) ergibt. Erst wenn der Datenblock an dem Router angekommen ist, zu dem das lokale Netzwerk gehört, werden die genauen Adressangaben von innerhalb des Netzes liegenden Adress-Servern ausgewertet. Es gibt Überlegungen, das Adressierungskonzept zu erweitern, denn die Anzahl der Rechner und sonstigen Geräte mit Internetkontakt droht den Adressvorrat zu sprengen. Diskutiert wird eine abwärtskompatible Erweiterung der IP-Nummern auf 128 Bit.
2.1.7
Das DNS-Konzept
Bei fast allen Datenübermittlungen im Internet werden IP-Nummern verwendet, obwohl Anwender sie selten sehen. IP-Nummern sind zwar hervorragend dazu geeignet, in kompakter und eindeutiger Form eine Adressierung von Rechnern vorzunehmen, jedoch für Menschen sind diese abstrakten Zahlenkolonnen oft lästig. Aus diesem Grund wurde den Zahlencodes zusätzlich ein eindeutiger Alias-Name zugeordnet und diese Zuordnung weltweit auf speziellen Namensservern dokumentiert. In Gegensatz zu der Zuordnung der IP-Nummern auf Grund der Grö ß e der Netzwerktopologie erfolgt die Vergabe der eindeutigen Namen nicht über irgendwelche Grö ß enangaben oder sonstige topologische Eigenschaften, sondern ist ein System von logisch und inhaltlich zusammengehörigen Rechnergruppen. Dennoch ist auch dieses Namensystem hierarchisch geordnet. Logisch zusammengehörende Bereiche werden Domain genannt, woraus sich der Name für dieses Namenssystem ableiten lässt: Domain-Name-System, kurz DNS. Genau wie bei den IP-Nummern werden die einzelnen Bestandteile eines DNS-Namens mit Punkten getrennt, die hierarchische Wertigkeit der Stufen ist jedoch umgekehrt, also von hinten nach vorne zu lesen. Der hinterste Teil eines solchen Alias-Namens stellt die gröbste logische beziehungsweise inhaltliche Einteilung da (die so genannte Top Level Domain), etwa eine Nation oder eine Organisationsform. Der unter Umständen zweiteilige Mittelteil (die so genannte Local Level Domain (Teil 1 des Mittelteils) und die Second Level Domain (Teil 2 des Mittelteils – von hinten gelesen) ist eine genaue Beschreibung des Rechnerverbandes bzw. des Rechners selbst. Der vorderste Teil bezeichnet direkt den einzelnen Server auf einem Rechner bzw. Rechnerverband.
68
Java 2 Kompendium
Was ist Java?
Kapitel 2
Wenn Sie in einem Browser bei der Kontaktaufnahme zu einem Server die Statuszeile im Auge behalten, werden Sie dort kurz die IP-Nummer sehen, auch wenn Sie im Adresseingabefeld des Browsers oder beim Klick auf den Hyperlink nur den DNS-Namen verwendet haben. Gültige Alias-Namen (rein fiktiv) für eine Adressangabe in diesem DNSKonzept sind: ftp.cs.tu-muenchen.de www.rjs.de webscripting.de java.sun.com www.mut.de
Der hinterste Teil des DNS-Namens wird für Rechner, die ihren Standort in den USA haben, seit Beginn des Internets nach einem eigenen Regelwerk ausgewählt. In der Regel erfolgt kein direkter Hinweis auf die Nation. Es gibt in diesem nur in den USA gültigen (was bedeuten soll, die Rechner sind dort registriert, adressiert werden können sie von überall her und auch die physikalische Präsens ist davon unberührt) Regelwerk nur sechs (sieben mit dem nachfolgend letztgenannten Spezialfall) logische Bereiche, in die alle Computer in den USA unterteilt werden (daher ist die Nation implizit klar). In der folgenden Tabelle sind sie alphabetisch aufgelistet. Name des Bereichs
Abkürzung für
Bedeutung
com
commercial
Alle von kommerziellen Unternehmen betriebenen Rechner
edu
educational
Rechner von Ausbildungsinstitutionen (Universitäten, Schulen usw.)
gov
government
Regierungsbehörden
mil
military
Militärische Computer
org
organization
Rechner von nicht kommerziellen Organisationen
net
network
Organisationen, die ein eigenes Netzwerk betreiben
arpa
Advanced Research Die Gründungsorganisation des InterProjects Agency nets hat eine eigene Sonderform für ihre Top Level Domain. Sie gilt nur für diese Organisation.
Java 2 Kompendium
Tabelle 2.2: Top-Level in den USA
69
Kapitel 2
Schnuppertour Java Beispiele für gültige Namen für Rechner in den USA sind: altavista.digital.com www.webcrawler.com ourworld.compuserve.com
Ende 2000 wurde eine Erweiterung der Top-Level-Domains vorgenommen. Beschlossen wurden info (einzig offene neue Erweiterung. Markennamen werden bevorzugt), name (Domain-Erweiterung für Namen von privaten Personen, nur in Verbindung von Vor- und Nachname), pro (Freiberufler), biz (kommerzielle Unternehmen; Alternative zu com), museum (Museen), aero (Unternehmen der Luftfahrt) und coop (genossenschaftliche Unternehmen) Außerhalb den USA werden die Top Level Domain-Namen als Abkürzungen für die Ländernamen genommen. Diese Ländercodes sind in der ISO3166-Norm (http://www.din.de/gremien/nas/nabd/iso3166ma/) festgelegt. Ein paar wichtige Beispiele folgen: Tabelle 2.3: Top-Level außerhalb der USA
70
Top Level Domain
Abkürzung für
at
Österreich
au
Australien
be
Belgien
br
Brasilien
ca
Kanada
ch
Schweiz
de
Deutschland
dk
Dänemark
es
Spanien
fr
Frankreich
gr
Griechenland
hk
Hongkong
il
Israel
mx
Mexiko
nl
Niederlande
no
Norwegen
Java 2 Kompendium
Was ist Java?
Kapitel 2
Top Level Domain
Abkürzung für
pl
Polen
pt
Portugal
ru
Russland
se
Schweden
tr
Türkei
uk
Großbritannien
za
Südafrika
Tabelle 2.3: Top-Level außerhalb der USA (Forts.)
Für die USA ist die Top Level Domain us reserviert, obwohl dort ein anderes Konzept priorisiert wird. Wie wir bereits diskutiert haben, verwendet das TCP/IP-Protokoll IP-Nummern zur Adressierung. Die DNS-Namen müssen durch spezielle NamensServer erst in die zugehörigen IP-Nummern übersetzt werden. Da das Internet so groß und komplex ist, übersteigen die gesamten Alias-Namen die Kapazität eines einzelnen Namens-Servers. Sofern ein Alias-Name nicht auf dem zuerst kontaktierten Namens-Server zuzuordnen ist, wird entsprechend der Namenshierarchie in einem komplexen Verfahren der Übersetzungsauftrag an andere Namens-Server weitergeroutet, bis die IP-Nummer vollständig ermittelt ist.
2.1.8
Uniform Resource Locator
Computer sind über die IP-Nummern beziehungsweise ihre Alias-Namen eindeutig adressiert. Innerhalb des Internets müssen aber alle Daten und Programme in Form von unverwechselbaren Internetadressen adressiert werden. Dabei werden neben der Rechneradresse zusätzlich einige andere Angaben notwendig. Der Name dieser Internetadressen für konkrete Adressanfragen an Dokumente (im weitesten Sinn) im Internet lautet URL und steht für Uniform Resource Locator, was übersetzt ins Deutsche ungefähr »einheitliches Adressierungsschema für Objekte im Internet« bedeutet (ziemlich ungünstige Übersetzung, aber leider üblich und abgesehen vom Klang recht treffend). Einheitlich deshalb, weil mit einer URL sowohl verschiedenen Dienste wie WWW, FTP, Gopher usw. als auch Rechner selbst oder direkt Dokumente beschrieben werden können.
Java 2 Kompendium
71
Kapitel 2
Schnuppertour Java Der Begriff Objekt steht in diesem Zusammenhang für so ziemlich alles, was Sie im Netz finden. Die exakte Schreibweise ist je nach Dienstprotokoll leicht unterschiedlich, sieht jedoch in der Regel folgendermaßen aus: :// Dienstprotokoll steht beispielsweise für http, ftp, gopher, news, mailto oder wais. Danach folgt ein Doppelpunkt und fast immer zwei Schrägstriche zur Abtrennung (eine Ausnahme ist mailto).
Mit host.domain wird ein Server im Internet adressiert. Dabei kann direkt die IP-Nummer eingegeben werden, was jedoch nicht üblich ist. Meist nimmt man dafür den DNS-Namen in der Form Server.{LocalDomain}.SecondLevelDomain.TopLevelDomain
Auf einem Internet-Rechner kann unter einem Namen (also der DNSAngabe ohne den Server) eine ganze Reihe von verschiedenen Diensten parallel betrieben werden (üblich sind z.B. ein FTP-Server und ein HTTP-Server). Um auf einem ausgewählten Rechner den gewünschten Dienst zu erreichen, benötigt man oft eine weitere Information, den so genannten Port bzw. Kanal. Innerhalb des TCP-Headers steht ein zwei Byte großes Flag für Port-Nummern zur Verfügung. Damit sind 65.536 numerische Werte möglich (2 hoch 16). Die Port-Adressen 0 bis 1.023 sind dabei reserviert. Sie sind vordefinierten Diensten zugewiesen (wellknown ports). Port-Adressen über 1023 sind aber durchaus möglich. Welcher Dienst darüber angesprochen werden soll liegt in der Verantwortung des Anbieters. Das bedeutet, nahezu jeder Internet-Dienst hat einen Defaultwert, der immer dann verwendet wird, wenn man in einem URL keinen Port notiert. In der Regel braucht deshalb der Port nicht explizit angegeben zu werden. Der Default-Port für zum Beispiel einen HTTP-Server ist 80, ein FTP-Server hat den Port 21, Gopher benutzt den Port 70. Es ist allerdings möglich, die Ports für bestimmte Zwecke zu manipulieren, d.h. es ist optional möglich, in dem URL mit :port festzulegen, auf welchem Kanal dieser Server angesprochen werden soll. Das genaue Objekt, das mit einer DNS-Angabe referenziert werden soll, verbirgt sich hinter der Angabe . Dies ist eine übliche Pfad- und Dateiangabe im Rahmen der Verzeichnisstrukturen eines Rechners. Beachten Sie, dass diese gesamten Angaben von Unix abstammen und deshalb als Trennzeichen kein Backslash (wie unter DOS oder Windows), sondern Slash verwendet wird.
72
Java 2 Kompendium
Die Geschichte von Java
2.2
Kapitel 2
Die Geschichte von Java
Die Geschichte von Java geht bis ins Jahr 1990 zurück, in die Labors der amerikanischen Firma Sun Microsystem. Sun war (und ist) einer der führenden Hersteller von Workstations. Die Sun-Workstations basieren auf dem Unix-Betriebssystem Solaris und Sparc-Prozessoren. Abbildung 2.3: Die Sun-Homepage
Die Geschäfte der Firma Sun mit Workstations und Mainframes liefen zu dieser Zeit zwar gut, aber Sun-PCs waren eigentlich nicht richtig konkurrenzfähig. Als Reaktion auf den drohenden Einbruch im PC-Markt rief Scott McNealy, der Sun-Chef, auf Anraten eines seiner Programmierer – Patrick Naughton – eine Entwicklergruppe mit Namen »Green« ins Leben, dessen zentrale Mitarbeiter neben Naughton James Gosling und Mike Sheridan waren. In dem hochgeheimen Projekt – niemand außer den obersten Führungskräften von Sun wusste in der Anfangsphase Bescheid – sollte der zukünftige Bedarf an EDV analysiert werden, um einen zukunftsträchtigen Markt für Sun zu lokalisieren. Haupterkenntnis des Green-Projektes war, dass die Computerzukunft nicht im Bereich der Großrechner (soweit nichts Besonderes, denn dies ahnten auch damals schon andere), jedoch auch nicht unbedingt bei den PCs zu sehen ist (und dies war neu und nicht unumstritten). Der Consumerbereich der allgemeinen Elektronik (Telefone, Videorecorder, Waschmaschinen, Kaffeemaschinen und eigentlich alle elektrischen Maschinen, die Daten benötigten) war nach Ansicht des Green-Projektes der Zukunftsmarkt der EDV. Wichtigste Forderungen an ein neues, voll-
Java 2 Kompendium
73
Kapitel 2
Schnuppertour Java kommen plattformunabhängiges Betriebssystem für dieses Einsatzfeld waren eine erheblich grö ß ere Fehlertoleranz, eine leichtere Bedienbarkeit und eine bedeutend bessere Stabilität als bei bisherigen Betriebssystemen. Im Frühjahr 1991 entwickelte sich aus den Planungen ein konkretes Projekt zur Generierung eines Prototyps für ein solches universales Betriebssystem. Ab August 1991 wurde – hauptsächlich von James Gosling – nach einer geeigneten Programmiersprache dafür gesucht. Allerdings entschieden sich die Green-Entwickler nicht für eine bereits existierende Programmiersprache, denn diese wiesen zu große Schwächen in Hinblick auf die Stabilität auf. Gerade bei Bedienerfehlern – und diese gestand man beim Green-Projekt der potenziellen Zielgruppe, Consumer, im Gegensatz zur gängigen Praxis bei Computeranwendern einfach zu – waren diese Programme einfach zu intolerant. Eine neue, plattformunabhängige und objektorientierte Sprache musste entwickelt werden. Der Name für diese neue Sprache? Nein, noch nicht Java. Oak – zu deutsch Eiche. Warum Oak? Bekannt ist das Gerücht, dass James Gosling einfach kein passender Name einfiel und er beim Brüten über neue Namen permanent auf eine imposante Eiche vor seinem Büro geblickt haben soll. Eine etwas andere Variante verlegt die Eiche in ein an der Wand hängendes Bild. Dieses ist aber alles inoffiziell und sicher nicht so wichtig. Eine seriöse Erklärung für Oak ist, dass es die Abkürzung für »Object Application Kernel« war. Allerdings findet man diesen Begriff in offiziellen Sun-Quellen nicht sofort, was wohl damit zusammenhängt, dass Sun sich nicht so gerne an Oak erinnert (dazu gleich mehr). 1992 präsentierte das Green-Team der Sun-Führung mit Duke, einer kleinen Trickfigur in einem virtuellen Haus, das erste Ergebnis. Und Duke überzeugte. Ein Sun-Tochterunternehmen namens First Person (im Prinzip das Green-Projekt, aber als unabhängige Firma) wurde gegründet, um das Projekt weiter zu entwickeln und der Öffentlichkeit sowie der Elektronik- und Unterhaltungsindustrie bekannt zu machen. Die Zeit war allerdings noch nicht reif für die neue Technik, die ersten Kontakte verliefen im Sand und First Person verzettelte sich zusätzlich in viele Kleinexperimente. 1994 verschwanden Oak und First Person wieder in der Versenkung und das GreenTeam kehrte zurück zu Sun. Dann aber bewahrte ein anderes Ereignis Oak vor dem völligen Vergessen – der legendäre Mosaic-Browser. Dieser hatte sich mittlerweile als eine feste Grö ß e im Internet etabliert und mit seinen Möglichkeiten wurde plötzlich das heterogene Internet zu einer möglichen Zielplattform für Oak. William Joy, einem Mitbegründer von Sun, ist es zu verdanken, dass Oak Ende 1994 für das Internet umgearbeitet wurde und zudem entsprechend dem gerade vorexerzierten Netscape-Geschäftsmodell über das Netz frei und umsonst verteilt wurde. Die geniale Theorie hinter diesem besagten Netscape-Geschäftsmodell heißt, Marktanteile ohne Gewinn zu erobern, um dann einen Standard festlegen zu können. Kassiert wird danach. 1995 war es soweit – Oak war zum großen Auftritt im Internet bereit. Allerdings musste aus zwei Gründen ein neuer Name gefunden werden. Marketinggründe waren der eine. Oak war ob der gescheiterten
74
Java 2 Kompendium
Die Geschichte von Java
Kapitel 2
Experimente zu negativ belastet. Es gab gleichfalls juristische Schwierigkeiten, denn der Name Oak war einem anderen Produkt zu ähnlich. Und wieder war die Namensgebung eine schwierige Geburt. Man konnte sich nicht auf einen Namen einigen. Dem Gerücht nach wurde der Name dann außerhalb des eigentlichen Brainstormings in der Cafeteria gefunden. JAVA! Der Name Java ist in Amerika – wie inzwischen wohl allgemein bekannt – eine Bezeichnung (eigentlich altenglisch) für das wichtigste Grundnahrungsmittel von Programmierern: Kaffee, heißen, sehr heißen Kaffee (und ist natürlich ebenfalls eine Insel in Indonesien).
2.2.1
Erstes Java-Auftreten, HotJava und das JDK 1.0
Im März 1995 präsentierte Sun Java und das zugehörige Paket von Entwicklungs-Tools (das JDK) der breiten Internet-Öffentlichkeit. Java schlug dort bekanntlich wie eine Bombe ein. In einem Atemzug mit Java wird bei diesem Datum oft der Begriff HotJava genannt. Erst die Kombination mit HotJava verschaffte Java die gebührende Aufmerksamkeit. HotJava war die erste komplexe und vollständig in Java geschriebene Anwendung und naheliegenderweise der erste Java-fähige Browser. Und damit die Präsentationsplattform für die ersten Java-Applets. Zudem war er eine wesentliche Ergänzung der ersten Java-Entwicklungstools von Sun – dem Java Development Kit 1.0 oder kurz JDK 1.0 (HotJava gehörte und gehört immer noch nicht zu dem JDK). Dieses Development Kit soll in der neuesten Version2 natürlich noch ausführliches Thema dieses Buchs sein. Kurz nach Präsentation des JDK 1.0 wurde von der Sun-Tochter Sunsoft mit dem Java-Workshop ein kommerzielles Entwicklungspaket nachgeschoben. Dieser war wie der HotJava-Browser vollständig in Java geschrieben und damit plattformunabhängig. Außerdem bot der Java-Workshop gegenüber dem frei verfügbaren Java Developement Kit statt einer kommandozeilenorientierten Shell, rudimentären Test- und Debug-Möglichkeiten sowie einem Referenzcompiler bereits eine integrierte Entwicklungsumgebung mit Editor, Browser, Project-, Portfolio- und Build-Manager, Debugger, ProjectTester und Online-Hilfe. Andere Hersteller sollten schnell folgen und heute gibt es eine Vielzahl von integrierten Java-Entwicklungsumgebungen. Alle basieren jedoch auf dem JDK. Meist direkt, indem sie die Tools des JDK einfach aufrufen, oder indirekt, indem sie die Funktionalitäten nachbilden. Natürlich gab es im ersten JDK diverse kleinere Kinderkrankheiten. Einige betrafen die Sicherheit, andere fehlende Funktionalitäten. 2
Und auch in älteren Versionen, da es für deren Verwendung immer noch Argumente gibt.
Java 2 Kompendium
75
Kapitel 2
Schnuppertour Java
Abbildung 2.4: Der 1. Java-Workshop von Sunsoft
Dies ist für ein vollkommen neues Produkt verständlich (und leider in der Softwarebranche üblich, wie die permanenten Schnellschüsse Windows oder die verschiedenen Office-Pakete sehr drastisch zeigen) und dürfen auf keinen Fall als Kritikpunkte an Java missbraucht werden. 1997 folgte deshalb nach einigen kleinen Zwischenversionen das erste bedeutende Update mit der Version 1.1 des JDK, der diverse kleinere Verbesserungen folgen sollten. Neben den für Updates üblichen Fehlerbereinigungen enthielten die Versionen 1.1.x einige entscheidende Neuerungen. Diese machten eine ganze Reihe von neuen Tools für das Java-SDK (Software Development Kit) nötig. Bestehende Tools wurde vielfach überarbeitet und sowohl im Layout als auch im Funktionsumfang verändert. Bereits Ende 1997 gab es dann die ersten Betaversionen zum JDK 1.2 und Java 1.2, wie nach den damaligen Veröffentlichungen die komplette Plattform heißen sollte. Das Final wurde für das erste, spätestens aber das zweite Quartal 1998 angekündigt. Daraus wurde jedoch nichts. Die Einführung von Java 1.2 und JDK 1.2 wurde immer wieder verschoben. Insgesamt vier Betaversionen fanden den Weg in die Öffentlichkeit. Diese erwiesen sich als recht stabil und allgemein wurde fast täglich die Freigabe der Finalversion erwartet. Aber erst im Dezember 1998 ließ Sun gleich zweimal eine Bombe platzen. Am 4. Dezember 1998 hatte Sun endlich die Finalversion des 76
Java 2 Kompendium
Die Geschichte von Java
Kapitel 2
JDK 1.2 freigegeben. Pikanterweise erfolgte dies unmittelbar, nachdem im Rahmen des Rechtsstreits mit Microsoft um Java die Redmonder eine erneute Niederlage hinnehmen mussten. Ein Schelm, wer vermutet, Sun nutzte die Aufmerksamkeit, um die Beachtung der neuen Java-Plattform zu erhöhen. Die zweite Bombe explodierte kurz danach auf der Java Business Expo. Nicht nur ein neues JDK, sondern ein vollständiges Plattform-Update unter dem Namen Java 2.0 wurde dort offenbart. Entgegen der allgemeinen Erwartung wurde das vollständige Update nicht als Version 1.2 in Umlauf gebracht. Mitte 2000 erschien dann das JDK 1.3, das das JDK 1.2 im Rahmen der Java-2-Plattform ablöste. Die gesamte Plattform wird aber immer noch Java 2 genannt.
2.2.2
Was macht Java so einzigartig?
Im Gegensatz zu HTML ist Java das Produkt einer Organisation, nicht eines Konsortiums von unterschiedlichsten Interessengruppen. Zudem ist Java vollkommen neu entwickelt worden und muss sich nicht mit Altlasten rumplagen, wie es beispielsweise C++ tun muss. Statt sich immer auf den kleinsten Nenner einigen zu müssen, konnten relativ leicht innovative Ideen und Denkansätze verfolgt und realisiert werden. Dies ist sicher ein Baustein für Erfolg und Leistungsfähigkeit von Java. Ein weiterer Baustein ist das Umfeld, in dem Java das erste Mal präsentiert wurde. Beim Auftreten von Java gab es einige Merkmale für den einschlagenden Triumph. Dabei waren es für verschiedene Gruppen von Leuten durchaus unterschiedliche Aspekte, die Java zu dem durchschlagenden Erfolg verhalfen. Für die reinen Anwender waren es sicher im Wesentlichen zwei Dinge: grafische, dreidimensionale Animationen und Interaktionsmöglichkeiten von Internet-Anwendern. Das Auftreten von Java und etwas später seinem Skript-Ableger JavaScript kam für Internet-Anwender einer Revolution gleich. Dem WWW (von den zeilen- oder Menü-orientieren Diensten ganz zu schweigen) fehlten, mit dem bis zu diesem Zeitpunkt realisierten Stand von HTML, einige ganz entscheidende Merkmale: eine dreidimensionale Darstellung von Objekten, eine bewegte Animation und die Möglichkeit einer vernünftigen Interaktion mit dem Anwender. Java rannte mit seinen Multimedia- und Interaktionseigenschaften schon lange geöffnete Türen ein. Die ziemlich eingeschränkten Interaktionsmöglichkeiten von WWW-Surfern beruhten bis dahin im Wesentlichen auf so genannten Hotspots, sensitiven Elementen auf HTML-Seiten, die beim Anklicken eine Aktion auslösten. Bei der Mausaktion »Klick« muss bei Hotspots die Cursorposition ausgewertet und zum Server zurückgeschickt werden (wie auch immer technisch realisiert). Aber auch eine Tastatureingabe des Anwenders auf einer Java 2 Kompendium
77
Kapitel 2
Schnuppertour Java Webseite musste zum Server übermittelt werden. Auf dem Server wurde die Eingabe verarbeitet und eine neue HTML-Seite zurück zum Client geschickt. Dieser Mechanismus wird CGI (Common Gateway Interface) genannt. Die grö ß te Arbeitslast liegt bei den Servern und den Leitungen des Internets. Der Client steht relativ ungenutzt herum und wartet (meist sehr, sehr lange). Der Ansatz von Java für die Optimierung dieser Vorgänge lag darin, dem Prozessor des Clients einen Teil der Arbeit zu übertragen. Denn obwohl die Rechner der Internet-Anwender immer leistungsfähiger wurden, lagen sie für die Internet-Arbeit normalerweise ziemlich brach. Der Client wurde zum dummen Terminal aus grauer Großrechner-Urzeit degradiert. Es war eigentlich absolut unlogisch, einen Hochleistungs-PC oder einen vergleichbaren Rechner als Client zu verwenden und ihn mit Aufgaben zu betrauen, die ein ZX81 (Kultrechner Anfang bis Mitte der 80er-Jahre mit Folientastatur und 1-16 KByte Hauptspeicher) zur Not noch zu Wege gebracht hätte. JavaApplets sorgten also mit einer Arbeitsverlagerung auf den Client für Aufsehen. Das zweite Java-Highlight für die Anwender – die neuen Darstellungsmöglichkeiten – sorgte zum ersten Mal für echtes Multimedia im Internet. Als Java der Öffentlichkeit präsentiert wurde, fanden Anwender bis dahin beim Surfen nur passive Seiten (zudem noch zweidimensional) vor, die weitgehend in HTML 1.0 oder 2.0 geschrieben waren. Selbst wenn es Texte mit Hyperlinks waren und recht komfortabel Effekte wie Grafiken oder Sounds eingebunden werden konnten, die Einschränkung »Text« blieb. Insbesondere die dreidimensionale Darstellung von Objekten war damit nicht zu realisieren. Genauso wenig eine bewegte Animation. Mit Java änderte sich die Situation schlagartig, die dritte Dimension hielt bewegend Einzug ins Netz. Für die EDV-Spezialisten gab es neben diesen beiden offensichtlichen Knallern jedoch noch andere Gründe. Ein oft genannter Grund ist, dass Java ohne Mitwirkung des »Reichs des Bösen« (liebevoller Kosename für Microsoft – zumindest von allen Nicht-Microsoft-Abhängigen) entstanden ist. Da gab es etwas Neues, Revolutionäres, Innovatives und Bill Gates war nicht dabei. Nicht nur das, Microsoft schätzte als einziges wichtiges EDV-Unternehmen die Internetentwicklung zu dieser Zeit vollkommen falsch ein und ignorierte die ungeheuren Zukunftsperspektiven. Eine in der Computerwelt zu diesem Zeitpunkt einmalige Chance für andere/neue Unternehmen, EDVEntwicklung zu gestalten, ohne von Microsoft die Richtung angezeigt zu bekommen. Firmen wie Sun oder Netscape nutzten die Gunst der Stunde. Bald aber hatte Microsoft seine erste Fehleinschätzung revidiert und sich mit Vehemenz in Entwicklungsprojekte rund um das Internet gestürzt. Allerdings schien es lange so, als ob sich Microsoft bei Java ziemlich kooperativ verhalten wollte. Die Partnerschaft mit Apple bzgl. der JVM- und JRE-
78
Java 2 Kompendium
Die Geschichte von Java
Kapitel 2
Entwicklung (JRE – Java Runtime Environment) signalisierten Kooperationsbereitschaft mit anderen Unternehmen. Diverse Aktionen von Microsoft in der jüngeren Vergangenheit verstärkten jedoch wieder die Befürchtungen der Anti-MS-Gemeinde, Bill Gates wolle doch Java und das Internet umarmen und verschlingen. Dazu zählt beispielsweise die Weigerung von Microsoft, die Java Foundation Classes, die Klassenbibliothek zur Erstellung grafischer Oberflächen, als Bestandteil der Sprache Java anzusehen. Damit wähnt sich Microsoft natürlich frei von etwaigen Lizenzbestimmungen, die Microsoft dazu verpflichten würden, die JFC mit jeder Java-VM auszuliefern – und damit in den Internet Explorer und Windows zu integrieren. Microsoft entwickelte statt dessen zwei Gegenentwürfe: Die eigenen AWTKlassen und J/Direct (Teil der Direct-Technologie von Microsoft), das es Java-Programmen erlaubt, Windows-Routinen zu nutzen. Beides natürlich plattformabhängig an Windows gebunden. Dies und diverse andere Aktionen führten zu mehreren Rechtsstreitigkeiten zwischen Sun und Microsoft, wobei Sun die meisten gewonnen hat. Insbesondere hat Sun erreicht, dass bestimmte Microsoft-Produkte das Java-Logo nicht führen dürfen, wenn sie nicht den Sun-Vorgaben entsprechen. Aber zurück zu den Erfolgsfaktoren von Java: Die Java-Eigenschaften Objektorientiertheit und Plattformunabhängigkeit waren die weiteren und wohl wichtigsten Gründe für den Erfolg. Und last but not least – die extreme Stabilität von Java.
2.2.3
Die Herkunft von Java
Java hat – wie jedes gute Kind – offiziell zwei Elternteile. Die Syntax ist im Wesentlichen eine an C/C++ angelehnte Programmiersprache, die Konzeption und die Objektorientiertheit stammen eher von dem anderen Elternteil – Small Talk. Als »Trauzeugen« werden ab und zu noch Eiffel und Objective-C genannt. Warum aber ist Java so erfolgreich? Eigentlich war es ein einfaches Rezept: Es wurden die Stärken der Vorfahren genommen, die Schwächen ausgemerzt und dann fehlende, sinnvolle Innovationen hinzugefügt. Zwar war einer der Java-Ahnen sowieso objektorientiert (Small Talk), jedoch kaum verbreitet. Dies liegt wohl in der vollständigen Andersartigkeit von Small Talk (gegenüber anderen Programmiersprachen wie C, PASCAL, Basic, COBOL oder FORTRAN). Small Talk ist zwar sehr leicht zu erlernen, jedoch einfach nicht mit gewohnten Befehlsstrukturen vergleichbar. Zumindest aus damaliger Sicht. Java macht nicht den Fehler von Small Talk und vermeidet ein gänzlich neues Befehlskonzept, sondern definiert sich von der Syntax eigentlich als eine Art bessere Untermenge von C++. Der Umstieg von C/C++ auf Java stellt also für die meisten Entwickler keinen großen Aufwand dar.
Java 2 Kompendium
79
Kapitel 2
Schnuppertour Java Von dem anderen Elternteil C/C++ hat sich Java zwar die Syntax geliehen, aber diverser C/C++-Altlasten entledigt und ist erheblich einfacher geworden, ohne viel an Leistungsfähigkeit gegenüber C/C++ zu verlieren. Dies betrifft einmal die Objektorientierung. Obwohl man mit C/C++ objektorientiert programmieren kann, hatte die überwiegende Mehrzahl der Programmierer C/C++ nie so eingesetzt. Die Möglichkeit des prozeduralen (altbekannten) Programmierens untergräbt bei C/C++ den strengen objektorientierten Gedanken. Java lässt einem Programmierer diese Wahl nicht. Man kann nur objektorientiert programmieren. Aber im Gegensatz zu C++ wurde keine Mehrfachvererbung realisiert, was Java-Programme viel besser wartbar macht. Ein weiterer Vorteil von Java gegenüber C/C++ ist, dass die JavaSyntax weniger kompliziert ist. Dies betrifft im Wesentlichen ziemlich üble C/C++-Möglichkeiten wie Zeiger, Operator-Overloading, manuelle Speicherverwaltung (d.h. das Speichermanagement, also das Beschaffen und das Freigeben von Speicher durch den Programmierer), automatische Konvertierung von Datentypen, Headerdateien, Pre-Prozessoren, Strukturen, VariantDatentypen und multidimensionale Arrays. Auf die genauen Unterschiede soll an einer anderen Stelle im Buch eingegangen werden. Insbesondere sollte Java nach Erwartung der Java-Väter (und Mütter) einige der wichtigsten Probleme moderner Programmierung lösen. Kernprinzipien von Java sollten die Eigenschaften kompakt, zuverlässig, portierbar, dezentral, echtzeitfähig und integriert sein. Die offizielle Definition von Sun Microsystems zu Java lautet folgendermaßen: Java: eine einfache, objektorientierte, dezentrale, interpretierte, stabil laufende, sichere, architekturneutrale, portierbare und dynamische Sprache, die Hochgeschwindigkeits-Anwendungen und Multithreading unterstützt. Im Einzelnen bedeutet dies: Java ist einfach, obwohl sehr nahe an der (ziemlich komplizierten) C/C++-Syntax entworfen wurde. Dadurch soll Java für C/C++-Progammierer schon auf den ersten Blick vertraut und verständlich sein und damit die Einarbeitungszeit kurz halten. Dass Java einfach zu erlernen ist (wie Sun behauptet), dem werden jedoch vor allem Programmieranfänger wohl trotzdem kaum zustimmen. Dazu ist Java auch zu mächtig. Aber da auf viele C/C++-Spezialitäten verzichtet wurde, hat Java unter der Prämisse »Weniger ist mehr« erheblich gewonnen. Hinzugefügt wurden dafür selektive und bisher nicht in C/C++ implementierte Funktionalitäten, die die Entwicklung, Implementation und Instandhaltung der Software erleichtern sollen. Obwohl beispielsweise OperatorenÜberladung weggelassen wurde, wurde das Überladen von Methoden beibehalten. Oder für das Speichermanagement, eine der Hauptfehlerquellen bei C/C++-Programmen, verfügt Java über eine automatische Garbage Collection (automatische Speicherbereinigung). Da Java über
80
Java 2 Kompendium
Die Geschichte von Java
Kapitel 2
diesen automatischen Garbage Collection-Mechanismus verfügt, vereinfacht es nicht nur die Programmierung, sondern verringert daneben die Anzahl der Fehler und beseitigt das alte C/C++-Problem des manuellen Speichermanagements. Java ist klein, was unter anderem ein angenehmer Nebeneffekt der Einfachheit ist. Eines der ursprünglichen Ziele von Java war, die Entwicklung von Software zu erleichtern, die »stand alone« auf kleinen Rechnern (ab mindestens 4 MByte RAM) oder sogar in Kaffeemaschinen oder Videorecordern läuft. Die Grö ß e des Basisinterpreters und die Klassenunterstützung betragen in etwa 40 KByte RAM. Zusätzliche Standardbibliotheken und Thread-Unterstützung benötigen weitere 175 KByte. Diese 215 KByte sind wesentlich kleiner als jede andere vergleichbare Programmiersprache oder -umgebung. Java ist objektorientiert. Es zählt zu einer Familie von Sprachen, die Daten als Objekte definieren und Methoden verwenden, um diese Objekte zu bearbeiten. Einfach gesagt, beschreiben objektorientierte Sprachen (OO ist die Abkürzung für Object Orientation) Interaktionen zwischen Datenobjekten. Allerdings hat Java gegenüber einigen anderen objektorientieren Sprachen eine entscheidende Einschränkung – es gibt keine Mehrfachvererbung. Dafür werden jedoch abstrakte Klassen und ein Schnittstellenkonzept unterstützt. Damit ist es möglich, bedeutend transparenter die Möglichkeiten der Mehrfachvererbung zu kompensieren. Damit werden einige der zentralen Probleme umgangen, die die tatsächliche Mehrfachvererbung aufwirft, wohingegen die meisten der Vorteile bewahrt werden. Mehr dazu später. Java ist dezentral, denn Java erfüllt ein wesentliches Charakteristikum von Client/Server-Anwendungen: die Fähigkeit, Informationen und die Last für die Berechnung der Daten zu verteilen. Der Begriff »dezentral« beschreibt dabei die Beziehung zwischen Systemobjekten, gleichgültig, ob sich diese Objekte nun auf lokalen oder auf entfernten Systemen befinden. Einer der großen Vorteile von Java-Applets und -Anwendungen ist, dass sie Objekte über URLs im gesamten Web genauso wie auf dem lokalen Rechner öffnen und auf diese zugreifen können. Dabei können bereits wichtige Teile der Anwendung bzw. der Daten lokal vorhanden sein, andere werden hingegen erst bei Bedarf geladen. Der schon beschriebene Mangel bei anderen Internetsystemen bzw. -sprachen wie HTML (der Client ist im Prinzip zur Arbeit bereitet, hat aber nichts zu tun und Server und Netzleitungen schaffen sich fast tot) wird umgangen. Dabei steht dem Java-Programmierer eine implementierte, umfangreiche Programm-Routinen-Bibliothek für die Zusammenarbeit mit TCP/IP-Diensten wie HTTP und FTP zur Verfügung. Das neue RMI-Konzept ist ein weiterer Schritt in diese Richtung.
Java 2 Kompendium
81
Kapitel 2
Schnuppertour Java Java ist interpretiert, denn ein gewisser Teil des Java-Codes (zwar nur ca. 20 % – das sind jedoch die kritischen 20 %) werden vom Container, z.B. dem Browser, interpretiert. Manchmal sagt man deshalb sogar, dass Java interpretiert und kompiliert zur gleichen Zeit ist, was auf den ersten Blick ja ein Widerspruch zu sein scheint. Sowohl die wesentlichen Aspekte der Java-Sicherheit, als auch die Fähigkeit, auf verschiedenen Systemen zu laufen, rühren von der Tatsache her, dass die letzten Schritte der Kompilierung lokal abgearbeitet werden. Vorher wurde der Java-Quellcode mit dem Java-Compiler in Bytecode kompiliert. Bei dem Bytecode handelt es sich um ein architekturneutrales Object-Codeformat. Ferner ist er binär und so lange nicht vollständig und lauffähig, bis er von der Java-Laufzeitumgebung interpretiert wird. Da jede Java-Laufzeitumgebung plattformspezifisch ist, arbeitet das endgültige ausgeführte Programm auf dieser spezifischen Plattform. Diese Kombination von Kompilierung und Interpretation ist vorteilhaft, da zunächst einmal Sicherheit und Stabilität erhöht werden. Die Java-Umgebung enthält ein Element namens »Linker«, das die in ihr System eingehenden Daten überprüft, um sicherzustellen, dass sie weder schädigende Daten enthalten (Sicherheit) noch Daten, die den Systembetrieb ihres Computers unterbrechen könnten (Stabilität). Außerdem wird die Pflege von Versionsnummern erleichtert. Die Tatsache, dass der letzte Teil der Übersetzung des Bytecodes von einem plattformspezifischen Programm auf der Plattform des Endanwenders ausgeführt wird, nimmt dem Entwickler die Verantwortung, verschiedene Quellen für verschiedene Plattformen halten zu müssen. Die Interpretation erlaubt zudem, Daten zur Laufzeit zu laden, was die Grundlage für das dynamische Verhalten von Java ist. Java ist stabil in der Bedeutung von »zuverlässig«. Je stabiler eine Sprache ist, desto unwahrscheinlicher ist es, dass in dieser Sprache geschriebene Programme abstürzen. Ein wesentliches Kriterium für die Stabilität einer Programmiersprache ist, dass bereits während der Kompilierungsphase der grö ß te Teil der Datentyp-Überprüfung ausgeführt wird, nicht erst zur Laufzeit wie bei nicht so stabilen Sprachen. Man nennt dies »stark typisiert«. Eine stark typisierte Sprache wie Java ermöglicht also bereits ein intensives Überprüfen des Codes während der Kompilierungsphase. Damit können Fehler relativ früh gefunden werden. Ein weiteres Stabilitätskriterium von Java-Programmen ist, dass sie – im Gegensatz zu Programmen, die in vielen anderen Sprachen geschrieben sind – keinen Zugriff auf den vollständigen Speicherbereich eines Computers, insbesondere den Systemspeicher, haben. Java besitzt eine eingebaute Begrenzung der Zugriffsmöglichkeiten. Damit verringert sich die Absturzwahrscheinlichkeit eines Java-Programms erheblich. Schlimmstes Negativbeispiel für eine Programmiersprache, die den umgekehrten Weg verfolgt und Programmieren weitgehend ungeprüfte
82
Java 2 Kompendium
Die Geschichte von Java
Kapitel 2
Zugriffe auf sämtliche Speicherbereiche des Rechners ermöglicht, ist C/ C++. Die Stichworte Zeigerarithmetik und implizite Deklarationen sind mit höchster Gefahr gleichzusetzen. Bei C/C++ liegt eindeutig der Schwerpunkt auf maximaler Geschwindigkeit, plattformnaher Programmierung und Flexibilität, bei Java auf Stabilität und Sicherheit. Ein weiterer Stabilitätsaspekt von Java ist die abschließende Sicherheitsüberprüfung durch einen Linker. Der Linker ist Teil der Laufzeitumgebung. Er versteht das Typensystem und wiederholt während der Laufzeit viele der Typenüberprüfungen, die der Compiler durchführt. Java gilt als sehr sicher. So ist die Unterbindung von beliebigen Speicherzugriffe durch Java nicht nur ein Stabilitätskriterium, sondern trägt gleichfalls zur Sicherheit bei. Da Java-Programme zuerst in BytecodeAnweisungen und Proto-Programme übersetzt werden, lassen diese sich dann recht gut überprüfen. Bytecode-Anweisungen sind nicht plattformspezifisch und enthalten zusätzliche Typinformationen. Diese Typinformation kann für die Überprüfung des legalen Status und von möglichen Sicherheitsverletzungen verwendet werden. Mehr zur Sicherheit folgt noch an anderer Stelle. Java ist architekturneutral, d.h., es ist auf verschiedenen Systemen mit unterschiedlichen Prozessoren und Betriebssystemarchitekturen lauffähig. Der kompilierte Java-Bytecode kann auf jedem Prozessor ausgeführt werden, der einen Java-fähigen Browser bzw. die virtuelle Maschine von Java im Allgemeinen unterstützt. Der Java-Compiler erzeugt niemals plattformabhängigen Binärcode, sondern neutralen Java-Bytecode. Dieser wird erst während der Laufzeit in systemeigenen Maschinencode übersetzt. Und dennoch ist Java eine vollständige Programmiersprache. Java ist portierbar, was eine wesentliche Folge der Architekturunabhängigkeit ist. Darüber hinaus fallen implementationsabhängige Aspekte, wie man sie in C und C++ findet, bei Java durch die Standards für Datentypen weg. In Java wird die Grö ß e einfacher Datentypen genau spezifiziert, und auch, wie sich die Arithmetik gegenüber diesen Datentypen verhält. Fast alle wichtigen Prozessoren unterstützen diese Java-Spezifikation und außerdem beinhalten die Java-Bibliotheken portierbare Schnittstellen für die wichtigsten Plattformen. Java ist sehr leistungsfähig, denn in Tests von Sun auf einer Sparc Station 10 hat sich gezeigt, dass die Performance von Java-Bytecode, der in Maschinencode umgewandelt wurde, von native C oder C++ bei vielen Funktionen nicht zu unterscheiden ist. Allerdings ist dabei die Zeit für die Laufzeit-Kompilierung nicht mit einbezogen. Der Start der virtuellen Maschine beim Aufruf einer Java-Applikation ist zudem zeitaufwändig. Bei allem Java-Lob muss man in dem Punkt Performance realistisch bleiben. Nicht umsonst zählt die absolut mangelhafte Performance früher Java-Versionen zu den Hauptkritikpunkten. Die Java-2-Plattform
Java 2 Kompendium
83
Kapitel 2
Schnuppertour Java beinhaltet diverse Neuerungen zur Steigerung der Performance (wir sind im ersten Kapitel darauf eingegangen). Die Geschwindigkeit von interpretiertem Java-Bytecode ist dennoch auf leistungsschwachen Plattformen recht niedrig, aber für die meisten Aufgaben ausreichend. Und für den Fall, dass eine höhere Performance notwendig ist, kann native Code integriert werden (wovon jedoch aus Sicherheitsgründen dringend abzuraten ist). Ein Ansatz zur Steigerung der Performance ist die Entwicklung von Just-in-Time-Compilern (JIT) durch diverse Hersteller von Java-Entwicklungsumgebungen. Insbesondere gehört in der Java-2Plattform ein JIT-Compiler zum Lieferumfang. Nach Angaben einiger Hersteller von Entwicklungstools kann die Leistungsfähigkeit von JavaApplikationen und Applets um das Fünf- bis Zehnfache erhöht werden – unabhängig davon, mit welchem Tool sie erstellt wurden. Ein JIT (Just-in-Time-Compiler) hat grob gesagt die Funktion, ein Java-Applet oder – Programm vor seiner Ausführung bereits zu übersetzen, um damit eine bessere Performance zu erreichen. Genauer genommen übersetzt der JIT nur häufig benötigte Funktionalitäten, d.h., beim ersten Aufruf einer Methode wird deren Bytecode in Maschinenbefehle übersetzt und im RAM gehalten. Beim erneuten Aufruf dieser Methode wird dann der bereits kompilierte Code verwendet. Zudem steigt durch die »Just-in-Time«-Funktionalität die Geschwindigkeit bei der parallelen Abwicklung mehrerer rechenintensiver Softwareapplikationen. Ein JITCompiler ist aber kein Allheilmittel, denn in der Praxis zeigt sich unter ungünstigen Umständen, dass durch Laden des JIT sogar eine Verringerung der Ausführungsgeschwindigkeit die Folge sein kann. In der Regel ist jedoch eine Steigerung der Performance wirklich oft zu beobachten. Die im JDK 1.3 eingeführte Hotspot-Technologie ist ein neuer Ansatz, die Leistungsfähigkeit von Java erheblich zu steigern. Java unterstützt Multithreading. Multithreading bedeutet zunächst nur, dass mehrere Aufgaben oder Prozesse quasi gleichzeitig ausgeführt werden können. Einfachstes (und bestes) Beispiel für ein Multithreadingsystem ist ein Mensch, der viele Dinge gleichzeitig erledigt. Bei Computersystemen werden solch natürliche Dinge wie Multithreading zu einem großen Problem. Viele ältere Betriebssysteme wie DOS waren nie in der Lage, Multithreading auch nur ansatzweise auszuführen. Nicht einmal Multitasking (das parallele Abarbeiten von mehreren Programmen) war bei diesen Betriebssystemen möglich. Auch das Multitasking von Windows 3.x war nie echtes Multitasking, geschweige denn Multithreading. Neben den Betriebssystemen unterstützten zudem die Konzepte bisheriger Programmiersprachen den Multithreading-Vorgang gar nicht oder nur sehr eingeschränkt. C/C++ ist ebenfalls auf Single-Threaded-Programme ausgerichtet. Bei Java ist die Beschränkung auf Single-Threading aufgehoben. Allerdings gilt vor übereilter Euphonie über Multithreading, dass die Vorteile von Multithreading (bessere interaktive Antwortfähigkeit, besseres Laufzeitver-
84
Java 2 Kompendium
Die Geschichte von Java
Kapitel 2
halten) stark von der zugrunde liegenden Plattform abhängen. Selbst wenn eine Plattform Multithreading unterstützt, Java-MultithreadingAnwendungen sind hauptsächlich für eine Multiprozessor-Umgebung geeignet und haben eigentlich nur dort ein optimales Laufzeitverhalten. Multithreading-Verhalten wird zwar funktionieren, wenn Sie eine JavaMultiprozessor-Anwendung unter Windows 98 auf einem PC laufen lassen, jedoch kaum gute Ergebnisse bieten. Im Prinzip bedeutet Multithreading ja nichts anderes, als dass mehrere Aufgaben gleichzeitig ausgeführt werden können. Bei mehreren Prozessoren kann jeder Prozessor einen Thread abarbeiten, was echte Gleichzeitigkeit darstellt. Was bei einem Prozessor Gleichzeitigkeit bedeutet, kann auf philosophischer Ebene bis zum Exzess diskutiert werden, jedoch ist dies durch die kurzen Intervalle der Zeitzuweisungen an einzelne Threads im Grunde mü ß ig. Die Einschränkungen auf Grund der Zyklen von Kapazitätszuweisungen sind aber offensichtlich. Der Vorgang des Multithreading sollte freilich noch einmal etwas genauer beleuchtet werden. Eigentlich ist die oft verwendete Übersetzung von Threads mit Aufgaben ungenau und verschleiert den Unterschied zu Multitasking, was ja streng genommen bedeutet, dass mehrere Aufgaben (Tasks) gleichzeitig ausgeführt werden können. Ein Thread ist im Grunde statt mit »Aufgabe« besser (wie es im Wörterbuch steht) mit »Faden«, »Faser« oder am besten »Zusammenhang« zu übersetzen. Nicht die gleichzeitige Ausführung von mehreren Programmen wie beim Multitasking, sondern die gleichzeitige, parallele Ausführung von mehreren einzelnen Programmschritten (oder zusammenhängenden Prozessen) ist echtes Multithreading. Dies kann auch bedeuten, dass innerhalb eines Programmes mehrere Dinge gleichzeitig geschehen, mehrere Fäden/Fasern eines Programms gleichzeitig verfolgt und abgearbeitet werden. Beispielsweise kann ein Thread eines Programms eine lange und hochkomplizierte Berechnung ausführen, während sich ein anderer Thread um die Bildschirmausgabe kümmert und ein dritter Thread die Usereingabe bearbeitet. Und dies im Sinne von »computergleichzeitig«. Bei Java ist das Multithreadingkonzept voll integrierter Bestandteil der Philosophie. Der hochentwickelte Befehlssatz in Java, um Threads zu synchronisieren, ist in die Sprache integriert, macht diese stabil und einfach in der Anwendung. Das Multithreadingkonzept an sich ist freilich schon viel älter als Java und auch das Java-Multithreadingkonzept basiert auf dem Cedar/Mesa-System von Xerox. Die einfachen Thread-Anweisungen von Java beruhen auf dem 20 Jahre alten Paradigma von Steuerund Bedingungsvariablen von C. Anthony Hoare. Allerdings hat Sun mit Java in dem äußerst wichtigen und komplizierten Bereich der Synchronisation von Threads viel Neues entwickelt und viele der Synchronisationsschwierigkeiten bisheriger Multithreading-Umgebungen aus dem Weg geräumt.
Java 2 Kompendium
85
Kapitel 2
Schnuppertour Java Java ist dynamisch, d.h., es kann sich an eine sich ständig weiterentwickelnde Umgebung anpassen. Sun zieht zur Verdeutlichung dieser Eigenschaft von Java das Beispiel C++ heran und definiert den Vorteil von Java gegenüber Entwicklungen mit C++ so, dass Entwickler bei C++ von jemand anderem abhängig werden. Grund dafür sind die Klassenbibliotheken, eine Sammlung von Plug-and-Play-Komponenten, in denen der C++-Code implementiert wird. Diese werden von fremden Unternehmen ständig verändert oder »upgegradet«. Da C++-Programme die Klassenbibliotheken verwenden, muss deshalb oft der C++Code angepasst werden, nur um die Programme lauffähig zu halten. Dummerweise werden die meisten User bei einem Programmfehler nach einem (vielleicht noch unbemerkten, weil bei einer Installation einer anderen Software erfolgten) Upgrade von Klassenbibliotheken den Fehler dem Programm zuschieben und nicht den neuen Klassenbibliotheken. Java verbindet im Gegensatz zu C++ die einzelnen Module in einer späteren Phase und vermeidet dadurch das Bibliotheken-Problem. Ein weiterer dynamischer Aspekt von Java ist der Mechanismus der Schnittstellen (Interfaces). Mehr dazu im Abschnitt über Schnittstellen. Nur soweit vorab die Information, dass Schnittstellen im Prinzip Klassen sehr ähnlich sind, jedoch im Gegensatz dazu Mehrfachvererbung unterstützen und auch sonst flexibler in bezug auf Vererbung sind, als dies bei Klassen der Fall ist. Eine wesentliche Eigenschaft von dynamischen Sprachen wie Java oder deren dynamischen Vorgängern Small Talk oder auch Lisp ist, dass sie sich auf Grund ihrer Flexibilität hervorragend zur Erstellung von Prototypen eigenen. Ein Hauptgrund dafür ist, dass sie in jeder Phase von Programmierern explizite Entscheidungen fordern, damit durch eine schlechte oder nicht erfolgte Entscheidung (etwa wie bei C/C++ ein Zeiger auf einen unbekannten Objekttyp) ein System nicht zum Absturz gebracht werden kann. Wenn Sie beispielsweise in Java einen Methodenaufruf schreiben und dabei Fehler machen, wird dieser beim Kompilieren bemerkt und Sie bekommen eine Warnmeldung, wenn Sie den Code kompilieren wollen.
2.3
Zusammenfassung
Zusammenfassend kann man sagen, dass Java eine der wohl spannendsten Entwicklungen der letzten Jahre in der EDV war und immer noch ist. Nahezu konkurrenzlos für die Bereiche, wo es auf Plattformneutralität und Stabilität ankommt, hat sich Java zu einer festen Grö ß e entwickelt. Java bietet weit mehr als nur die Möglichkeit, im Internet kleine, bunte »Progrämmchen« zu erstellen. Es ist eine der leistungsfähigsten Entwicklungsumgebungen, die man sich vorstellen kann.
86
Java 2 Kompendium
3
Das JDK
Wir wollen in diesem Kapitel zu den Entwicklungstools für Java kommen. Das Java Development Kit (JDK) ist die Sun-Entwicklungsumgebung zum Erstellen von Java-Applikationen, -Applets und -Komponenten. Es ist Kern sämtlicher Java-Entwicklungswerkzeuge (gleichfalls von Fremdherstellern). Das Kapitel ist relativ knapp gehalten und spricht nur die wichtigsten Tools an. Im Anhang gehen wir intensiver auf das JDK und ergänzende Entwicklungstools ein. Das JDK wird in der aktuellen Version 1.3 (die – um es nochmals zu betonen – das aktuelle Entwicklungspaket der Java-2-Plattform ist) von Sun für Windows 95/98/ME/NT (ab der Version 4.0)/2000 sowie deren Nachfolger und das Solaris-Betriebssystem bzw. das in der letzten Zeit immer populärer werdenden Linux frei zur Verfügung gestellt. Genauere Informationen finden Sie unter http://java.sun.com/products/jdk/faq.html. Beachten Sie, dass das JDK 1.3 an diversen Stellen als SDK 2 – Software Development Kit – bezeichnet wird, womit streng genommen aber eine Obermenge des JDK gemeint ist. Für die Windows-Versionen 3.x und früher gibt es keine JDK-Variante, was jedoch schon deswegen klar ist, da dort lange Dateinamen nicht unterstützt werden. Schwierigkeiten beim Erzeugen einer Multithreading-Umgebung in einer Betriebssystemumgebung, die nicht einmal preemptives Multitasking unterstützt, und fehlende direkte TCP/IP-Unterstützung bei Windows 3.x sind weitere Gründe. Allerdings können Windows 3.1x-Anwender seit einiger Zeit zumindest Java-Applets laufen lassen, denn es gibt sowohl von Netscape als auch von Microsoft mittlerweile Java-taugliche Browser für Windows 3.1x. Das JDK ist bezüglich der minimalen Plattformvoraussetzungen genügsam. Nicht nur Java selbst ist klein, auch das JDK ist relativ klein und kompakt. Die Java-Gesamtkonzeption legt auf solche Eigenschaften ja sehr großen Wert. Das Win32-Release läuft sogar schon auf einem einfachen PC mit einem Pentium-Prozessor der ersten Generation mit nur 32 Megabyte recht gut. Wenn es sein muss, sogar bei noch sparsamerer Ausstattung. Das jewei-
Java 2 Kompendium
87
Kapitel 3
Das JDK lige Betriebssystem oder eine auf dem JDK aufbauende Entwicklungsumgebung wird statt dessen die notwendigen Minimalanforderungen für die Hardware festlegen. Das JDK besteht fast ausschließlich aus Befehlszeilen-orientierten Tools und erreicht damit natürlich nicht den Komfortstandard integrierter Entwicklungsumgebungen (IDE), die eine grafische Benutzerumgebung (GUI – Graphical User Interface) haben. Aber Befehlszeilen-Orientierung ist nicht immer schlecht. Man sollte nur daran erinnern, wie viele PC-Profis sogar heute noch lieber mit DOS-Befehlen, als mit den langsamen Stützrädern der Windows-Programme arbeiten. Die JDK-Werkzeuge (den Compiler eingeschlossen) können über eine einfache Befehlszeileneingabe auf Prompt-Ebene aufgerufen werden. Der JavaSource selbst (eine Datei mit Erweiterung .java) kann mit jedem einfachen Texteditor erstellt und bearbeitet werden. Im Anhang werden wir dennoch als Alternativen zu diesem rustikalen – und aus didaktischen Gründen sehr sinnvollen – Arbeiten einige frei verfügbare IDEs vorstellen. Um nun das JDK auf einem lokalen Rechner zu installieren und anzupassen, sollte man in mehreren chronologischen Schritten vorgehen. Am Anfang steht natürlich der Bezug eines möglichst aktuellen JDKs.
3.1
Bezug des JDK
Natürlichste Quelle für ein Java-Entwicklungstool ist wohl das Internet. Immerhin hat dieses erst den Erfolg von Java ermöglicht und wer mit Java programmieren will, hat auch meistens einen funktionierenden Internetzugang. Es gibt nun zahlreiche Quellen, von wo Sie das jeweils aktuelle JDK (aber auch ältere Versionen) beziehen können. Am einfachsten ist der Weg über eine der vielen Seiten des Sun-Imperiums. Der sinnvollste Einstieg erfolgt über den Java-Bereich von Sun (http://java.sun.com). Dort finden Sie alles rund um Java und natürlich auch die neue Java-2-Plattform samt dem zugehörigen JDK 1.3. Wenn Sie diese Java-Seiten aufrufen, folgen Sie einfach den entsprechenden Links für die gewünschte Java/JDK/SDK-Version und Ihrem Betriebssystem. In der Regel müssen einige übliche Copyright- und die Readme-Dateien auf dem Weg dorthin gelesen und bestätigt werden. Sie können die konkreten Seiten für das JDK natürlich auch direkt anwählen. Das erfolgt meist über eine URL wie die folgende: http://java.sun.com/j2se/
88
Java 2 Kompendium
Bezug des JDK
Kapitel 3 Abbildung 3.1: Alles rund um Java direkt von Sun
Abbildung 3.2: Hier gibt es das JDK.
Java 2 Kompendium
89
Kapitel 3
Das JDK Sie können das JDK auch von Seiten laden, die nicht zum offiziellen SunInternetbereich zählen. Etwa von gespiegelten FTP-Servern diverser Organisationen. Gerade die gespiegelten FTP-Server halten aber nicht immer, was diverse Quellen – sogar die offiziellen Sun-Unterlagen – versprechen. Prinzipiell sollte man ob der permanenten Umstrukturierungen auf den Servern bei Fehlermeldungen auf dem Root-Verzeichnis der jeweiligen Organisation einsteigen und dann sein Glück versuchen. An dieser Stelle stehen Ihnen dann u.a. eine Liste der unterstützten Plattformen und die dafür vorhandenen Versionen des JDK zur Verfügung. Sie werden mit detaillierten Anweisungen und Hyperlinks zum Download für Ihre Version und Plattform geführt. Auf der CD finden Sie ein 1.3-JDK. Allerdings kann es sein, dass es seit der Bucherstellung neuere Versionen gibt. Über die angegebenen URLs laden Sie in der Regel ein selbstextrahierendes Archiv auf den lokalen Rechner, sofern es sich um eine ältere Version des JDK handelt. Ab der Version 1.2 (bzw. sogar schon in 1.1.x-Zwischenversionen) steht – zumindest in der Windows-Version – ein Standard-Setup zur Verfügung. Auf den Sun-Downloadseiten stehen verschiedene Möglichkeiten zum Download des doch ziemlich großen JDK-Paketes zur Verfügung. Es gibt sowohl einen FTP-Download als auch einen HTTP-Download. Wenn es Ihnen möglich ist, sollten Sie einen FTP-Download durchführen. Der ist in der Regel schneller als ein HTTP-Download. Zusätzlich müssen Sie das gesamte Paket nicht als eine Datei laden. Es gibt das JDK auch in kleinen Häppchen. Die genauen Grö ß enangaben für das JDK können je nach Release variieren, aber grob sollte die Installationsdatei des JDK 1.3 ca. 29,4 MByte groß sein und mit allem Drum und Dran nach der Installation auf der Festplatte ca. 50 MByte belegen. Da die genauen Grö ß enangaben sich permanent verändern, macht eine genauere Angabe keinen Sinn. In der Regel wird sowieso immer die neueste Variante des JDK geladen und deren Grö ß enangaben können immer wieder variieren. Bei der Kapazität heutiger Datenspeichermedien spielt dies kaum noch eine Rolle, und das JDK ist auf jeden Fall kleiner als übliche Entwicklungsumgebungen.
90
Java 2 Kompendium
Installation des JDK
Kapitel 3 Abbildung 3.3: Eine Installationsdatei des JDK
3.2
Installation des JDK
Die Installation des JDK ist in neueren Versionen kein Problem mehr. Die ersten Versionen waren da nicht so einfach zu handhaben. Es ist jedoch zu empfehlen, ein neues JDK nicht über ein altes Release zu installieren. Wenn Sie eine ältere Version ersetzen wollen, werden als Installationsorte sowieso defaultmäß ig verschiedene Verzeichnisstrukturen vorgeschlagen. Wollen Sie jedoch die bereits vorhandene Verzeichnisstruktur bzw. die bisherigen Namen der Verzeichnisse verwenden (etwa, um diverse Pfade und Einstellungen nicht mehr ändern zu müssen), sollten Sie vor der Installation einer neuen JDK-Version eine gegebenenfalls vorhandene Altversion vollständig beseitigen, damit die beiden Varianten sich nicht in die Quere kommen. Falls Sie vor einer Installation die alte Version beseitigen, sollten Sie natürlich gegebenenfalls vorhandenen eigenen Java-Source und sonstige selbst erstellten Dokumente in dem Verzeichnis in Sicherheit bringen, bevor Sie das alte Verzeichnis liquidieren. Die genauen Schritte bei der Installation sind für die unterschiedlichen Betriebssysteme leicht verschieden, entsprechen aber den üblichen Schrittfolgen bei Installationen unter den jeweiligen Plattformen. Die genauen Installationshinweise für jedes Release werden auf Java-Webseiten unter der zu jedem Release gehörenden Verzeichnisstruktur zur Verfügung gestellt. Wir werden als Beispiel die Installation unter dem Betriebssystem Windows durchsprechen. Ab der Version 1.1.x verwendet das JDK den Standardvorgang zum Installieren unter Windows, den InstallShield. Positiv zu erwähnen ist dabei, dass selbst ein Aufruf des Installationsprogrammes auf Befehlzeilenebene keine sonst übliche Fehlermeldung der Art »This program requires Windows« erzeugt, sondern direkt zum InstallShield übergeht. Der InstallShield bietet alle bekannten Einstellmöglichkeiten in Bezug auf das Installations-Verzeichnis und zu installierende Komponenten. Außerdem wird das Ziellaufwerk überprüft.
Java 2 Kompendium
91
Kapitel 3
Das JDK
Abbildung 3.4: Der Beginn des Installationsvorgangs ist WindowsAnwendern bekannt
Abbildung 3.5: Standardeinstellungsmöglichkeiten
Ziemlich störend ab der Version 1.2 sind die zahlreichen Stellen, wo Sie Lizenzbedingungen akzeptieren müssen. Wenn man die zusätzlichen Bestätigungen der Lizenzbedingungen vor dem Download dazu zählt könnte man auf die Idee kommen, Sun würde einen Augapfel opfern. Das Defaultverzeichnis setzt sich aus der Laufwerksangabe JDK und der Versionsnummer, durch Punkte getrennt, zusammen, zum Beispiel C:\JDK1.1.1 oder C:\JDK1.3. Dies erleichtert eine parallele Führung von mehreren Versionen erheblich.
92
Java 2 Kompendium
Installation des JDK
Kapitel 3
Der Setup-Wizard installiert neben dem JDK noch zusätzlich eine JavaLaufzeitumgebung in ein separates Verzeichnis. Dies ist etwas ärgerlich, weil Sie diese zweite Laufzeitumgebung nicht benötigen – das JDK enthält sowieso eine solche.
3.2.1
classes.zip, src.zip, src.jar, rt.jar & Co.
Zwischen dem JDK 1.1 und der Finalversion 1.2 (bzw. natürlich auch dem Wechsel von JDK 1.2 auf JDK 1.3, aber diese sind nicht ganz so massiv) haben sich zahlreiche Veränderungen ergeben, die die interne Arbeitsweise der JDK-Tools und die Voraussetzungen für deren Aufruf betreffen. Hier soll ein wichtiges Detail hervorgehoben werden – die Dateien Classes.zip und Src.zip sowie die Laufzeitumgebung von Java. Bis zu der JDK-Version 1.1.7 (und sogar den meisten Betaversionen des JDK 1.2) erzeugte das Extrahieren des JDK-Archives beim Installieren normalerweise (u.a.) zwei interessante Dateien bzw. Verzeichnisse: Src.zip im Java-Verzeichnis selbst bzw. das Verzeichnis src und Classes.zip in dessen Unterverzeichnis lib.
Beide ZIP-Dateien sollten normalerweise nicht (!) extrahiert werden. Classes.zip war wesentlicher Teil des RUNTIME-Moduls (die Systemklassen) von Java in den damaligen Versionen. Die Datei enthält den vollständigen, kompilierten Code von Java und muss in diesen Versionen des JDK einigen JDK-Tools (insbesondere dem Compiler und dem Interpreter) zur Laufzeit zur Verfügung stehen. Ein Entpacken der Datei ist so gut wie nie notwendig, denn Java kann ZIP-Dateien in komprimierter Form verwenden. Falls Sie die Datei dennoch entpacken, erreichen Sie nur eine geringfügige Steigerung der Performance und verlieren viel Platz auf der Festplatte. Die Datei Src.zip beinhaltete in den älteren Versionen den eigentlichen Quellcode von Java. Normalerweise werden Sie diesen Quelltext nicht benötigen. Mit einer Ausnahme – diese Source-Files enthalten zum einen wichtige Informationen über Java, zum anderen können sie das Lernen von Java unterstützen, indem man den Source analysiert. Die Klassen sind in der API-Reference-Dokumentation beschrieben, die mit dem Tool javadoc erstellt wurde. Aber um es nochmals zu betonen – ab der Finalversion des JDK 1.2 werden Sie die Dateien Src.zip und Classes.zip nicht mehr finden. Die Datei Src.zip bzw. das Verzeichnis SRC ist durch die Datei Src.jar ersetzt worden. Diese ist in ihrer Funktionalität identisch. Sie können deren Installation im Setup-Programm mit angeben. Ein .jar-File ist ein Kompri-
Java 2 Kompendium
93
Kapitel 3
Das JDK mierungsformat, mit dem Java direkt arbeiten kann. Es muss genauso wenig extrahiert werden, wie die bisherige ZIP-Dateien. Die Laufzeitumgebung des JDK-1.2-Finalrelease hat sich ebenso vollständig gegenüber den Vorgängern geändert. Die Datei Classes.zip ist im Wesentlichen durch die Datei rt.jar (rt steht für RunTime) ersetzt worden. Darauf kommen wir aber gleich wieder zu sprechen.
3.2.2
Verzeichnisstruktur innerhalb des JDK-Verzeichnisses
Innerhalb des Installationsverzeichnisses des JDK wird von dem Setup-Programm eine Unterstruktur angelegt. Diese hat sich über die verschiedenen JDK-Versionen öfters verändert. Außerdem ist die genaue Verzeichnisstruktur davon abhängig, welche Optionen Sie bei der Installation angegeben haben. Sie werden bei einer vollständigen Installation des JDK 1.3 normalerweise die folgende Struktur finden: Tabelle 3.1: Die Verzeichnisstruktur des JDK
Verzeichnis
Inhalt
\bin
In diesem Verzeichnis befinden sich (wie bei vielen Entwicklungsumgebungen anderer Sprachen) die JDK-Programme, also z.B. der Compiler, der Interpreter, ein Appletviewer, der Debugger, der Disassembler oder das Dokumentationstool. Dieses Verzeichnis ist immer vorhanden – es ist das JDK.
\lib
In diesem Verzeichnis befinden sich defaultmäßig StandardJava-Klassen des JDK. Im Wesentlichen ist das in den alten Versionen des JDK die Datei Classes.zip, ab dem JDK 1.2 (Final) sind es die Dateien Tools.jar, Jvm.lib und Dt.jar. Dazu kommem im JDK 1.3 die Dateien ir.idl, jawt.lib und orb.idl. Tools.jar beinhaltet die Non-Core-Klassen zur Unterstützung der Tools und Utilities im JDK. Dt.jar (DesignTime-Archive) ist dafür da, über BeanInfo-
Dateien interaktiven Entwicklungsumgebungen (IDE's) Informationen zur Verfügung zu stellen, wie sie die Java-Komponenten darstellen sollen und wie sie Entwickler dort für ihre Applikationen anpassen können. Die Datei Jvm.lib ist eine Bibliothek für die virtuelle Maschine von Java. Auf diese Thematik werden wir gleich noch etwas näher eingehen. Die beiden Dateien ir.idl und orb.idl dienen der Zusammenarbeit von Java mit der IDL-Sprache, jawt.lib mit dem AWT Native Interface.
94
Java 2 Kompendium
Installation des JDK
Verzeichnis
Kapitel 3
Inhalt Beachten Sie, dass zwar in den JDK-Versionen vor 1.2 in diesem Verzeichnis die Datei classes.zip zu finden war, aber in neuerern JDK-Versionen nicht deren wesentlicher Ersatz rt.jar. Diese befindet sich an anderer Stelle innerhalb der Verzeichnisstruktur (im Unterverzeichnis \jre).
\include
Der C/C++-Programmierern sicher bekannte Ausdruck »include« steht für ein optionales Verzeichnis, das diverse Header-Dateien für die gemeinsame Verwendung von Java und C/C++ enthält. Außerdem gibt es dort ein Unterverzeichnis \win32, das weitere Header-Dateien beinhaltet. Die CHeaderfiles in diesem Verzeichnis sind ausschließlich für die Unterstützung von Nativecode-Programmierung über das Java Native Interface und das Java Virtual Machine Debugger Interface gedacht.
\include-old
Ab dem JDK 1.2 (Final) gibt es optional dieses Verzeichnis, in dem aus Gründen der Abwärtskompatibilität Header-Dateien zur Unterstützung von Nativecode-Programmierung über ältere Schnittstellen zur Verfügung stehen. Diese Dateien gelten als deprecated (veraltet), werden nicht weiter unterstützt und stehen nicht auf allen Plattformen zur Verfügung.
\demo
Das optionale Demoverzeichnis beinhaltet Beispielprogramme. Es hat einige Unterverzeichnisse (u.a. applets und jfc).
\src
In der JDK-Version 1.1.x und den meisten Betaversionen des JDK 1.2 können Sie das Verzeichnis SRC mit installieren. Darin befinden sich dann die entkomprimierten Java-Dateien, die in diesen JDK-Versionen sonst nur im gepackten Zustand in der Datei Src.zip vorhanden sind. Das Verzeichnis ist durch die Datei Src.jar ab dem JDK 1.2 ersetzt worden, die seitdem im Hauptverzeichnis befindet.
\jre
Das Verzeichnis beinhaltet die Laufzeitumgebung von Java. Es beinhaltet die zwei Unterverzeichnisse bin und lib. Im Wesentlichen finden Sie die Datei rt.jar in lib und in bin diejenigen Programme, die zum Ausführen von Java-Applikationen notwendig sind (ohne Entwicklungstools).
Tabelle 3.1: Die Verzeichnisstruktur des JDK (Forts.)
Nach erfolgreicher Installation können Sie normalerweise das Setup-File des SDK von der Festplatte wieder löschen. Es wird nicht mehr benötigt und belegt nur Platz. Überdies ist es im Gegensatz zu gekaufter Software jederzeit erneut zu beziehen. Jedoch sollten Sie sich darüber im Klaren sein, dass Ihnen dann im Falle einer Neuinstallation erneut ein längerer Download bevorsteht.
Java 2 Kompendium
95
Kapitel 3
Das JDK
3.2.3
Die Java-Laufzeitumgebung jre
Hinter dem Begriff Java Runtime Environment (JRE) verbirgt sich die JavaLaufzeitumgebung, der Minimalstandard, um Java-Programme laufen lassen zu können. Das Java Runtime Environment besteht aus der Java Virtual Machine, Java Core Classes und aufseiten der Tools hauptsächlich aus dem Java-Interpreter, ein paar ergänzenden Programmen sowie einigen dazu gehörenden DLLs. Insbesondere sind keinerlei Entwicklungstools enthalten und kein Tool zum Starten und Ansehen von Applets. Laden können Sie das Java Runtime Environment separat von denselben Quellen, wo auch das JDK zu finden ist. Sie können (und müssen!!) es aber auch in der Setuproutine des JDK mit installieren. Das JRE wird dann wie oben beschrieben im Unterverzeichnis \jre installiert. Sie werden auf Ihrem Rechner diverse Java-Laufzeitumgebungen finden. Das ist einmal diejenige, die vom JDK in dessen Installationsverzeichnis angelegt wird, aber auch an unterschiedlichsten anderen Stellen werden Sie – teils differierende Versionen – finden. Die verschiedensten Programme installieren eine solche Umgebung – in den unterschiedlichsten Versionen.
3.2.4
Das Java-Plug-In
Wir wollen hier den Einsatz des Java-Plug-In (siehe dazu auch Seite 35) durchspielen. Dies wird Ihnen dann die Möglichkeit eröffnen, ihre mit erweiterten Java-Technologien erstellten Java-Applets nicht nur im Appletviewer des JDK zu testen, sondern auch in einem (moderneren) Browser zu testen. Zuerst laden Sie das Tool, das als ZIP-Datei bereitgestellt wird, von den Sun-Seiten. Es gibt dort verschiedene Möglichkeiten, von wo und wie Sie das Tool laden können. Am besten ist natürlich ein direkter FTP-Download. Danach entpacken Sie einfach die ZIP-Datei in leeres Verzeichnis auf Ihrem Rechner. Sie erhalten dort zwei Verzeichnisse. Im Verzeichnis classes befinden sich dann die eigentliche Java-Programmdatei HTMLConverter.class, die Sie mit dem Java-Interpreter direkt starten können (java HTMLConverter) sowie eine Batchdatei mit Namen HTMLConverter.bat, die diesen Vorgang ein wenig vereinfacht. Wenn Sie das Tool gestartet haben, können Sie HTML-Dateien konvertieren und dabei diverse Konfigurationen vornehmen.
96
Java 2 Kompendium
Installation des JDK
Kapitel 3 Abbildung 3.6: Die Downloadseite des HTML-Converters
Abbildung 3.7: Die Downloadseite des HTML-Converters 1.3
Java 2 Kompendium
97
Kapitel 3
Das JDK
Abbildung 3.8: Das Unterverzeichnis classes
Abbildung 3.9: Konvertierung von einer HTML-Seite mit dem <APPLET>-Tag
Spielen wir die Situation mit einem vollständigen Applet durch. Der nachfolgende HTML-Code bindet ein Swing-Applet mittels des <APPLET>-Tags in eine Webseite ein. Listing 3.1: Einbindung von einem SwingApplet mit dem <APPLET>-Tag
98
<TITLE>DemoApplet – Einbindung mit Applet-Tag
Java 2 Kompendium
Installation des JDK <APPLET CODEBASE = "." CODE = "DemoApplet.class" NAME = "TestApplet" WIDTH = 400 HEIGHT = 300 HSPACE = 0 VSPACE = 0 ALIGN
Kapitel 3
= middle>
Im Appletviewer des JDK wird das Applet auch einwandfrei funktionieren. Abbildung 3.10: Klick auf die eine Schaltfläche im Demo-Applet
Abbildung 3.11: Klick auf die andere Schaltfläche im Demo-Applet
Java 2 Kompendium
99
Kapitel 3
Das JDK Schauen wir uns die Webseite nun in halbwegs modernen Browsern an. Der Netscape Navigator 4.7 meldet einen Fehler in der Statuszeile und zeigt nichts an.
Abbildung 3.12: Netscape meldet Probleme im Demo-Applet.
Der Internet Explorer 5 meldet ebenso, dass er eine Klasse nicht finden kann und zeigt auch nichts an. Abbildung 3.13: Der Explorer übt sich in Ignoranz.
100
Java 2 Kompendium
Installation des JDK
Kapitel 3
Wenden wir das Tool nun auf die HTML-Datei an. Das kommt dabei heraus: <TITLE>DemoApplet – Einbindung mit Applet-Tag <EMBED type="application/x-java-applet;version=1.3" CODE = "DemoApplet.class" CODEBASE = "." NAME = "TestApplet" WIDTH = 400 HEIGHT = 300 ALIGN = middle VSPACE = 0 HSPACE = 0 scriptable=false pluginspage="http://java.sun.com/products/plugin/1.3/plugininstall.html"> -->
Java 2 Kompendium
345
Kapitel 7
Grundlagen der Applet-Erstellung Beispiel: <TITLE>Titel Überschriften, Text, Verweise, Grafiken, Java-Applet-Referenz usw.
Listing 7.1: Schematisches Grundgerüst einer Webseite
HTML-Strukturen können verschachtelt werden, das heißt, zwischen einem einleitenden und einem abschließenden Tag können beliebige – sinnvolle – andere Steueranweisungen stehen. Dies ist sogar zwingend, da insbesondere die vollständige HTML-Seite ein einleitendes und ein abschließendes Tag benötigt werden und alle weiteren Steueranweisungen darin verschachtelt werden müssen. Bei der Verschachtelung von Tags sollte jedoch unbedingt die Reihenfolge eingehalten werden! Das bedeutet, wenn ein Container (Einleitungs- und Abschluss-Tag) weitere Tags enthalten soll, sollten diese vollständig darin enthalten sein und in umgekehrter Reihenfolge der Einleitungs-Tags die Abschluss-Tags aufweisen. Zwar kann in vielen Fällen auch eine sich überschneidende Verschachtelung funktionieren, sie ist aber schlecht lesbar und kann in einigen Fällen zu Fehlern führen. Wichtige HTML-Elemente HTML bietet inzwischen eine Menge Gestaltungselemente. Das fängt bei Farben an und geht über Textformatierung, Überschriften, Listen, Tabellen, Eingabefeldern, Buttons bis hin zu Multimedia-Effekten. Diese gehören jedoch nicht in ein Java-Buch, sondern in eine Abhandlung über HTML. Sie sollten jedoch den in unserem Zusammenhang wichtigsten Bestandteil kennen, die Referenz auf andere Objekte innerhalb einer Webseite. Der wichtigste Fall einer Referenz auf andere Objekte ist der Verweis oder Hyperlink. Das WWW lebt nur von diesen Hyperlinks, den lokalen Sprüngen und vor allem den Verweisen auf die verschiedensten anderen InternetInhalte. Mit einem Verweis verzweigen Sie durch Anklicken sofort zu einer angegebenen Adresse, laden ein Programm auf dem lokalen Rechner oder senden eine E-Mail an die im Verweis angegebenen Adresse. Die Grundstruktur eines Verweises in einer Datei setzt man mit den folgenden Steueranweisungen: Verweistext
Java 2 Kompendium
347
Kapitel 7
Grundlagen der Applet-Erstellung Hierbei müssen die einzelnen Bestandteile dieser Grundstruktur natürlich noch genauer bezeichnet werden, was wir uns hier schenken wollen. Nur so viel: Der Typ gibt die Art des Verweises an. Der Bezeichner ist die konkrete Adresse (eine URL). Bei einem Verweis unterscheidet man zwischen verschiedenen Typen von Verweisen und daraus ergibt sich die genaue Syntax des Verweises. Wir wollen uns nur exemplarisch ein paar Beispiele mit verschiedenen Verweistypen ansehen und diese dann kurz beschreiben.
Tabelle 7.2: Einige Beispiele für Hyperlinks
Referenz
Beschreibung.
Zur Datei
Beispiel für einen Verweis auf eine andere Datei innerhalb des gleichen Verzeichnisses.
Zur Datei
Beispiel für einen Verweis auf eine andere Datei in einem relativen Verzeichnis.
Dies ist ein Verweis mit absoluter Pfadangabe auf einem lokalen PC
Beispiel für einen Verweis auf eine lokale, absolut adressierte Datei.
Der Autor
Beispiel für einen nicht-lokalen Verweis.
Ab ins Mehl
Aufruf des E-Mail-Clients aus der Webseite heraus.
Ein anderer Typ von Referenz sind Grafikbezüge. Beispiel: Tabelle 7.3: Eine Grafikreferenz
Referenz
Beschreibung
Referenz auf eine Grafik.
Kommen wir nun zu dem nächsten Referenztyp: der Java-Applet-Referenz (und da wollen wir ja eigentlich hin).
348
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
7.3
Kapitel 7
Konkrete Referenzierung eines Java-Applets
Es gibt derzeit drei aktuelle Varianten, wie Sie ein Applet in eine Webseite integrieren können. Mit dem <APPLET>-Tag, dem <EMBED>-Tag und dem -Tag. Wie bereits angesprochen, ist die ab dem HTML-Standard 4.0 erlaubte Referenzierung eines Applets über das -Tag mit Vorsicht zu genießen, weil dieser Standard noch nicht von vielen Browsern unterstützt wird und das <APPLET>-Tag sicher noch einige Jahre verwendet werden kann. Das <EMBED>-Tag sollte ebenso mit Vorsicht eingesetzt werden.
7.3.1
Die <APPLET>-Syntax
Schauen wir uns zuerst die konkrete Referenzierung eines Java-Applets mit dem <APPLET>-Tag an. Zwischen dem einleitenden Tag und dem abschließenden Tag können Sie gegebenenfalls benötigte Parameter, die dem Applet beim Aufruf übergeben werden, oder auch beliebigen Text eingeben. Die einfachste Form der Applet-Referenz Ein Java-Applet in der einfachsten Form (das heißt ohne irgendwelche Parameter und optionale Attribute) wird mit folgender HTML-Syntax in eine HTML-Seite eingebunden: <APPLET CODE="[classelement]" WIDTH=[Wert] HEIGHT=[Wert]>
Dabei bezeichnet [classelement] die Applet-Klasse, also das Applet selbst (mit Namenserweiterung .class oder auch ohne – es geht beides) WIDTH=[Wert] die Breite des Applets in Pixel. HEIGHT=[Wert] die Höhe des Applets in Pixel. WIDTH und HEIGHT bestimmen also die anfängliche Grö ß e der Darstellung des Applets innerhalb der HTML-Seite. Diese Grö ß enangaben haben nichts direkt mit der »echten« Grö ß e des Applets zu tun. Es kann also durchaus zu Verzerrungen (auch gewollten) des Applets kommen oder unter Umständen wird bei zu kleiner Wahl der Breite und Höhe nicht das vollständige Applet angezeigt.
Die Angabe der Breite und Höhe ist bei der Verwendung des Appletviewers zwingend, während beim Fehlen einer dieser Angaben in vielen Browsern das Applet dennoch angezeigt wird. Setzen Sie aber zur Sicherheit immer beide.
Java 2 Kompendium
349
Kapitel 7
Grundlagen der Applet-Erstellung
Abbildung 7.1: Da fehlt was
Es folgt ein Beispiel für die Syntax zur Einbindung eines einfachen JavaApplets ohne weitere Angaben (nur die Breite und Höhe). Wir verwenden am Anfang ein Applet, das wir ja sowieso noch haben sollten. Beispiel: Listing 7.2: Einfachste Form der Applet-Referenz
<APPLET CODE="HelloJavaApplet.class" WIDTH=150 HEIGHT=75>
Die Angabe der Applet-Klasse erfolgt in der Regel in Hochkommata und mit Dateierweiterung. Beides ist aber – zumindest in den meisten Browsern – nicht zwingend, aber sinnvoll. Der Anzeigebereich des Applets wäre in obigem Beispiel 150 Pixel breit und 75 Pixel hoch. Obwohl es für unser Applet noch nicht viel Sinn macht (der Text bleibt einfach so klein wie er ist), wollen wir die Grö ß enangaben einmal auf WIDTH=150 und HEIGHT=275 verändern. Über die optionale Angabe SRC kann man innerhalb der Applet-Referenzierung zusätzlich die Source-Datei (die Datei mit der Kennung .java) eines Java-Applets angegeben. Diese wird jedoch im Prinzip nicht benötigt, um ein Applet in eine Webseite einzubauen oder zu starten, nur zur Dokumentation der Funktionalität und einer eventuellen Modifizierung des Applets. 350
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
Kapitel 7 Abbildung 7.2: Unser Applet 150 Pixel ist breit und 75 Pixel hoch
Abbildung 7.3: Andere Größ enangaben
Java 2 Kompendium
351
Kapitel 7
Grundlagen der Applet-Erstellung Beispiel:
Listing 7.3: Applet-Referenz mit Source-Angabe
<APPLET CODE="HelloJavaApplet.Class" SRC="HelloJavaApplet.Java" WIDTH=100 HEIGHT=50>
Applet-Referenz mit Pfaden Die bisherigen Beispiele funktionieren nur, wenn sich das Applet im gleichen Verzeichnis wie die aufrufende HTML-Datei befindet. Wenn sich das Applet in einem anderen Verzeichnis befindet, wird dieses über das Attribut CODEBASE bestimmt. Dies ist die Suchpfadangabe für das Applet – eine übliche URL. Hier ein Beispiel für die Einbindung eines Java-Applets mit zusätzlich Pfadangaben (relativ) auf das Unterverzeichnis classes. Beispiel: Listing 7.4: Applet-Referenz mit relativer Angabe eines Suchpfades für die .class-Datei
<APPLET CODEBASE="classes" CODE="HelloJavaApplet.class" WIDTH=100 HEIGHT=50>
Das Verzeichnis in der CODEBASE-Anweisung wird in der Regel ebenfalls in Hochkommata stehen und kann vor oder hinter der Codeanweisung stehen. In diesem Beispiel wird die Position des Applets relativ zur Position des HTML-Dokuments angegeben. Ein Applet kann genauso gut mit einer absoluten Pfadangabe referenziert werden. Dabei spielt es keine Rolle, ob sich das Applet auf dem gleichen Rechner oder einem anderen Server befindet, wie das folgende Beispiel für die Einbindung eines Java-Applets mit absoluten Pfadangaben zeigt (mit Kommentar innerhalb des Containers, der in nicht-Java-fähigen Browsern angezeigt wird). Beispiel:
Listing 7.5: Applet-Referenz mit absoluter URLAngabe eines Suchpfades für die .class-Datei
<APPLET CODEBASE="http://www.rjs.de" CODE="HelloJavaApplet.class" WIDTH=100 HEIGHT=50> Das Applet wird über http://www.rjs.de adressiert
Für CODEBASE kann also eine beliebige URL gesetzt werden. Es können also darüber ganz leicht Netzwerkzugriffe realisiert werden (wenngleich auf diese Art von außerhalb des Applets).
352
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
Kapitel 7
Die genaue Position des Applets in der Webseite Die Position eines Applets auf der Seite ergibt sich aus der Stelle, wo das <APPLET>-Tag in das HTML-Dokument eingefügt ist. Dabei kann ein Applet genau wie andere Objekte (etwa Überschriften oder Grafiken) innerhalb der Seite mit allen üblichen HTML-Spezifikationen ausgerichtet werden. Ein Applet, das beispielsweise in die HTML-Zentrierungs-Tags und eingeschlossen ist, wird beim Anzeigen zentriert ausgegeben. Beispiel: <APPLET code="HelloJavaApplet.class" width="500" height="600">
Listing 7.6: Zentrierung eines Applets Abbildung 7.4: Das Applet zentriert
Zusätzlich lassen sich bei einem Applet noch Angaben über den Textfluss um das Applet herum machen, wie das nachfolgende Beispiel für die Einbindung eines Java-Applets mit Angaben zum Textfluss zeigt. Beispiel: <APPLET CODE="HelloJavaApplet.class" WIDTH=100 HEIGHT=50 ALIGN=middle VSPACE=25 HSPACE=30>
Java 2 Kompendium
Listing 7.7: Angaben zum Textfluss um das Applet herum
353
Kapitel 7
Grundlagen der Applet-Erstellung Dabei gibt es für die Angabe ALIGN, die die Ausrichtung von einem dem Applet folgenden Text angibt, folgende Werte: LEFT: links ausgerichtet RIGHT: rechts ausgerichtet MIDDLE: zentriert in der horizontalen Ausrichtung am Applet
Die Angabe VSPACE definiert den vertikalen Abstand zwischen Applet und Text oberhalb und unterhalb des Applets. HSPACE definiert den horizontalen Abstand links und rechts vom Applet. Der Container-Inhalt Zwischen dem einleitenden Tag <APPLET> und dem abschließenden -Tag kann beliebiger Text stehen. Dies nutzt man hauptsächlich dafür, in einem nicht Java-fähigen Browser deutlich zu machen, dass an dieser Stelle ein Java-Applet steht. Sie sollten sich nicht täuschen – so was gibt es wirklich noch. Und nicht zuletzt: Die Java-Option lässt sich auch in modernen Browsern deaktivieren. Es ist kein guter Stil, wenn man sich einfach auf den Standpunkt stellt, dass jeder Besucher einer Webseite gefälligst Javafähige Browser zu nutzen und die entsprechende Option zu aktivieren hat. Denken Sie daran, dass in der Regel nicht der Surfer etwas von Ihnen will, sondern Sie ihm etwas anbieten wollen. Machen Sie doch einfach Surfer mit fehlender Java-Funktionalität im Browser neugierig, indem Sie mit einem netten Sätzchen locken. Man macht sich übrigens bei dem Text zwischen den <APPLET>-Tags wie auch beispielsweise bei Grafiken oder der Frame-Technik das Prinzip der Fehlertoleranz zunutze. Wenn Browser unbekannte Tags – in diesem Fall das <APPLET>-Tag – finden, werden sie den Tag ignorieren und den nachstehenden Text als reinen ASCII-Text auf dem Bildschirm anzeigen. Javafähige Browser (mit aktivierter Java-Option) sind so konzipiert, dass sie den Text zwischen ein- und abschließenden -Tags nicht anzeigen, sondern eben das Applet selbst. Sie können zum Beispiel angeben, dass dort ein Java-Applet steht, das nicht Java-fähige Browser eben nicht anzeigen. Beispiel: <APPLET code="HelloJavaApplet.class" width="500" height="600">Wenn Sie hier diesen Text sehen, ist Ihr Browser nicht in der Lage, Java-Applets darzustellen oder Sie haben die entsprechende Option deaktiviert, denn hier sollte ein Applet zu sehen sein! Ich kann nur sagen – Sie verpassen etwas. Wie wäre es – aktivieren Sie Ihre Java-Option und laden Sie dann die Seite neu. Falls Sie keinen Java-fähigen Browser haben – etwas weiter unten
354
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
Kapitel 7
befinden sich ein paar Hyperlinks, von denen Sie sich solche Browser laden können. Und dann: Come back and enjoy Java!
Der alte Mosaic-Browser von CompuServe ist ein Exempel für einen nichtJava-fähigen Browser. Hier wird statt des Applets der freundliche Hinweis auf ein Applet zu sehen sein. Abbildung 7.5: Langsam wird es Zeit für ein Update.
Die gleiche HTML-Datei sieht in einem Java-fähigen Browser wie wir oben schon gesehen haben oder vergleichbar aus. Bei Text, der das Applet umfließt, kann es zu Missverständnissen kommen, da vor und nach dem Applet stehender Text den Hinweis auf das Applet in nicht-Java-fähigen Browsern unter Umständen nicht auffällig genug macht. Verwenden Sie am besten irgendwelche Unterschiede zwischen normalem Text und dem Hinweis auf das Applet (etwa Farbe oder Schriftgrö ß e).
7.3.2
Die Parameter des <APPLET>-Tags
Eine ganz wichtige Art von Angaben kann zwischen dem einleitenden Tag <APPLET> und dem abschließenden Tag stehen – die Parameter, die über eigene Tags innerhalb des Containers notiert werden. Unter solchen Parametern versteht man Werte, die ein Programm – oder in diesem Fall das Applet – benötigt, um laufen zu können und die den Ablauf des Programms/ Applets beeinflussen. Die Situation ist uns ja nicht unbekannt. Bei vielen DOS-Befehlen muss man Parameterangaben machen, damit der Befehl erst einen Sinn bekommt. Denken Sie an den Kopierbefehl COPY, der erst durch Angabe von zwei Parametern – der Quelle und dem Ziel – vom Betriebssystem ausgeführt werden kann und auch dann erst Sinn macht.
Java 2 Kompendium
355
Kapitel 7
Grundlagen der Applet-Erstellung
Abbildung 7.6: Schlecht: Der Applethinweis ist kaum zu erkennen.
Abbildung 7.7: So ist es zumindest zu erkennen.
Wir kennen auch bereits einen Java-Fall, wo wir Parameter von außen an ein Java-Programm übergeben haben. Um Argumente auf Befehlszeilenebene an ein Java-Programm weiterzugeben, müssen diese einfach an den Programmaufruf – mit Leerzeichen abgetrennt – angehängt werden. Die Parameter in dem <APPLET>-Container der HTML-Seite sind nun bei einem Applet das Analogon zu den Argumenten auf Befehlszeile bei einer eigenständigen Applikation.
356
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
Kapitel 7
Wenn Sie ein Applet nur in eine Webseite einbinden wollen, haben Sie keinen Einfluss auf die verwendeten Parameter. Dies ist natürlich eine andere Situation, als wenn Sie den Source des Applets erstellen. Welche Parameter ein Applet konkret benötigt, ist fest in dem Java-Applet einprogrammiert und kann von einem reinen Anwender beim Aufruf nicht verändert werden. Viele Applets benötigen keine Parameter, andere wiederum mehrere. Wenn Sie ein bestehendes Applet einbinden wollen, müssen Sie diese Information aus der Dokumentation des Applets entnehmen. Wenn Sie keinen Hinweis auf Parameter finden, ist es sehr wahrscheinlich, dass das Applet auch keine braucht. Auf jeden Fall gilt dann »Try and Error«. Wenn es funktioniert, dann benötigt es wirklich keine Parameter. Wir kommen in einem nachfolgenden Abschnitt zur Auswertung und Verwendung von Parametern im Source des Applets. Lassen Sie uns zuerst noch die HTML-Syntax für die Parameter beenden. Die Angabe von Parametern erfolgt einfach über Parameter-Tags – gegebenenfalls mehrere hintereinander. In diesem Fall spezifiziert jedes Parameter-Tag einen anderen AppletParameter. Sie sehen wie folgt aus: .
In den Parameterangaben werden zwei Bezeichner verwendet: name – der Name des Parameters value – der Wert des angegebenen Parameters
Ein Beispiel für die Einbindung eines Java-Applets mit Parameter-Angaben: <APPLET code="Ataxxlet.class" width=450 height=550>
Listing 7.8: Beispiel einer Applet-Referenz mit Parametern
Im gesamten -Tag kann man zwar Groß- und Kleinschreibung verwenden (es ist ja HTML), aber beim name- und value-Wert kann Großund Kleinschreibung eine Rolle spielen. Diese Werte werden ja an das JavaApplet übergeben und da kommt es darauf an, wie dieses die Werte verwendet. Abschließend soll besprochen werden, was für und was gegen die AppletReferenzierung mit dem <APPLET>-Tag spricht.
Java 2 Kompendium
357
Kapitel 7
Grundlagen der Applet-Erstellung Kontra: 1.
Der Tag ist vom W3C als deprecated erklärt worden. Das will aber nicht viel heißen, denn viele als deprecated erklärte Tags werden unverändert weiter verwendet. Oft ist es sogar so, dass deren Verwendung statt der offiziellen Befehle von Profis gerade ausdrücklich empfohlen wird. So beruhen Optimierungsmaßnahmen in einer HTML-Seite beispielsweise darauf, bei einer Zentrierung statt des align-Attributs für Absatz-bezogene HTML-Tags (offizielle Empfehlung) das als deprecated gekennzeichnete -Tag zu verwenden, da damit Zeichen gespart werden können und die Seite kleiner und damit schneller zu laden ist.
2.
Die Unterstützung der Java-Plug-Ins funktioniert mit diesem Tag nicht. Wenn in einem Applet also Java-APIs verwendet werden, die von der virtuellen Maschine des Browsers nicht unterstützt werden, wird das Applet nicht laufen. Um es drastisch zu formulieren – ein mit diesem Tag referenziertes Applet sollte nur Techniken verwenden, die maximal auf Java 1.0.2 beruhen oder zumindest in allen potenziellen Zielbrowsern getestet werden.
Pro: 1.
Der Tag ist einfach anzuwenden.
2.
Der Tag wird von allen Java-fähigen Browsern verstanden – auch den älteren.
3.
Es wird kein zusätzliches Plug-In benötigt.
4.
Der Tag ist populär. Das soll Verschiedenes bedeuten. Einmal kennen viele Anwender dieses Tag. Das führt dazu, dass jeder, der den Quelltext liest, leicht erkennen kann, dass hier ein Java-Applet referenziert wird. Die Konkurrenz-Tags machen das dem Laien nicht so deutlich. Diese suggerieren etwa im Fall des -Tags eine Verbindung zu der umstrittenen ActiveX-Technologie und das kann zur Ablehnung durch den Anwender führen. Die Popularität bedeutet aber auch, dass viele HTML-Tools dieses Tag automatisch verwenden, wenn ein Anwender ein Java-Applet einbindet.
7.3.3
Die <EMBED>-Syntax
Das <EMBED>-Tag ist eine Netscape-Erweiterung von HTML 3.2 zur allgemeinen Einbindung von Multimedia-Elementen und auch Applets in eine Webseite. Er wird gelegentlich auch Java-Plug-In-Tag genannt. Die Verwendung sollte mit Vorsicht geschehen, da die Technik im Wesentlichen auf Netscape Browser ab der Version 4.x beschränkt ist (einige Ausprägungen
358
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
Kapitel 7
des Tags werden aber auch in neueren Versionen des Internet Explorers verstanden). Java-Applets werden damit mit dem angegebenen Java-Plug-In von Sun gestartet. Die allgemeine Syntax sieht so aus: <EMBED type="[PlugIn]" pluginspage ="[URL]" code="[NameApplet].class" name="[NameApplet]" object="[serializedObjectOderJavaBean]" codebase="[VerzeichnisclassFile]" width="[Breite]" height="[Höhe]" align = [Ausrichtung] vspace = [Textfluss vertikal] hspace = [Textfluss vertikal] > ...
Listing 7.9: Schema für die Einbindung eines Applets mit <EMBED>
Über das Attribut type geben Sie das verwendete Plug-In an. Diese Angabe kann das Plug-In noch genauer spezifizieren (etwa "application/x-java-applet;version=1.2"). Über die optionale Angabe pluginspage kann man eine Downloadmöglichkeit in Form einer URL angegeben, wo der ein lokal nicht vorhandenes Plug-In bei Bedarf automatisch geladen werden kann (etwa pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html"). Die Angaben code und object dürfen nicht gleichzeitig verwendet werden, die restlichen Attribute sind wie beim <APPLET>-Tag zu verstehen. Die Einbindung von HelloJavaApplet.class funktioniert beispielsweise so: <EMBED type="application/x-java-applet;version=1.3" CODE = "HelloJavaApplet.class" CODEBASE = "." NAME = "HelloJavaApplet" WIDTH = 400 HEIGHT = 300 ALIGN = middle VSPACE = 0 HSPACE = 0 pluginspage= "http://java.sun.com/products/plugin/1.3/plugin-install.html"> Java 2 Kompendium
Listing 7.10: Die Einbindung des Applets HelloJavaApplet.class mit <EMBED>
359
Kapitel 7
Grundlagen der Applet-Erstellung
Abbildung 7.8: Die Darstellung im Navigator funktioniert mit <EMBED>
Mit dieser Form der Einbindung gibt es leider diverse Probleme. Kontra: 1.
Der Tag ist vom W3C als deprecated erklärt worden. Das ist aber wie beim <APPLET>-Tag nur ein »Papier-Tiger«-Argument.
2.
Der Tag ist mit seinen Parametern relativ komplex. Bei vielen »HobbyHomepage-Bauern« wird das ein Problem.
3.
Der Tag ist in dieser vollständigen Version auf neuere Navigator-Versionen und kompatible Browser beschränkt. Man muss also für Internet-Explorer-Anwender zusätzlich ein weiteres Tag verwenden.
4.
Ein Applet kann nicht dargestellt werden, wenn das angegebene PlugIn nicht zur Verfügung steht und gerade keine Onlineverbindung besteht, der Anwender kein extra Plug-In installieren möchte oder der Browser mit dem Plug-In nicht zurechtkommt.
5.
Wenn das Java-Plug-In verwendet werden soll, muss beim Client eine passende, zusätzliche virtuelle Maschine vorhanden sein.
Pro: 1.
Das Java-Plug-In wird unterstützt. Das bedeutet, ein Java-Applet kann theoretisch die gleichen APIs nutzen wie eine vollständige Java-Applikation. Das setzt aber voraus, dass auf der Client-Plattform eine passende virtuelle Maschine vorhanden ist.
7.3.4
Die -Syntax
Das -Tag ist das neue Standard-Tag unter HTML 4.0 zum Einbinden von Applets und beliebigen Multimedia-Objekten in eine Webseite. Eingeführt wurde der Tag in der Grundform ursprünglich als Erweiterung des Internet Explorer 4.x für HTML 3.2. Die Syntax sieht schematisch so aus: 360
Java 2 Kompendium
Konkrete Referenzierung eines Java-Applets
Kapitel 7
Der Wert des classID-Attributs ist die weltweit eindeutige ActiveX-ID für das Java-Plug-In (immer classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"), das Sie setzen müssen, damit das -Tag es im Browser aktiviert. Das codebase-Attribut wird dafür verwendet, das Java-Plug-In aus dem Netz zu laden, wenn es fehlt (etwa codebase="http://java.sun.com/products/plugin/ 1.3/jinstall-13-win32.cab#Version=1,3,0,0"). Verwechseln Sie nicht das codebase-Attribut des -Tags mit dem Parameter codebase (<param name="codebase" value="[Verzeichnis-Class-File]">), der optional eine relative URL zur Angabe des Ortes von der Applet-Klasse spezifizieren kann. Die Angabe <param name="JAVA_CODE"... ist eine Spezifizierung für den Fall, dass es Konflikte zwischen anderen Parametern der Form <param name="CODE"... gibt. Das type-Parameter-Tag wird zum Laden des Plug-Ins verwendet. In der NAME="type" Regel ist das wieder eine Angabe wie
Für ein serialisiertes Objekt oder JavaBean wird das type-Parameter-Tag in der Regel so aussehen: <param name="type" value="application/x-java-bean;version=1.1">
oder <param name="type" value="application/x-java-bean">
Was spricht nun für und gegen den Einsatz dieses Tags? Java 2 Kompendium
361
Kapitel 7
Grundlagen der Applet-Erstellung Kontra: 1.
Der Tag ist mit seinen Parametern relativ komplex. Mehr noch als beim <EMBED>-Tag werden viele Webseiten-Ersteller von der Syntax abgeschreckt. Allerdings können viele HTML-Tools die manuelle Erstellungen abnehmen.
2.
Der Tag ist auf neuere Internet-Explorer-Versionen und kompatible Browser beschränkt. Man muss also für Navigator-Anwender zusätzlich einen weiteren Tag verwenden.
3.
Ein Applet kann nicht dargestellt werden, wenn das angegebene PlugIn nicht zur Verfügung steht und gerade keine Onlineverbindung besteht, der Anwender kein extra Plug-In installieren möchte oder der Browser mit dem Plug-In nicht zurechtkommt.
4.
Wenn das Java-Plug-In verwendet werden soll, muss beim Client eine passende, zusätzliche virtuelle Maschine vorhanden sein.
5.
Der Tag arbeitet mit einer ActiveX-ID. ActiveX-bezogene Technik wird weder von allen Browsern im Internet unterstützt, noch erlauben halbwegs sicherheitsbewusste Surfer deren Verwendung. Unnötigerweise wird eine absolut sichere Technologie wie Java mit dem wohl grö ß ten Sicherheitsrisiko im Web in Verbindung gebracht.
Pro: 1.
Der Tag ist vom W3C zum Standard-Tag erklärt worden. Aber genau wie bei den als deprecated gekennzeichneten Tags ist das kein echtes Argument. Weder Anwender noch die meisten Browser-Hersteller kümmert das in irgendeiner Weise.
2.
Das Java-Plug-In wird unterstützt. Das bedeutet, ein Java-Applet kann theoretisch die gleichen APIs nutzen wie eine vollständige Java-Applikation. Das setzt aber voraus, dass auf der Client-Plattform eine passende virtuelle Maschine vorhanden ist.
7.3.5
Welches Tag ist sinnvoll?
Da es für jede der drei beschriebenen Referenzmodell Pro- und KontraArgumente gibt, muss jeder Anwender abwägen, was ihm am wichtigsten ist. Einige Aussagen können dabei aber als Leitschnur dienen: Wenn das Applet möglichst große Verbreitung erhalten soll und keine Java-Technologie jenseits von Java 1.0.2 verwendet wird, ist das <APPLET>-Tag die einzig sinnvolle Wahl. Offizielle Quellen hin oder her. Diese argumentieren politisch.
362
Java 2 Kompendium
Die interne Arbeitsweise eines Applets
Kapitel 7
Wird Java-Technologie verwendet, deren Unterstützung in den virtuellen Maschinen der Browser man sich nicht sicher ist, sollte man mit dem <APPLET>-Tag die potenziellen Zielbrowser testen. Läuft das Applet mit der <APPLET>-Referenz, sollte diese auf jeden Fall genommen werden. Verwendet man Technologie, die jenseits der virtuellen Maschinen der Zielbrowser angesiedelt ist, kommt man um die Tags zum Aufruf des Java-Plug-Ins nicht herum. Mit allen Konsequenzen. In einem Intranet sind die negativen Auswirkungen zu minimieren. Im Internet sollte man sehr gut abwägen. Die bessere Alternative ist es sicher, wenn es irgend geht, bei Applets auf Java-APIs zu verzichten, die in Browsern Probleme machen können. Nutzen Sie den in Kapitel 1 näher beschriebenen HTML-Konverter (zu laden von der Sun-Plug-In-Homepage http://java.sun.com/products/ plugin), der aus einer Webseite mit dem <APPLET>-Tag eine solche mit -Tag (für den Internet Explorer) bzw. <EMBED>-Tag (für den Netscape Navigator) macht.
7.3.6
Die ursprüngliche HotJava-Syntax
Nur der Vollständigkeit halber sei die HotJava-Syntax zum Referenzieren eines Applets innerhalb einer HTML-Seite noch kurz angerissen. Sie definieren die Referenz auf ein Applet mit dem Befehl <APP>. Dieser Befehl hat offiziell kein abschließendes Tag. Parameterangaben werden in Form von Zusatzangaben innerhalb des <APP>-Tags notiert. Beachten muss man, dass die Klasse ohne .class angegeben werden muss.
7.4
Die interne Arbeitsweise eines Applets
Was passiert nun mit den Parametern, die beispielsweise mit dem Tag an das Applet weitergereicht werden? Und wie wird eigentlich ein Applet in seinem Inneren funktionieren? Es geht also ab jetzt darum, HTML wieder zu verlassen und zu Java zurückzukehren. Um diese Fragen zu beantworten, sollten wir uns an den Aufbau eines Applets erinnern, wie wir ihn schon vor unserem ersten Applet angesprochen haben. Eine eigenständig lauffähige Java-Applikation benötigt – wie wir jetzt schon mehrfach gesehen haben – immer nur eine main()-Methode. Ein Java-Applet besitzt im Gegensatz zu einem Java-Programm im Allgemeinen keine main()-Methode2, die beim Laden gestartet wird und das Programm solange am Leben erhält, bis der Benutzer es beendet. Statt dessen sorgen bei voller Funktions-
2
oder benutzt zumindest keine
Java 2 Kompendium
363
Kapitel 7
Grundlagen der Applet-Erstellung fähigkeit mindestens vier andere Methoden – die init()-Methode, die start()-Methode, die stop()-Methode und die destroy()-Methode – im Programm dafür, dass sich das Applet in seine Umgebung korrekt verhält. Ein Applet befindet sich immer innerhalb eines Containers und muss sich kooperativ zu ihm verhalten. Es muss also die Möglichkeiten nutzen, die ihm der Container zur Verfügung stellt. Um nun erklären zu können, was beispielsweise konkret mit den Parametern passiert, müssen wir noch ein wenig weiter ausholen.
7.4.1
Erstellung und Grundmethoden eines Applets
Um ein Applet zu erstellen, müssen Sie immer eine Subklasse der Klasse java.applet.Applet (fundamentaler Bestandteil von Java) erzeugen. Diese Klasse beinhaltet bereits sämtliche Eigenschaften, die die Kooperation mit dem Container sicherstellen, die Fähigkeiten des AWT für Oberflächenprogrammierung (Menüs, Button, Mausereignisse usw.) nutzbar machen und auch die lebenswichtigen Grundmethoden für ein Applet. Letzteres war auch der Grund, warum unser erstes Applet funktioniert hat, obwohl wir auf diese Methoden verzichtet haben. Sie wurden einfach aus der Superklasse gezogen. Normalerweise werden Sie diese jedoch überschrieben. Jede Applet-Klasse wird mit folgender Syntax als Unterschrift erstellt: public class <AppletName> extends java.applet.Applet
Java setzt übrigens für die sinnvolle Verwendung voraus, dass eine AppletKlasse als public deklariert wird.
Applets sollten java.applet.* importieren, um sich im Laufe des Quelltexts Schreibarbeit zu sparen. Applets mit grafischen Schnittstellen benötigen meist auch java.awt.*. Im Inneren des Applet-Codes werden dann die notwendigen Methoden für die Funktionalität des Applets platziert. Darunter fallen natürlich ebenfalls die Grundmethoden, die das Leben eines Applets festlegen. Schauen wir uns nun diese vier Stationen im Leben eines Applets im Detail an. Sie werden normalerweise in einem Applet sie teilweise oder gar allesamt überschreiben. Die Initialisierung Der Einstieg in ein Applet-Leben ist immer die Initialisierung. Diese erfolgt immer mit der Methode public void init(), die automatisch aufgerufen
364
Java 2 Kompendium
Die interne Arbeitsweise eines Applets
Kapitel 7
wird, sobald das Applet in den Browser (oder einen anderen Container wie den Appletviewer) geladen wird. Hier wird das System zur Ausführung des Applets vorbereitet. An dieser Stelle werden beispielsweise die Bildschirmanzeige initialisiert, Netzwerkverbindungen oder Datenbankzugriffe aufgebaut oder Schriften eingestellt. Und hier ist auch die Stelle, wo die Parameter aus dem HTML-Code der Seite eingelesen werden können. Sie können hier mit der Methode public String getParameter(String name) auf diese Parameter zugreifen. Mehr zur Auswertung von Übergabewerten an ein Applet finden Sie etwas weiter unten auf Seite 368. Der Start Die Methode public void start() wird beim Start des Applets direkt nach der Initialisierung aufgerufen. Während die Initialisierung nur einmal erfolgt, kann (und wird normalerweise) der Start beliebig oft wiederholt werden. Beispielsweise, wenn das Applet gestoppt wurde oder das Applet durch scrollen des HTML-Dokuments erneut in den sichtbaren Bereich des Browsers geholt wird. Um das Startverhalten Ihres Applets zu spezifizieren, überschreiben Sie die start()-Methode. Dort können diverse Funktionalitäten stehen, beispielsweise das Starten eines Threads oder der Aufruf einer anderen Methode. Das Stoppen eines Applets Das Stoppen eines Applets hört sich schlimmer an, als es wirklich ist. Die Methode public void stop() wird automatisch aufgerufen, sobald Sie die HTML-Seite, auf der das Applet läuft, verlassen. Ein gestopptes Applet ist jedoch weiter voll funktionsfähig und wird bei der Rückkehr auf die Seite automatisch durch die Methode start() wieder zu neuem Leben erweckt. Erinnern Sie sich an den Appletviewer? In dem Menü finden Sie die Startund Stop-Funktionalitäten wieder. Das Zerstören eines Applets Wenn ein Applet-Container beendet wird, ermöglicht die Methode public void destroy() dem Applet, vernünftig hinter sich aufzuräumen und die letzten Systemressourcen, die es belegt hatte, freizugeben. Unter solche Aufräumarbeiten fallen die Beendigung von laufenden Threads oder die Freigabe von anderen laufenden Objekten. Normalerweise müssen Sie die destroy()-Methoden nicht überschreiben, sofern Sie nicht explizit Ressourcen freigeben müssen.
Java 2 Kompendium
365
Kapitel 7
Grundlagen der Applet-Erstellung Noch einmal zur Erinnerung: Die allgemeinere finalize()-Methode ist hier nicht zu verwenden, da diese eher für ein einzelnes Objekt irgendeines Typs zum Aufräumen verwendet wird und vor allem, weil im Gegensatz zu der finalize()-Methode die destroy()-Methode immer beim Beenden eines Browsers oder beim Neuladen eines Applets automatisch ausgeführt wird.
7.4.2
Ein Musterapplet als Schablone
Nachfolgend sehen Sie ein Musterapplet, das als Gerüst für sämtliche Applets verwendet werden kann. Es besteht im Wesentlichen aus dem Import einiger wichtiger Java-Pakete, die für das Applet von Bedeutung sein können. Diese sind in der Schablone auskommentiert und müssen bei Bedarf aktiviert werden. Wenn Sie weitere Pakete benötigen, können Sie diese selbstverständlich hinzufügen. Sie können sogar alle denkbaren Pakete importieren (ob Sie diese dann brauchen oder nicht), denn das Java-Importieren ist ja kein Einbeziehen der Pakete in den Source wie mit include in C. Daher werden Sie keinen grö ß eren Sourcecode bekommen und auch sonst keine Verluste erleiden. Es könnte nur sein, dass Ihr Quellcode an Übersichtlichkeit verliert. Der Klassenname in der Top-level-Klassen-Deklaration des Applets muss natürlich durch die korrekte Bezeichnung ersetzt werden. Listing 7.11: Eine Schablone für ein Applet
366
// Name der Klasse // Beschreibung: // Import der Pakete // import java.applet.*; // import java.awt.*; // import java.awt.image.*; // import java.awt.peer.*; // import java.io.*; // import java.lang.*; // import java.net.*; // import java.util.* // Top-level-Klassen-Deklaration des Applets. public [Klassenname] extends java.applet.Applet { // Variablen-Deklaration // Bauen Sie hier Ihre eigenen Methoden ein // Die Methoden, die überschrieben werden public void init() { } public void start() { } public void stop() { } public void destroy() { } // Optional, aber sehr wahrscheinlich –
Java 2 Kompendium
Die Applet-Klasse // // // // // // }
Kapitel 7
die Ausgabemethode public void paint(Graphics g) { } Bei Multithreading die run()-Methode verwenden. public void run() { }
7.5
Die Applet-Klasse
Wir haben jetzt gesehen, dass ein Applet von der Applet-Klasse abgeleitet wird. Die Applet-Klasse selbst wiederum erbt von einer ganzen Reihe anderer Klassen. Eine Klasse, die java.applet.Applet erweitert, kann Variablen und Methoden (sowie Konstruktoren) aus java.lang.Object, java.awt.Component, java.awt.Container und java.awt.Panel verwenden. Schauen wir uns die Applet-Klasse noch ein bisschen genauer an. Die Methoden der Applet-Klasse ermöglichen Applets diverse Grundfunktionen. Sie erlauben Applets, Parameter zu handhaben, Grafik zu handhaben, Bilder zu importieren, Sound-Clips zu importieren und abzuspielen, mit dem Browser oder dem Appletviewer zu interagieren oder Lebenszyklen des Applets zu verwalten. Wir wollen uns ein paar wichtige Methoden ansehen, die diese Vorgänge unterstützen. Dabei muss als Hinweis vorausgeschickt werden, dass diese Vorstellung nur ein Schlaglicht auf die Möglichkeiten eines Applets werfen wird. Insbesondere werden nicht sämtliche Varianten der angesprochenen Methoden aufgeführt, sondern jeweils eine sinnvolle Version ausgewählt. Selbst ein einfaches Applet besteht also in der Regel aus mehr als nur den genannten vier Grundmethoden. Da sind zum einen die selbst definierten Methoden, die z.B. in der start()-Methode aufgerufen werden können. Es gibt jedoch noch ein paar Standardmethoden, die so wichtig sind, dass wir sie hier behandeln wollen. Einige davon kennen Sie bereits. Wir haben sie in unserem ersten Applet verwendet.
Java 2 Kompendium
367
Kapitel 7
Grundlagen der Applet-Erstellung
7.5.1
Ausgabe in einem Applet mit der paint()-Methode
Erinnern Sie sich an die Ausgabe in unserem ersten Applet? Wir haben dazu nicht die println()-Methode, sondern eine Ausgabe innerhalb der public void paint(Graphics g)-Methode verwendet. Wir haben unseren Text gezeichnet und nicht geschrieben. Zeichnen bestimmt im Allgemeinen, wie ein Applet etwas auf dem Bildschirm ausgibt. Dies kann beliebig oft während eines Applet-Lebens vorkommen. Um einem Applet das Zeichnen zu ermöglichen, müssen sie diese paint()-Methode überschreiben. Diese steht jedem Applet defaultmäß ig zur Verfügung und wird automatisch aufgerufen, wenn es notwendig ist (d.h. beim Starten des Applets, wenn das Applet zum Teil verdeckt wurde und wieder ein grö ß erer Bereich angezeigt wird usw.). Die paint()-Methode wird automatisch aufgerufen, wenn Sie das Applet (erneut) starten.
Es wird Ihnen sicher auffallen, dass die paint()-Methode einen Parameter hat: eine Instanz der Klasse java.awt.Graphics. Deshalb müssen Sie sicherstellen, dass die Graphics-Klasse in Ihren Applet-Code importiert wird, oder den Parameter vollqualifiziert angegeben. Die Grafik-Ausgabe ist ein so wichtiges Thema, dass wir es hier abbrechen und in einem eigenen Kapitel gründlich durchsprechen wollen. Nichtsdestotrotz wird in den nachfolgenden Beispielen die paint()-Methode verwendet werden. Auch auf eigenständigen Applikationen mit grafischer Oberfläche steht die paint()-Methode zur Verfügung.
7.5.2
Übergabewerte für ein Applet
Über die getParameter()-Methode können Sie auf jedes Argument zugreifen, das unter HTML in der Applet-Referenz mit dem name-Wert spezifiziert wurde. Dieser Wert von name ist eine Zeichenkette, die in der getParameter()-Methode in den Klammern angeben werden muss. Die Rückgabe der getParameter()-Methode ist der mit value in der HTML-Datei spezifizierte Wert. Beispiel: String parameter1 = getParameter("htmlParameterName")
Falls Sie einen Parameter spezifizieren, der in der HTML-Datei nicht angegeben wurde, gibt die getParameter()-Methode null zurück. Dies sollte man immer mit einer Abfrage auswerten und einen Standardwert einstellen. 368
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7
Beispiel: if (parameter1 == null) parameter1 = "Standardwert1"
Der im HTML-Parameter-Tag angegebene Name und der in der getParameter()-Methode spezifizierte Name müssen absolut identisch sein, auch in Bezug auf Groß- und Kleinschreibung. Da die Rückgabe der getParameter()-Methode immer eine Zeichenkette ist, müssen alle Übergabeparameter eines Java-Applets in Form von Zeichenketten übergeben und dann im Source ebenso behandelt werden. Wenn Sie die Parameter in einem anderen Datentyp verwenden wollen, müssen Sie diese konvertieren. Sie können allerdings (wie im letzten Kapitel besprochen) nicht per Casting vorgehen, sondern müssen die Instanzen der als Ersatz dafür vorhandenen Wrapper-Klassen verwenden. Diese sind für alle primitiven Datentypen vorhanden. Wenn Sie z.B. einen Parameter in einen long-Wert umwandeln wollen, kann das so erfolgen: long l = new Long(stringParameter).longValue()
Wie ein Applet-Code Standard-Parameter aus einem HTML-Dokument erhält, haben wir also damit gesehen. Wie aber stellt das Applet Informationen über benötigte Parameter bereit? Was von einem Anwender des Applets verlangt wird, ist ja, dass er die Parameter in der HTML-Datei richtig angibt, also den Namen der Übergabewerte, den jeweiligen Datentyp und eine Beschreibung. Diese Informationen kann ein Applet in einer Methode dokumentieren, die ein Applet-Client dann beispielsweise auswerten kann. Es handelt sich um die Methode public String[][] getParameterInfo().
Diese gibt ein Zeichenketten-Array wieder, wo alle Parameter aufgelistet werden können, die das Applet benötigt. Diese Zeichenkette spezifiziert für jeden Parameter den Namen, den Typ und eine Beschreibung. Beispiel (mit zwei Parametern): public String[][] getParameterInfo() { String[][] pinfo = { {"MeinPara1", "String", "Stringübergabewert"}, {"MeinPara2", "int", "int-Übergabewert"}, }; return pinfo; }
Listing 7.12: Beispiel für eine überschriebene getParameterInfo()Methode
In den gleichen Zusammenhang fällt die Methode public String getAppletInfo().
Java 2 Kompendium
369
Kapitel 7
Grundlagen der Applet-Erstellung Mit dieser Methode kann man Angaben über das Applet machen, etwa den Autor, die Version, das Erstellungsdatum usw. Auch diese Methode kann in einem Applet-Client abgefragt werden. Direkt mit dem Applet-Client kommuniziert die Methode public void showStatus(String msg).
Diese schreibt einen Text in die Statuszeile des Browsers. Allerdings kollidiert diese Methode in einigen Situationen mit Standardausgaben vom Browser und vor allem dem Appletviewer und ist deshalb oft nicht sehr effektiv. Wenden wir diese Methoden nun in einem Beispiel an. Zuerst wird eine HTML-Datei mit Übergabe-Parametern erstellt. Listing 7.13: Die HTML-Datei mit der Applet-Referenz und Parametern
<APPLET CODEBASE = "." CODE = "UebergabeApplet.class" NAME = "TestApplet" WIDTH = 400 HEIGHT = 300 HSPACE = 0 VSPACE = 0 ALIGN = middle>
An das Applet wird ein String übergeben, der dann im Applet ausgegeben werden soll. Der zweite Übergabewert ist ein int-Wert, der intern im Applet zum Setzen der Hintergrundfarbe verwendet wird. Die paint()-Methode wird zur Ausgabe verwendet. Beachten Sie, dass wir in dem Beispiel bewusst das Schlüsselwort this einsetzen. An einigen Stellen wird es aus Demonstrationsgründen eingesetzt, um in der gleichen Situation an anderer Stelle darauf zu verzichten. Listing 7.14: Das Applet mit der Auswertung von Übergabewerten plus der Bereitstellung von Informationen gegenüber Applet-Clients
370
import java.awt.*; import java.applet.*; public class UebergabeApplet extends Applet { String meinP1; int meinP2; // Laden der Parameterwerte // Mit Test, ob der Parameter auch vorhanden ist public String getParameter(String key, String def) { return getParameter(key) != null
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7 Abbildung 7.9: Das Applet – in der Statuszeile ist die Reaktion auf die Methode showStatus() zu sehen.
? getParameter(key) : def; } //Initialisieren des Applets public void init() { meinP1 = this.getParameter("MeinPara1", "Vorbelegung"); meinP2 = Integer.parseInt(getParameter("MeinPara2", "2")); // Setze Hintergrundfarbe switch (meinP2) { case 1: this.setBackground(Color.cyan); break; case 2: this.setBackground(Color.red); break; case 3: this.setBackground(Color.yellow); break; default: this.setBackground(Color.white); } // Setze die Groesse des Applets this.setSize(new Dimension(400,300));
Java 2 Kompendium
371
Kapitel 7
Grundlagen der Applet-Erstellung } public void paint(Graphics g) { g.drawString(meinP1,50,50); g.drawString("Farbwahl war: " + new Integer(meinP2).toString(),50,150); showStatus("Das Applet wurde gestartet"); } //Die Applet-Information public String getAppletInfo() { return "Die Applet Information: (C) RJS, Version 1.0, 11/2000 "; } // Parameterinfo public String[][] getParameterInfo() { String[][] pinfo = { {"MeinPara1", "String", "Text, der ausgeben werden soll"}, {"MeinPara2", "int", "Farbwahl"}, }; return pinfo; } }
Im Appletviewer kann man über das Menü auf einfache Weise die bereitgestellten Informationen des Applets abgreifen. Abbildung 7.10: Im Appletviewer kann man auf die Methoden getAppletInfo() und getParameterInfo() zugreifen.
372
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7 Abbildung 7.11: Die Infos, die das Applet bereitstellt, im Appletviewer
7.5.3
Bilder importieren
Selbstverständlich können Applets Bilder importieren und ausgeben. Dazu können die folgenden Methoden genutzt werden: getImage() drawImage()
Die Methode public Image getImage(URL url, String name) lädt BildDateien in ein Applet. Beispiel: bild1 = getImage(getCodeBase(), "bild.gif");
Das Beispiel lädt das Bild bild.gif. In unserem Beispiel verwenden wir die Methode getCodeBase() als Argument für die Ermittelung des URLs, d.h. wir laden das Bild von der gleichen Stelle, wo sich auch die HTML-Datei befindet (gleich noch mehr dazu). Als Bild können Sie jedes der unter Java erlaubten Formate (etwa GIF oder JPEG) verwenden. Das Thema Bildverarbeitung unter Java ist natürlich mit diesem kurzen Beispiel nicht erschöpft, sondern wird im Rahmen des Kapitels über Grafik und Animation ausführlich erläutert. Dort finden Sie dann auch nähere Erklärungen zu der Methode. Hier soll nur die prinzipielle Möglichkeit eines Applets zum Laden eines Bildes angesprochen werden. Mit der Methode public abstract boolean drawImage(Image img, int x, int y, ImageObserver observer) können Sie ein geladenes Bild anzeigen. Beispiel: g.drawImage(meinBild, 50, 50, this);
Wir wollen ein kleines Applet erstellen, das ein Bild lädt und auf dem Bildschirm wieder ausgibt. Die folgende HTML-Datei dient zum Einbinden.
Java 2 Kompendium
373
Kapitel 7 Listing 7.15: Die HTML-Datei
Grundlagen der Applet-Erstellung <APPLET CODEBASE = "." CODE = "DrawImage.class" WIDTH = 400 HEIGHT = 300>
Das Applet sieht so aus: Listing 7.16: Ein Applet mit Bild-Ausgabe
import java.awt.Image; import java.awt.Graphics; public class DrawImage extends java.applet.Applet { Image samImage; public void init() { // ein Bild wird geladen samImage = getImage(getDocumentBase(), "images/baby.jpg"); resize(320, 240); // Grö ß e des Applets } public void paint(Graphics g) { // Ausgabe des Bildes g.drawImage(samImage, 0, 0, this); } }
Abbildung 7.12: Ein Bild in einem Applet
Das Beispiel setzt natürlich voraus, dass im dem Unterverzeichnis images die entsprechende Grafik vorhanden ist. In diesem Fall wird in der init()Methode die Grafik geladen und dann die Applet-Grö ß e angepaßt. Nach der Initialisierung des Applets wird als nächstes die paint()-Methode aufgerufen. Diese verwendet unsere hier besprochene Methode dann zum Anzeigen des aktuellen Bildes. Mehr dazu finden Sie beim Abschnitt über Grafiken.
374
Java 2 Kompendium
Die Applet-Klasse
7.5.4
Kapitel 7
Importieren und Abspielen von Sound
Multimedia-Eigenschaften waren ja am Anfang ein Grund für den einschlagenden Erfolg von Java beim ersten Auftauchen im Internet3. Dazu zählt natürlich ebenfalls die Akustik. Ab der Java-Version 1.2 können Sie MIDIDateien (Typ 0 und Typ 1) sowie RMF-, WAVE-, AIFF-, und AU-Dateien in hoher Tonqualität abspielen und zusammenmischen. Ein Applet kann über die Methode public AudioClip getAudioClip(URL url, String name) sowohl Audio-Clips als auch Sound-Clips importieren. Beispiel: meinSoundClip = getAudioClip(getCodeBase(), "history.wav");
Die Methoden public void play(URL url, String name) und public abstract void loop() dienen zum Abspielen und Wiederholen des Clips.
7.5.5
Die Interaktion des Applets mit der Umgebung und den Lebenszyklus eines Applets verwalten
Jedes Applet kann mit seiner Umgebung in Kontakt treten und auf sie reagieren. Dies ergibt sich in einfacher Form schon allein deshalb, weil es eine Ableitung der Klasse Applet ist. Die einfachsten (und grundlegendsten) Funktionalitäten eines Applets sind, dass es sich starten lässt und – hier kommt die Interaktion zur Laufzeit ins Spiel – vernünftig beenden lässt (es reagiert auf Schließbefehle des Fensters). Java besitzt dazu einen Mechanismus, durch den Applets in Schlüsselmomenten, in denen bestimmte Ereignisse eintreten, die Kontrolle übernehmen können. Die schon behandelten Methoden init(), start(), stop() und destroy() werden entsprechend aufgerufen, wenn das Applet geladen wird, mit der Ausführung beginnt, mit der Ausführung stoppt und zerstört wird. Wenn ein Applet zu einem dieser Schlüsselmomente etwas ausführen soll, dann müssen Sie nur die entsprechende Methode überschreiben, indem Sie Ihre eigene Implementierung davon in das Applet einbauen. Interaktionen gehen jedoch selbstverständlich noch weiter. Ein etwas komplizierteres Applet wird auf Buttons, Mausaktionen im Allgemeinen, Menübefehle und/oder Tastatureingaben reagieren. Dies ist sicher nicht überraschend. So etwas nennt man ein Programm mit einer (sinnvollen) Anwenderschnittstelle. Java stellt Ihnen Methoden zur Verfügung, die das System bei bestimmten Ereignissen aufrufen kann. Wenn Sie irgendeine Aufgabe als Reaktion auf ein Ereignis erledigen wollen, müssen Sie nur die entsprechende Methode überschreiben. 3
Mittlerweile ist das exzessive Multimedia-Bombardement per HTML-Grafiken, JavaScript, Java oder ActiveX leider nur noch als Anti-Kriterium für das Laden von Webseiten zu sehen.
Java 2 Kompendium
375
Kapitel 7
Grundlagen der Applet-Erstellung Interaktionen betreffen jedoch auch die Plattform, unter der das Applet läuft (Zugriffe auf Ressourcen, soweit dies erlaubt ist), sowie Kontakte über Netzwerkverbindungen hinweg. Interaktion ist also ein recht weit gefasster Begriff. Schauen wir uns ein paar Methoden an, mit denen ein Applet auf seine Umwelt reagiert und darauf Einfluss nimmt. Die Methode getAppletContext() Die Methode public AppletContext getAppletContext() gibt ein Objekt vom Typ AppletContext (eine Schnittstelle) zurück, das Sie dazu verwenden können, Informationen und Kontrolle über die Umgebung des Applets zu erlangen. AppletContext-Methoden ermöglichen es Ihnen, herauszufinden, welche Applets außer dem aktuellen noch auf derselben Seite laufen, Videos und Sounds zu importieren, eine andere Webseite aus dem Applet heraus zu laden, den Kontext eines anderen Applets zu importieren und dessen Methoden aufzurufen oder Meldungen an andere Applets weiterzugeben. Konkret haben Sie über ein Objekt dieses Typs folgende Methoden zur Verfügung: public public public public public public public
AudioClip getAudioClip(URL url) Image getImage(URL url) Applet getApplet(String name) Enumeration getApplets() void showDocument(URL url) void showDocument(URL url, String target) void showStatus(String status)
Schauen wir uns davon einige in der Praxis an. Das folgende Beispiel lädt aus dem Applet heraus über einen AppletContext direkt eine neue Webseite. Dazu verwenden wir die showDocument()-Methode. Beachten Sie, dass wir dieser ein URL-Objekt übergeben müssen, das wir anonym innerhalb der Parameterklammern erzeugen. Dabei müssen wir eine Ausnahmebehandlung vornehmen. Auf die näheren Details dazu gehen wir noch ein. In dem Beispiel wird die Webseite Applet2.html geladen. Listing 7.17: Laden einer neuen Webseite aus einem Applet heraus
376
import import import public
java.awt.*; java.applet.*; java.net.*; class Applet1 extends Applet {
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7
public void init() { try { getAppletContext().showDocument(new URL(getDocumentBase(),"Applet2.html")); } catch(Exception e) { System.out.println(e.toString()); } } }
Das nächste Beispiel gibt Informationen über andere in der Webseite geladenen Applets aus. In der nachfolgenden Webseite sind zwei Applets geladen. <APPLET CODEBASE = "." CODE = "UebergabeApplet.class" NAME = "TestApplet" WIDTH = 400 HEIGHT = 300 HSPACE = 0 VSPACE = 0 ALIGN = middle>
<APPLET CODEBASE = "." CODE = "Applet2.class" WIDTH = 500 HEIGHT = 200>
Listing 7.18: Eine Webseite mit zwei Applets
Das zweite Applet greift mittels der Methode getApplets() und dort via nextElement() auf das erste Applet zu und gibt Informationen darüber aus. import java.awt.*; import java.applet.*; public class Applet2 extends Applet { public void paint(Graphics g) { g.drawString(getAppletContext().getApplets(). nextElement().toString(),50,100); } }
Listing 7.19: Zugriff auf Interna des NachbarApplets in der Webseite
Die Methoden getCodeBase() und getDocumentBase() Schon an verschiedenen Stellen in diesem Kapitel ist die Methode public URL getCodeBase() verwendet worden. Damit wird der4 URL des Applets selbst zurückgegeben. Die Methode public URL getDocumentBase() funktio4
»Der« URL oder »die« URL ist wieder so ein Fachbegriff, wo sich Duden und Fachleute streiten. Ich verwende gegen die Empfehlung des Duden »der«.
Java 2 Kompendium
377
Kapitel 7
Grundlagen der Applet-Erstellung niert ähnlich, nur wird der URL des Verzeichnisses mit dem HTML-Dokument zurückgegeben. Die Methode isActive() Die Methode public boolean isActive() stellt fest, ob ein Applet aktiv ist. Sie können diese Methode zum Überprüfen des Zustands eines anderen Applets mit dem Aufruf von AppletContext.getApplets() im Kontext und durch den Aufruf von isActive() für ein bestimmtes Applet benutzen. Die Methode setStub() Sie können die Methode public final void setStub(AppletStub stub) verwenden, um eine neue AppletStub-Schnittstelle zu erstellen. Eine mögliche Verwendung ist die Implementation eines neuen Appletviewers. Normalerweise wird der AppletStub automatisch durch das System gesetzt. Wir verfolgen die Methode nicht weiter. Die Methode resize() Diese Methode werden Sie in vielen Applets entdecken. Damit kann man die Grö ß e eines Fensters und im Prinzip auch jedes Applets festlegen. Die Methode public void resize(Dimension d) bzw. public void resize(int x, int y) legt die Grö ß e eines Fenster bzw. des Anzeigebereichs des Applets fest. Dabei ist zu beachten, dass die äußeren Grö ß enangaben der HTMLDatei die angezeigte Grö ß e eines Applets beeinflussen, d.h., in einem Browser gelten die dort festgelegten Grö ß enangaben. Diese Methode kann nicht bewirken, dass ein über HTML-Grö ß enangaben festgelegtes Applet in einer Webseite innerhalb eines Browsers redimensioniert wird. Der Appletviewer hingegen reagiert dementsprechend mit einer Anpassung der Grö ß e. Sinn macht die Methode aber vor allem, wenn ein eigenständiges Folgefenster aktiviert wird.
7.5.6
Methoden zur Ereignisbehandlung in Applets
Natürlich kann ein Applet auch auf Ereignisse wie Mausbewegungen oder Tastatureingaben reagieren. Wir wollen dieses Verhalten noch im Rahmen eines Abschnittes über das prinzipielle Handling von Ereignissen in Java ausführlicher behandeln. Wir werden dort sehen, wie Java konkret auf die nachfolgenden Aktionen reagiert. Hier interessieren uns nur die Möglichkeiten und die Anwendung in einfachen Beispielen. Die meisten der nachfolgenden Methoden werden von Sun als deprecated bezeichnet. Wie aber schon verschiedentlich besprochen, müssen Sie sich bei Applets in vielen Fällen auf Java 1.0.x beschränken, was insbesondere die Verwendung des Eventmodells 1.0 erzwingt. Dieses unterscheidet sich erheblich von dem mittlerweile verwendeten Eventmodell 1.1. Die nachfol-
378
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7
genden Methoden gehören allesamt zum Eventmodell 1.0. Wir werden im Abschnitt über die beiden Eventmodelle darauf noch näher eingehen und die beiden Modelle gegenüberstellen. Mausaktionen Zu den wichtigsten Interaktionen eines Applets (und natürlich eines gewöhnlichen Programms) zählt die Reaktion auf Mausereignisse. Dabei soll hier nicht die Auswertung von Button und Menüeinträgen im Blickpunkt stehen, sondern die Reaktion auf Mausereignisse, die sich irgendwo im Bereich des Applets abspielen. Obwohl es nicht zwingend ist, beschränken wir uns auf die übliche linke Maustaste. Es gibt sechs mögliche Mausereignisse: Die Maustaste wird gedrückt. Die gedrückte Maustaste wird wieder losgelassen. Die Maus wird mit gedrückter Maustaste bewegt (Drag). Die Maus wird mit losgelassener Maustaste bewegt. Der Mauszeiger verlässt den Bereich des Applets. Der Mauszeiger kommt (wieder) in den Bereich des Applets. Für jedes Ereignis stellt Java in dem alten Eventmodell eine Methode zur Verfügung, die zur Applet-Klasse gehört. Über die Methode public boolean mouseDown(Event evt, int x, int y)
können Sie Aktionen auslösen, wenn der Benutzer eine Maustaste drückt. Dabei ist Event die Ereignisklasse, die die Informationen über das Ereignis enthält und x und y sind die Koordinaten, bei denen die Maustaste gedrückt wurde. Das Gegenstück zu der Methode mouseDown() ist die Methode public boolean mouseUp(Event event, int x, int y),
über die Sie Aktionen auslösen können, wenn der Benutzer eine Maustaste losgelassen hat. Die mouseUp()-Methode verwendet die gleichen Argumente wie mouseDown().
Java 2 Kompendium
379
Kapitel 7
Grundlagen der Applet-Erstellung Die Methode public boolean mouseEnter(Event event, int x, int y)
wird immer dann aufgerufen, wenn der Mauszeiger in den Bereich des Applets bewegt wird. Die Maustaste muss nicht extra gedrückt werden, damit die Methode aufgerufen wird. Die Methode verwendet die gleichen Argumente wie die bereits beschriebenen. Die Methode public boolean mouseExit(Event event, int x, int y)
ist das Gegenstück zu mouseEnter() und wird immer dann aufgerufen, wenn der Mauspfeil aus den Bereich des Applets bewegt wird. Die Maustaste muss nicht extra gedrückt werden und es gelten wieder die üblichen Argumente. Die Methode public boolean mouseDrag(Event event, int x, int y)
wird immer dann aufgerufen, wenn die Maus mit gedrückter Taste im Bereich des Applets bewegt wird und die Methode public boolean mouseMove(Event event, int x, int y)
wird immer dann aufgerufen, wenn die Maus bewegt wird und keine Taste gedrückt ist. Es gelten wieder die üblichen Argumente. Jedes Mal, wenn die Maustaste gedrückt wird, werden vor dem Aufrufen von mouseDown() die Methoden mouseExit() und mouseEnter() aufgerufen. Das bedeutet, dass die Methode mouseEnter() keinen Code enthalten sollte, der bei der Aktion mouseDown() schaden kann. Wir wollen zum Ende des Kapitels ein etwas komplexeres Applet zusammenbauen, das einige der bisher erarbeiteten Funktionalitäten nutzt. Es soll auf Mausaktionen reagieren, die getInfo()- und getCodeBase()-Methoden unterstützen und auf Wunsch ausgeben, Übergabeparameter verwenden, auf Arrays zugreifen, ein Bild laden und dieses dann ausgeben. Der Source wird mit Kommentaren dokumentiert, sodass er sicher verständlich bleibt. Listing 7.20: Ein Applet, das auf verschiedene Mausaktionen reagiert
380
import java.applet.*; import java.awt.*; public class AppletReaktionen extends Applet { /* Variablen zur Aufnahme von Übergabeparameter 1 – 3 */ private String m_Para1 = "";
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7
private String m_Para2 = ""; private String m_Para3 = ""; /* Die Parameternamen in der HTML-Datei. */ private final String PARAM_Para1 = "Para1"; private final String PARAM_Para2 = "Para2"; private final String PARAM_Para3 = "Para3"; /* Eine Image-Variable*/ Image samImage; /* Eine Instanz von Graphics, die für diverse Ausgabeaktionen genutzt wird. */ private Graphics ausgabe; public String getAppletInfo() { // Die Info return "Name: AppletReaktionen " + "Autor: Ralph Steyer"; } // Die Parameter-Info public String[][] getParameterInfo() { String[][] info = { { PARAM_Para1, "String", "Parameterbeschreibung für unseren ersten Übergabeparameter" }, { PARAM_Para2, "String", "Parameterbeschreibung Nummer 2" }, { PARAM_Para3, "String", "Hier kommt ein dritter Übergabeparameter" }, }; return info; } // die Initialisierung public void init() { // lokale Testvariable zum Auswerten der // Übergabeparameter String param; // Test des 1. Übergabeparameters // Wenn der Übergabeparameter vorhanden ist, // Zuweisung des 1. Übergabeparametes in die // entsprechende Variable param = getParameter(PARAM_Para1); if (param != null) m_Para1 = param; // Test des 2. Übergabeparameters // Wenn der Übergabeparameter vorhanden ist, // Zuweisung des 2. Übergabeparametes in die // entsprechende Variable param = getParameter(PARAM_Para2); if (param != null) m_Para2 = param; // Test der 3. Übergabeparameters – wie oben param = getParameter(PARAM_Para3); if (param != null) m_Para3 = param; // Laden eines Bildes samImage = getImage(getDocumentBase(), "images/ba2.jpg"); // Initialisierung der Graphic-Instanz ausgabe = getGraphics(); } public void paint(Graphics g) { /* Automatische Ausgabe des ersten Übergabeparameters */ g.drawString(m_Para1, 10, 20); /* Zeige das geladene Bild an */ Java 2 Kompendium
381
Kapitel 7
Grundlagen der Applet-Erstellung g.drawImage(samImage, 20, 50, this); } public boolean mouseDown(Event evt, int x, int y) { // Wir verwenden hier einen der Übergabeparameter // an das Applet. // Hier wird der Übergabeparameter 3 rechts oben // im Appletbereich angezeigt, wenn der Mauszeiger // gedrückt wird. ausgabe.drawString(m_Para3, 300, 10); return true; } public boolean mouseUp(Event evt, int x, int y) { // Die Parameterinfo wird eingeholt und damit ein // 2-dimensionales Zeichen-Array gefüllt. String [][] parainfo = getParameterInfo(); // Wenn der Mauszeiger gedrückt und dann wieder // losgelassen wird, wird die Appletinfo // angezeigt. ausgabe.drawString(getAppletInfo(), 5, 180); // Zusätzlich wird ein Teil der Parameterinfo // angezeigt. Es erfolgt der Zugriff auf das Feld // 3,3 ausgabe.drawString(parainfo[2][2], 5, 200); return true; } public boolean mouseDrag(Event evt, int x, int y) { // Zeige das geladene Bild an anderer Stelle // an, wenn die Maus gezogen wird. ausgabe.drawImage(samImage, 300, 20, this); return true; } public boolean mouseMove(Event evt, int x, int y) { return true; } public boolean mouseEnter(Event evt, int x, int y) { // Hier werden alle in den anderen Mausaktionen // ausgegebener Zeichenketten wieder gelöscht, // wenn der Mauszeiger wieder in den Appletbereich // kommt. ausgabe.clearRect(0, 0, 500, 500); return true; } public boolean mouseExit(Event evt, int x, int y) { // Wir verwenden hier einen der Übergabeparameter // an das Applet. // Hier wird der Übergabeparameter 2 links unten // im Appletbereich angezeigt, wenn der Mauszeiger // den Appletbereich verlässt. ausgabe.drawString(m_Para2, 20, 230); return true; } }
382
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7 Abbildung 7.13: Das Applet nach dem Start
Abbildung 7.14: Das Applet in voller Pracht. Einige der Mausaktionen wurden ausgelöst.
Java 2 Kompendium
383
Kapitel 7
Grundlagen der Applet-Erstellung Die HTML-Datei zum Einbinden sieht so aus:
Listing 7.21: Die HTML-Datei mit den ÜbergabeParametern
<APPLET CODE = "AppletReaktionen.class" WIDTH = 500 HEIGHT = 500> <param name=Para1 value="Parameter Nummer 1"> <param name=Para2 value="Hier kommt der zweite"> <param name=Para3 value="Alle guten Dinge sind 3">
Tastaturereignisse Mit Sicherheit zählen auch Tastaturereignisse zu den Grundereignissen der Interaktion zwischen einem Applet (und erst recht einer eigenständigen Applikation) und seiner Umwelt. Jedesmal, wenn ein Anwender eine Taste auf der Tastatur drückt, kann diese ein Ereignis auslösen, das das Applet auswerten kann. Dabei unterscheidet man zwischen verschiedenen Typen von Tastaturereignissen. Irgendeine Taste wird gedrückt. Die genaue Taste spielt keine Rolle. Eine bestimmte Taste wird gedrückt und ausgewertet. Eine so genannte Ergänzungstaste wird gedrückt. Dennoch haben Tastaturereignisse sicher nicht die Bedeutung wie Mausereignisse, denn das WWW arbeitet ja möglichst selten mit der Tastatur. Die Methode public boolean keyDown(Event event, int key)
wird immer dann aufgerufen, wenn eine Taste gedrückt wird. Die durch die Methode keyDown() erfassten Tastenanschläge sind Ganzzahlen und werden über den Parameter key an die Methode übergeben. Die Ganzzahlen stellen den ASCII-Wert des gedrückten Zeichens dar. Es können sämtliche Tastenanschläge ausgewertet werden, die einen ASCII-Code besitzen. Um die Ganzzahlen aus dem key-Parameter als Zeichen verwenden zu können, müssen sie per Casting in Zeichen umgewandelt werden. Die Syntax dafür ist beispielsweise einZeichen = (char)key;
384
Java 2 Kompendium
Die Applet-Klasse
Kapitel 7
Wenn Sie den Parameter key nicht auswerten wollen, heißt dies, dass eine beliebige Taste gedrückt werden kann und alleine darauf hin eine Aktion erfolgt. Wir wollen uns wieder ein einfaches Beispiel zu Gemüte führen, das über die keyDown()-Methode Tastenanschläge auswertet und im Anzeigebereich des Applets ausgibt. import java.applet.*; import java.awt.Event; import java.awt.*; public class AppletTaste extends Applet { static char taste; public void paint(Graphics g) { g.drawString(String.valueOf(taste), 50, 30); } public boolean keyDown(Event evt, int key) { taste=(char)key; repaint(); return true; } }
Listing 7.22: Das Applet wertet Tastatureingaben aus
Beachten Sie im Beispiel die Methode repaint(). Damit wird nach jeder Tastatureingabe die paint()-Methode aufgerufen. Mehr dazu bei der Behandlung der Grafikmöglichkeiten von Java. Aufgerufen wird das Applet mit <APPLET CODE = "AppletTaste.class" WIDTH = 500 HEIGHT = 500>
Listing 7.23: Die HTML-Datei zum Einbinden
Das Beispiel wird unter Umständen im Appletviewer des JDK 1.2 nicht laufen. Es gibt zwar keinerlei Fehlermeldung, aber die Anzeige der gedrückten Tasten unterbleibt seltsamerweise. Im Navigator oder Explorer gibt es keine Schwierigkeiten. Auch nicht in anderen Versionen des Appletviewers (auch die des JDK 1.3 ist okay). Standardtasten der Event-Klasse Die Event-Klasse stellt einige Klassenvariablen zur Verfügung, die einige nicht alphanumerische Standardtasten repräsentieren. Dies sind z.B. die Pfeiltasten. Diese Klassenvariablen können Sie anstelle der numerischen ASCII-Werte in der keyDown()-Methode verwenden. Damit wird eine bessere Übersichtlichkeit des Sourcecodes gewährleistet.
Java 2 Kompendium
385
Kapitel 7
Grundlagen der Applet-Erstellung Folgende Standardvariablen stehen zur Verfügung:
Tabelle 7.4: Standardtasten der Event-Klasse
Taste
Klassenvariable
Funktionstasten F1 bis F12
Event.F1 – Event.F12
Pos1
Event.home
Ende
Event.end
Bild nach oben
Event.pgup
Bild nach unten
Event.pgdn
Pfeil nach oben
Event.up
Pfeil nach unten
Event.down
Pfeil nach links
Event.left
Pfeil nach rechts
Event.right
Die Ergänzungstasten Es gibt drei wichtige Tasten, welchen kein ASCII-Code direkt zugeordnet ist, die aber für sich so wichtig sind, dass sie dennoch ausgewertet werden müssen. Es handelt sich um: die Shift-Taste die STRG oder Control-Taste die Meta-Taste Das besondere an diesen drei Tasten ist, dass sie keine Tastenereignisse auslösen, die mit der keyDown()-Methode ausgewertet werden können. In einigen Fällen ist es klar, dass die Shift-Taste gedrückt wurde, nämlich immer dann, wenn ein Großbuchstabe oder ein sonstiges oberes Zeichen der Tastatur als ASCII-Wert interpretiert werden kann. Dies ist jedoch eine implizite Vorgehensweise. Es gibt indes noch eine andere Strategie. Wenn ein gewöhnliches Tastaturoder Mausereignis eintritt, kann über zusätzliche Methoden getestet werden, ob eine der drei Tasten zusätzlich gedrückt wurde. Die Event-Klasse enthält drei Methoden, die testen, ob zusätzlich zu den gewöhnlichen Tastatur- oder Mausereignissen eine der drei Zusatztasten gedrückt wurden. Es handelt sich um die shiftDown()-, die metaDown()- und die controlDown()-Methode. 386
Java 2 Kompendium
Multithreading bei Applets
Kapitel 7
Alle drei Methoden geben boolesche Werte zurück. Sie können diese Methoden in jeder beliebigen Ereignishandlung (Tastatur- oder Mausereignis) verwenden, indem Sie sie zusätzlich zu dem Ereignis-Objekt, das an die jeweilige Methode weitergegeben wurde, aufrufen. Ein kurzes Beispiel für jede Ergänzungsmethode soll die Technik verdeutlichen: public boolean keyDown(Event event, int key) { if (event.shiftDown) ... irgendwelche Anweisungen ... else ... irgendwelche Anweisungen ... } public boolean mouseDrag(Event event, int x, int y) { if (event.metaDown) ... irgendwelche Anweisungen ... else ... irgendwelche Anweisungen ... } public boolean mouseDown(Event evt, int x, int y) { if (event.contolDown) ... irgendwelche Anweisungen ... else ... irgendwelche Anweisungen ... }
Listing 7.24: Skizzierter Einsatz der Ergänzungstasten
Die Standardmethoden zur Handhabung von Ereignissen in Applets gehören eigentlich zum AWT-Event-Handler. Mehr dazu erörtern wir im Kapitel über das AWT und das prinzipielle Eventhandling von Java.
7.6
Multithreading bei Applets
Kommen wir nun zum ersten Mal zu dem Begriff Threads innerhalb von Applets. Das Thema Multithreading in Java soll ebenfalls in einem eigenen Kapitel behandelt werden, aber an dieser Stelle soll zumindest noch die Bedeutung der run()-Methode erklärt werden. Java unterstützt Multithreading. Die genauere Erklärung von Multithreading finden Sie in Kapitel 8. Multithreading bedeutet für uns erst einmal nur, dass mehrere Aufgaben oder Prozesse quasi gleichzeitig ausgeführt werden können. Durch die Verwendung von Threads können Sie Applets so erstellen, dass diverse Prozesse in ihrem eigenen Thread laufen, ohne andere Teile des Systems zu beeinflussen. Zwar werden eventuelle Engpässe in der Kapazität des Rechners die diversen Threads unter Umständen verlangsamen, aber sie sind und bleiben unabhängig voneinander.
Java 2 Kompendium
387
Kapitel 7
Grundlagen der Applet-Erstellung Wie wird nun ein Applet Multithreading-fähig? Sie müssen im Wesentlichen vier Schritte durchführen. 1.
Erweitern Sie die Unterschrift des Applets um implements Runnable (Sie integrieren also diese Schnittstelle).
2.
Fügen Sie eine Instanzvariable ein, die den Thread des Applets enthält.
3.
Reduzieren Sie die start()-Methode so, dass sie außer dem Start des Threads (bzw. ggf. dem Erzeugen eines Thread-Objekts) keinen weiteren Aufruf enthält.
4.
Jetzt kommt eine neue Methode ins Spiel – die run()-Methode, die ab sofort den eigentlichen Code enthält, den das Applet ausführen soll. Sie ersetzt damit die start()-Methode weitgehend.
Schauen wir uns die Schritte anhand eines Beispiels an. Listing 7.25: Ein MultithreadingApplet
388
/* Datumsausgabe mit Threads*/ import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class DatumThread extends java.applet.Applet implements Runnable { Font schriftArt = new Font("TimesRoman",Font.BOLD,24); Date Datum1, Datum2; Thread MeinThread1, MeinThread2; public void start() { if (MeinThread1 == null); { MeinThread1 = new Thread(this); MeinThread1.start(); } if (MeinThread2 == null); { MeinThread2 = new Thread(this); MeinThread2.start(); } } public void stop() { if (MeinThread1 != null) { MeinThread1.stop(); MeinThread1 = null; } if (MeinThread2 != null) { MeinThread2.stop(); MeinThread2 = null; } } public void run() { while (true) { try { Datum1 = new Date(); MeinThread1.sleep(2017);
Java 2 Kompendium
Multithreading bei Applets
Kapitel 7
repaint(); } catch (InterruptedException e) { } try { Datum2 = new Date(); MeinThread2.sleep(5029); repaint(); } catch (InterruptedException e) { } } } public void paint(Graphics g) { g.setFont(schriftArt); g.drawString(Datum1.toString(),15,30); g.drawString(Datum2.toString(),15,80); } }
Wenn Sie nun das Applet mit einer einfachen HTML-Seite einbinden, können wir sehen, was es tut. <APPLET CODE = "DatumThread.class" WIDTH = 500 HEIGHT = 500>
Listing 7.26: Die HTML-Seite für das MultithreadingApplet
Das Applet gibt zweimal Datum und Uhrzeit aus. Die Threading-Eigenschaft äußert sich darin, dass die beiden Zeiten nicht identisch sind und asynchron in verschieden langen Intervallen aktualisiert werden. Das liegt daran, dass nach Erzeugung eines jeweiligen Datumsobjekts der gerade aktive Thread »schlafen geht« und deshalb bis zur Erzeugung des zweiten Datumsobjekts ein gewisses Intervall vergeht. Zudem ist der Aufruf der repaint()-Methode entsprechend damit gekoppelt, weshalb die Anzeige immer nur eine der beiden Datumsausgaben aktualisieren kann. Abbildung 7.15: Wer außer Buchautoren arbeitet schon sonntagabends so spät?
Java 2 Kompendium
389
Kapitel 7
Grundlagen der Applet-Erstellung Analysieren wir das Applet ein wenig: public class DatumThread extends java.applet.Applet implements Runnable
ist unser Schritt 1 – Implementieren der Schnittstelle Runnable. Thread MeinThread1, meinThread2;
ist der Schritt 2, das Einfügen der Instanzvariablen, die die Threads des Applets enthalten. Schritt 3 ist die start()-Methode, die eine Abprüfung auf den Thread enthält und nur wenn kein Thread vorhanden ist, einen Thread startet. Sonst tut die start()-Methode nichts. Die eigentliche Aktivität des Applets muss – wie wir in Schritt 4 festgelegt haben – innerhalb der run()-Methode stattfinden. Genau das passiert hier: Bis zum Auslösen der stop()-Methode wird eine Endlosschleife ausgeführt, die mittels der repaint()-Methode (zu dieser gleich mehr) immer wieder eine Ausgabe der aktualisierten Zeit auf dem Bildschirm erzeugt. Zu einer Behandlung von potenziellen Ausnahmen werden einige Anweisungen in einem try-catch-Block platziert.
7.7
Zusammenfassung
Applets benötigen immer einen Container, in dem sie zum Leben erweckt werden. In diesen werden sie als eine Referenz in einer HTML-Seiten geladen. Ein Java-Applet in der einfachsten Form (ohne irgendwelche Parameter und optionale Attribute) kann mit folgender HTML-Syntax in eine HTMLSeite eingebunden werden: <APPLET CODE="[classelement]" WIDTH=[Wert] HEIGHT=[Wert]>
Daneben gibt es noch diverse optionale Angaben (etwa Positionsangaben, Quelltextverweise, Parameterübergabe). Sie können ein Applet auch mit anderen HTML-Tags in eine Webseite einbinden, die aber komplizierter zu handhaben sind und durch ihre Einschränkungen auf spezielle Voraussetzungen das <APPLET>-Tag noch nicht abgelöst haben. Um ein Applet zu erstellen, müssen Sie immer eine Subklasse der Klasse Applet erzeugen. Diese Klasse beinhaltet sämtliche Eigenschaften, die die Kooperation mit dem Container sicherstellen, die Fähigkeiten des AWT für Oberflächenprogrammierung nutzbar machen und auch die lebenswichtigen Grundmethoden für ein Applet. 390
Java 2 Kompendium
Zusammenfassung
Kapitel 7
Der Einstieg in ein Applet-Leben ist die Initialisierung. Diese erfolgt immer mit der Methode init(), die automatisch aufgerufen wird, sobald das Applet in den Browser (oder einen anderen Container wie den Appletviewer) geladen wird. Die Methode start() startet das eigentliche Applet direkt nach der Initialisierung. Während die Initialisierung nur einmal erfolgt, kann (und wird normalerweise) der Start beliebig oft wiederholt werden. Die Methode stop() stoppt ein Applet, das dann mit start() wieder zu neuem Leben erweckt werden kann. Engültig zerstört wird ein Applet mit der Methode destroy(). Neben diesen Grundmethoden gibt es noch eine Vielzahl von Methoden, um die Funktion eines Applets sinnvoll zu erweitern.
Java 2 Kompendium
391
8
Multithreading
Multithreading bedeutet im Wesentlichen, dass mehrere Aufgaben oder Prozesse quasi gleichzeitig ausgeführt werden können. Einfachstes (und bestes) Beispiel für ein Multithreading-System ist ein Mensch, der viele Dinge gleichzeitig erledigt. Bei Computersystemen werden natürliche Dinge wie Multithreading zu einem großen Problem und viele ältere Betriebssysteme wie DOS waren nie in der Lage, Multithreading auch nur ansatzweise auszuführen. Auch Windows 3.x unterstützte nicht einmal echtes Multitasking, geschweige denn Multithreading. Neben den Betriebssystemen haben ebenso die Konzepte bisheriger Programmiersprachen den MultithreadingVorgang gar nicht oder nur sehr eingeschränkt integriert. Der Vorgang des Multithreading wird durch die oft verwendete Übersetzung von Threads mit »Aufgaben« ungenau beschrieben und verschleiert den Unterschied zu Multitasking, was ja streng genommen genauso bedeutet, dass mehrere Aufgaben (Tasks) gleichzeitig ausgeführt werden können. Ein Thread ist im Grunde statt mit »Aufgabe« besser (wie es auch im Wörterbuch steht) mit »Faden«, »Faser« oder am besten »Zusammenhang« zu übersetzen. Nicht die quasi gleichzeitige Ausführung von mehreren Programmen wie beim Multitasking, sondern die gleichzeitige, parallele Ausführung von mehreren einzelnen Programmschritten (oder zusammenhängenden Prozessen) ist echtes Multithreading. Dies kann ebenso bedeuten, dass innerhalb eines Programms mehrere Dinge gleichzeitig geschehen, mehrere Fäden/Fasern eines Programms synchron verfolgt und abgearbeitet werden. Bei Java ist das Multithreadingkonzept voll integrierter Bestandteil der Philosophie. Der hochentwickelte Befehlssatz in Java, um Threads zu erstellen und bei Bedarf zu synchronisieren, ist in die Sprache integriert, macht diese stabil und einfach in der Anwendung. Java verwendet hochintelligente Synchronisationsanweisung für den Umgang mit Multithreading. Die Schlüsselworte synchronized und threadsafe werden zum Markieren von Blöcken und Methoden benutzt, die eventuell vor gleichzeitiger Verwendung geschützt werden sollen.
Java 2 Kompendium
393
Kapitel 8
Multithreading Grundsätzlich sollte man das Verfahren von Multithreading nicht überschätzen. Gerade auf Singleprozessor-Rechnern und/oder Betriebssystemen, die kein echtes Multithreading unterstützen, bedeutet die Technik nur, dass Prozesse abwechselnd die so genannte Zeitscheibe des Prozessors bekommen. Echte Gleichzeitigkeit ist damit nicht möglich.
8.1
Klassen Thread-fähig machen
Es gibt zwei Wege, wie Sie Teile Ihrer Anwendungenen und Klassen in separaten Threads laufen lassen können. Einmal, indem Sie die Thread-Klasse erweitern oder indem Sie die Schnittstelle Runnable implementieren. Beide finden Sie im Paket java.lang. Damit stehen sowohl die Klasse als auch die Schnittstelle überall zur Verfügung.
8.1.1
Die Erweiterung der Klasse Thread
Sie können eine Klasse als Thread lauffähig machen, indem Sie die Klasse java.lang.Thread erweitern. Dies gibt Ihnen direkten Zugriff auf alle Thread-Methoden. Beispiel: public class MeineThreadKlasse extends Thread
In der als Thread lauffähig gemachten Klasse müssen Sie die Methode public void run()
überschreiben. Aus der so vorbereiteten Klasse erzeugen Sie dann mit einem der zahlreichen Konstruktoren (Thread(), Thread(Runnable target), Thread(Runnable target, String name), Thread(String name), Thread(ThreadGroup group, Runnable target), Thread(ThreadGroup group, Runnable target, String name), Thread(ThreadGroup group, String name)) ein
Thread-Objekt. Wir wenden verschiedene der Konstruktoren im Laufe des Kapitels an. Start von Threads Wenn Sie dann aus dieser Klasse ein Objekt erzeugen, können Sie den Thread über diese Objektrepräsentation und die Methode start() laufen lassen1. Die Methode wirft die Ausnahme vom Typ IllegalThreadStateException aus, wenn der Thread bereits läuft. 1
394
Das gilt auch für die später noch besprochene Implementation von Runnable.
Java 2 Kompendium
Klassen Thread-fähig machen
Kapitel 8
Die Methode run() sollte nie direkt aufgerufen werden. In diesem Fall wird das als normaler Methodenaufruf interpretiert und nicht als Start eines Threads. Schauen wir uns ein Beispiel an. class ErsterThread extends Thread { long erg; public void run() { while(true) { System.out.println(erg++); } } } class ZweiterThread extends Thread { long erg; public void run() { while(true) { System.out.println(erg--); } } } public class ThreadTest1 { public static void main(String args[]) { ErsterThread p = new ErsterThread(); ZweiterThread q = new ZweiterThread(); p.start(); q.start(); } }
Listing 8.1: Eine Applikation mit zwei Threads
Das Programm lässt sich nur durch die Tastenkombination STRG+C in der DOS-Box abbrechen In dem Beispiel arbeiten wir mit zwei Thread-fähig gemachten Klassen, die beide die run()-Methode überschreiben. Dort läuft jeweils eine Endlosschleife. Eine zählt eine Variable hoch und gibt sie aus, die andere zählt die Variable herunter. In der eigentlichen Applikation erzeugen wir jeweils ein Objekt und starten dann die beiden Threads. Beachten Sie, dass damit die main()-Methode beendet ist und ein nicht Multithreading-fähiges Programm unmittelbar beendet werden würde. Insbesondere würde es aber auch gar nicht zum Aufruf von q.start() kommen, denn die erste Endlosschleife würde das verhindern. So aber werden sie sehen, dass beide Threads gestartet werden und die Ausgabe zwischen positiven und negativen Zahlen hinund herwechselt (je nachdem, welcher Thread gerade die Ausgabe erzeugt). Threads abbrechen Ein Thread wird beendet, wenn das Ende seiner run()-Methode erreicht ist oder das umgebende Programm endet. Es gibt aber auch die Möglichkeit, einen Thread über einen Stopaufruf an sein Objekt zu beenden oder zumindest zu unterbrechen. Die mittlerweile
Java 2 Kompendium
395
Kapitel 8
Multithreading als deprecated geltende Methode stop() kann das tun (wenngleich mit nicht vorhersagbarem Ausführungszeitpunkt). Testen wir die Methode.
Listing 8.2: Stoppen des ersten Threads mit stop()
class DritterThread extends Thread { long erg; public void run() { while(true) { System.out.println(erg++); } } } class VierterThread extends Thread { DritterThread p = new DritterThread(); public void run() { p.start(); while(true) { if(p.erg>100) { p.stop(); break; } } } } public class ThreadTest2 { public static void main(String args[]) { VierterThread q = new VierterThread(); q.start(); } }
Das Beispiel unterscheidet sich nur auf den ersten Blick nicht sonderlich von dem ersten. Sie sind aber grundverschieden. Zwar arbeiten wir auch hier mit zwei Thread-fähigen Klassen, aber nur die erste beinhaltet eine Endlosschleife ohne interne Abbruchmöglichkeit. In der zweiten Klasse wird der Thread der ersten Klasse erzeugt und im Rahmen der run()-Methode gestartet (nicht im Hauptprogramm). Die zweite Thread-Klasse hat die Aufgabe, in einem eigenen, parallel laufenden Thread zu überwachen, wann der erste Thread abgebrochen werden soll. Im Rahmen der eigentlichen Applikation wird dann aus dieser zweiten Klasse ein Thread-Objekt erzeugt und nur dieses gestartet. Der erste Thread zählt wieder eine Variable hoch, der zweite Thread durchläuft permanent eine if-Schleife, in der kontrolliert wird, ob dieser Wert grö ß er als 100 ist. In diesem Fall wird die stop()-Methode für den ersten (!) Thread ausgelöst und mit einem break die Endlosschleife des zweiten Threads beendet. Damit endet auch automatisch seine run()Methode. Das Verfahren funktioniert soweit zuverlässig, nur wird Ihnen bei einem Test auffallen, dass die Zählvariable des ersten Threads beim Abbruch bedeutend grö ß er als 100 sein wird und vor allem, dass der Wert bei jedem Test verschieden sein wird. Wie bereits angedeutet, hat man auf diese Art und Weise keine genaue Kontrolle über den Zeitpunkt des Abbruchs. Außerdem ist unter gewissen Umständen die gesamte Technik mit der stop()-Methode unsicher. Die Methode gilt deshalb als deprecated. Dennoch – für zahlreiche Anwendungen ist diese einfache Technik immer noch sinnvoll.
396
Java 2 Kompendium
Klassen Thread-fähig machen
Kapitel 8
Es gibt aber mittlerweile eine bessere Variante, die wir in dem nachfolgenden, umgebauten Beispiel einsetzen wollen. Sie basiert auf den folgenden drei Methoden: interrupt() interrupted() isInterrupted()
Diese Technik basiert auf einem Unterbrechungsstatus, der gesetzt werden kann und dann in Form von Botschaften an einen Thread weitergereicht wird. Dieser nimmt den Status, wenn der Thread wieder vom Prozessor die Zeitscheibe bekommt, unmittelbar zur Kenntnis und man kann entsprechende Aktionen auslösen. Die Methode public void interrupt()
unterbricht den Thread, auf den sie angewendet wird. Über die Methode public static boolean interrupted()
kann man testen, ob ein aktueller Thread unterbrochen wurde (falls ja, Rückgabe true). Der Aufruf der Methode löscht den Interrupted-Status von dem Thread, sodass ein zweiter Aufruf false zurückliefern wird (es sei denn, der Thread ist zwischenzeitlich erneut unterbrochen worden). Die Methode public boolean isInterrupted()
testet ebenso, ob ein Thread unterbrochen wurde, nur wird der InterruptedStatus bei einem Aufruf unverändert gelassen. Bei allen drei Methoden sollte man beachten, dass man damit nur mit der Unterbrechung eines Threads agiert, ihn aber noch nicht explizit beendet. Darum muss man sich noch selbst kümmern. Der Unterbrechungsstatus ermöglicht jedoch auf einfache Weise, eine Abbruchanweisung im unterbrochenen Thread auszulösen, etwa wie in dem folgenden Beispiel. class FuenfterThread extends Thread { long erg; public void run() { while(true) { System.out.println(erg++); if(isInterrupted()) { System.out.println("Erster Thread unterbrochen"); break; } } } } class SechsterThread extends Thread { FuenfterThread p = new FuenfterThread();
Java 2 Kompendium
Listing 8.3: Unterbrechung von Threads
397
Kapitel 8
Multithreading public void run() { p.start(); while(true) { if(p.erg>100) { p.interrupt(); break; } } } } public class ThreadTest3 { public static void main(String args[]) { SechsterThread q = new SechsterThread(); q.start(); } }
Zwei mittlerweile als deprecated erklärte Methoden sind suspend() und resume(). Diese dienten ursprünglich dazu, einen Thread anzuhalten und wieder zu starten. suspend() versetzt einen Thread in Wartezustand, die Methode resume() kehrt zu dem schlafenden Thread zurück und aktiviert ihn wieder. Sie sollten nicht mehr verwendet werden, da damit leicht ein Deadlock erzeugt werden kann. Von Interesse ist in diesem Zusammenhang die Methode public final boolean isAlive(), womit getestet werden kann, ob ein Thread beendet wurde. Falls er noch nicht beendet wurde, wird true zurückgegeben. Eine weitere Methode zur Änderung des Laufstatus von Threads ist public void destroy(). Im Allgemeinen sollten Sie destroy() jedoch nicht anwenden, denn damit werden keine Säuberungen am Thread durchgeführt, sondern er wird lediglich zerstört. Threads schlafen legen Eine sehr interessante Methode ist sleep(), die es in zwei Versionen gibt: static void sleep(long millis) static void sleep(long millis, int nanos)
Damit kann man einen Thread für ein in Millisekunden und optional Nanosekunden angegebenes Zeitintervall »schlafen legen«. Diese Zeitangaben sind aber (gerade auf einem Singleprozessorsystem) nur sehr ungenau und können von diversen Faktoren abhängen (Betriebssystem, Hardware, parallel laufende Programme usw.). Die Methode ist eine Klassenmethode und kann deshalb auch ohne konkretes Thread-Objekt angewandt werden. Dies kann dazu verwendet werden, das Hauptprogramm (was ja selbst auch als eigener Thread zu verstehen ist) selbst eine gewisse Zeit pausieren zu lassen. Testen wir die Methode.
398
Java 2 Kompendium
Klassen Thread-fähig machen import java.util.*; class SiebterThread extends Thread { int a; public void run() { while(aListenerInterface
2.
Implementation von separaten Event-Listener-Klassen. Dies haben wir durchgesprochen. Dieses Verfahren hat aber den Nachteil, dass es unter Umständen sehr aufwändig sein kann und die Zahl der notwendigen Klassen stark erhöht.
3.
Redefinition der Event-Dispatch-Methoden (processEvent oder process<Event-Klasse>), die jedes GUI-Objekt aus dem AWT standardmäß ig besitzt.
Die dritte Variante verwendet im Gegensatz zu Variante zwei kein extra Event-Listener-Interface, erkauft sich dieses Vorgehen jedoch über den Nachteil, dass es zu den gleichen Problemen wie im Eventhandling des JDK 1.0 kommen kann. Problematisch sind beispielsweise die unübersichtlichen if-else-Konstrukte bei komplexen Applikationen. Diesen Missstand versucht das neue Framework durch eine klare Trennung der Konzepte zu beheben. Das gut gegliederte, objektorientierte Design vermeidet damit solche schwer wartbaren und fehleranfälligen Konstruktionen. Durch das Zwischenschalten der Listener erstellt man nur noch dann Subklassen von Standard-GUI-Objekten, wenn sich diese tatsächlich durch ein eigenes Verhalten auszeichnen. Ansonsten versucht man, das Erzeugen von Subklassen zur Ereignisbehandlung so weit wie möglich zu unterlassen. Das Verhalten passt damit noch besser als vorher in die objektorientierte Philosophie, wo man ja ebenfalls Verhaltensweisen soweit oben wie möglich im Vererbungsbaum ansiedeln möchte. Der Preis für diese Einfachheit ist der Aufbau von zusätzlichen Listener-Klassen. Schauen wir uns nun ein ganz einfaches Beispiel mit dem Eventhandling 1.1 unter dem Aspekt der Ereignisbehandlung an, das die gerade beschriebene Vorgehensweise demonstriert (und sicher einige der bisherigen Beispiele in dem Kapitel verständlicher macht). Eine eigenständige Java-Applikation beinhaltet einen Button. Dazu wird dann ein Action-Listener mit addActionListener(new Event1_button1_actionAdapter(this)) registriert. Die im Parameter verwendete Klasse Event1_button1_actionAdapter implemen-
616
Java 2 Kompendium
Die Eventmodelle 1.0 und 1.1
Kapitel 10
tiert java.awt.event.ActionListener. Die entsprechend festgelegte Methode button1_actionPerformed(ActionEvent e) wird bei einem Klick auf den Button ausgelöst und schließt das Programm. Wir verwenden hier also einen Standard-Adapter für das Eventhandling. import java.awt.*; import java.awt.event.*; public class Event1 extends Frame { Button button1 = new Button(); FlowLayout flowLayout1 = new FlowLayout(); public Event1() { initial(); } public static void main(String[] args) { Event1 mF = new Event1(); mF.setSize(200,100); mF.show(); } private void initial() { button1.setLabel("button1"); button1.addActionListener(new Event1_button1_actionAdapter(this)); this.setLayout(flowLayout1); this.add(button1, null); } void button1_actionPerformed(ActionEvent e) { System.exit(0); }} class Event1_button1_actionAdapter implements java.awt.event.ActionListener { Event1 adapt; Event1_button1_actionAdapter(Event1 adapt) { this.adapt = adapt; } public void actionPerformed(ActionEvent e) { adapt.button1_actionPerformed(e); }}
Listing 10.29: Ein einfaches Beispiel mit Eventhandling 1.1 und Standard-Adapter
Abschließend sei der Hinweis nachgetragen, dass sich beim Eventmodell 1.1 die Verwendung von anonymen Klassen ideal anbietet. Die Umarbeitung des gerade demonstrierten Beispiels zeigt, dass der Quelltext kompakter und besser lesbar wird. Insbesondere entfällt die Implementation der Event-Listener-Schnittstelle. Im Kapitel über Swing werden wir einige weitere Beispiele mit einem Standard-Adapter durchspielen. import java.awt.*; import java.awt.event.*; public class Event2 extends Frame { Button button1 = new Button(); FlowLayout flowLayout1 = new FlowLayout();
Java 2 Kompendium
Listing 10.30: Das gleiche Beispiel mit Eventhandling 1.1 und anonymem Adapter
617
Kapitel 10
Das AWT public Event2() { initial(); } public static void main(String[] args) { Event2 mF = new Event2(); mF.setSize(200,100); mF.show(); } private void initial() { button1.setLabel("button1"); button1.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { button1_actionPerformed(e);}}); this.setLayout(flowLayout1); this.add(button1, null); } void button1_actionPerformed(ActionEvent e) { System.exit(0); }}
10.14.6
Der Umstieg vom 1.0-Eventmodell auf das 1.1-Modell
Obwohl seit der Einführung des Eventmodells 1.1 viel Wasser den Bach heruntergeflossen ist, gibt es – aus mehrfach erwähnten Gründen – noch zahlreiche Projekte, die auf dem alten Eventhandling beruhen. Falls diese auf das 1.1-Modell umgestellt werden sollen, steht eine Menge Arbeit bevor. Zur Erleichterung des Umstiegs vom 1.0-Eventmodell auf das 1.1Modell folgt in diesem Abschnitt eine Event-Konvertierungstabelle. Dabei werden die 1.0-Events ihren 1.1-Partnern gegenübergestellt. Die erste Spalte listet jeden 1.0-Eventtyp mit dem Namen der Methode (falls vorhanden) auf, die dem Ereignis zugeordnet ist. Wo keine Methode angegeben ist, wird das Ereignis immer in der handleEvent()-Methode behandelt. Die zweite Spalte listet die 1.0-Komponenten auf, die den angegebenen Ereignistyp generieren können. Die dritte Spalte gibt das Listener-Interface zum Auffinden des 1.1-Äquivalents der aufgelisteten Ereignisse an. Die vierte Spalte gibt die Methoden in jedem Listener-Interface an. Tabelle 10.14: Gegenüberstellung der 1.0- und 1.1Modelle für den Umstieg
618
Modell 1.0
Modell 1.1
Event/Methode
Generiert von
Listener-Interface Methoden
ACTION_EVENT/ action
Button, List, MenuItem, TextField
ActionListener
actionPerformed (ActionEvent)
Java 2 Kompendium
Die Eventmodelle 1.0 und 1.1
Modell 1.0
WINDOW_DESTROY WINDOW_EXPOSE WINDOW_ICONIFY WINDOW_DEICONIFY
Kapitel 10
Modell 1.1 Checkbox, CheckboxMenuItem, Choice
ItemListener
itemStateChanged (ItemEvent)
Dialog, Frame
WindowListener
windowClosing (WindowEvent) windowOpened (WindowEvent) windowIconified (WindowEvent) windowDeiconified (WindowEvent) windowClosed (WindowEvent) (kein
Äquvivalent in der Version 1.0) windowActivated (WindowEvent) (kein
Äquvivalent in der Version 1.0) windowDeactivated(WindowEvent) (kein
Äquvivalent in der Version 1.0) WINDOW_MOVED
Dialog, Frame
ComponentListener componentMoved (ComponentEvent) componentHidden (ComponentEvent) (kein
Äquvivalent in der Version 1.0) componentResized (ComponentEvent) (kein
Äquvivalent in der Version 1.0) componentShown (ComponentEvent) (kein
Äquvivalent in der Version 1.0) SCROLL_LINE_UP SCROLL_LINE_DOWN SCROLL_PAGE_UP SCROLL_PAGE_DOWN SCROLL_ABSOLUTE SCROLL_BEGIN SCROLL_END
Java 2 Kompendium
Scrollbar
AdjustmentListener adjustmentValueChanged
(alternativ kann (AdjustmentEvent) die neue ScrollPaneKlasse verwendet werden)
619
Kapitel 10
Das AWT
Modell 1.0
Modell 1.1
LIST_SELECT LIST_DESELECT
Checkbox, CheckboxMenuItem, Choice, List
ItemListener
itemStateChanged (ItemEvent)
MOUSE_DRAG/ mouseDrag MOUSE_MOVE/ mouseMove
Canvas, Dialog, Frame, Panel, Window
MouseMotionListener
mouseDragged (MouseEvent) mouseMoved(MouseEvent)
MOUSE_DOWN/ mouseDown MOUSE_UP/mouseUp MOUSE_ENTER/ mouseEnter MOUSE_EXIT/ mouseExit
Canvas, Dialog, Frame, Panel, Window
MouseListener
mousePressed (MouseEvent) mouseReleased (MouseEvent) mouseEntered (MouseEvent) mouseExited (MouseEvent) mouseClicked (MouseEvent) (kein
Äquvivalent in der Version 1.0)
620
KEY_PRESS/ keyDown KEY_RELEASE/ keyUp KEY_ACTION/ keyDown KEY_ACTION_RELEA SE/keyUp
Component
GOT_FOCUS/ gotFocus LOST_FOCUS/ lostFocus
Component
KeyListener
keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent)
(kein Äquvivalent in der Version 1.0)
FocusListener
focusGained (FocusEvent) focusLost(FocusEvent)
Kein Äquvivalent in der Version 1.0.
ContainerListener
componentAdded (ContainerEvent) componentRemoved (ContainerEvent)
Kein Äquvivalent in der Version 1.0.
TextListener
textValueChanged (TextEvent)
Java 2 Kompendium
Zusammenfassung
10.15
Kapitel 10
Zusammenfassung
Die Kommunikation mit dem Anwender wird in Java hauptsächlich über das AWT (bzw. das im nächsten Kapitel beschriebene, darauf aufbauende Swing-Konzept) realisiert. Das AWT beinhaltet zur Kommunikation mit dem Anwender im Wesentlichen ein API, über die allgemeine Komponenten der Anwenderschnittstelle wie Buttons oder Menüs plattformunabhängig genutzt werden können. Die von Anfang an vorhandenen Komponenten des AWT sind folgende: Schaltflächen (Buttons) Label Kontrollkästchen (Checkbuttons) Optionsfelder (Radiobuttons) Listen Auswahlfelder Textfelder Textbereiche Menüs Zeichenbereiche Bildlaufleisten Komponenten werden in Java in Containern organisiert, wo sie gemeinsam verwaltet werden. Die Komponenten werden mittels der Container in verwaltbaren Gruppen organisiert. In Java können nur dann die Komponenten im AWT verwendet werden, wenn diese dann auch in einem Container enthalten sind. Die Container im AWT sind: Fenster (Windows) Panels Frames Dialoge Die Applet-Klasse ist eine Unterklasse der Panel-Klasse. Insbesondere stellt bei Applets der Browser eine Umgebung für das AWT (und Grafik) bereit. Ein bedeutender Bestandteil des AWT ist die Technik der Layoutmanager, die das Layout der Oberfläche regeln. Unter Java werden Sie im Allgemeinen nicht mehr genau angeben, wo eine hinzugefügte Komponente in einem Container platziert werden soll. Die genaue Platzierung regeln die Layout-
Java 2 Kompendium
621
Kapitel 10
Das AWT manager. Sie weisen das AWT darüber nur noch an, wo Ihre Komponenten im Verhältnis zu den anderen Komponenten stehen sollen. Der Layoutmanager findet – angepasst an die jeweilige Situation – automatisch heraus, an welche Stelle die Komponenten am besten passen. Das AWT stellt fünf verschiedene Typen von Layoutmanagern zur Verfügung: FlowLayout BorderLayout GridLayout CardLayout GridBagLayout Das Eventhandling muss in Java zweigleisig betrachtet werden. Java und das JDK bieten zwei verschiedene Modelle, wie auf Ereignisse zu reagieren ist. Das Eventhandling hat sich im Wechsel von der Version 1.0 auf die JDK-Version 1.1 total verändert. Allerdings besitzen beide Ereignisbehandlungskonzepte noch ihre Existenzberechtigung. Sun rät explizit, die beiden Modelle nicht in einem Programm zu mischen. Zusammenfassend kann man sagen, dass das neue Eventmodell den wesentlichen Vorteil bietet, dass die gleiche Architektur sowohl in der GUI-Programmierung als auch im Rahmen des neuen Komponentenmodells, JavaBeans, anwendbar ist. Die Entwickler müssen nur ein Framework lernen, das sich allerdings von der Logik des vorher praktizierten Modells unterscheidet. Außerdem wird die gesamte Programmstruktur einfacher, übersichtlicher, stabiler und in einigen Fällen schneller. Wo aber viel Licht ist, ist auch Schatten. Durch die neue Logik in dem Eventmodell werden die unter 1.0 entwickelten Projekte nur mit erheblichem Aufwand auf das veränderte Eventmodell zu portieren sein. Zwar verspricht Sun, dass dies einfach und ohne Probleme zu bewerkstelligen ist, aber für komplexe Anwendungen wird es – entgegen der Marktingbeteuerungen – ein kaum zu realisierender Aufwand sein. Nicht umsonst wird das alte Eventhandling auch unter Java 1.1 und 1.2 weiter unterstützt (wenn auch bei der Kompilierung die Meldungen auftauchen, man würde deprecated-Elemente verwenden). Und man sollte ebenfalls beachten, dass gerade bei Applets das neue Eventmodell erhebliche Probleme bereiten kann.
622
Java 2 Kompendium
11
Swing & Co
Nachdem wir im vorherigen Kapitel das AWT und grundsätzlich das Eventhandling unter Java diskutiert haben, wollen wir in diesem Kapitel Swing und die neueren Oberflächentechniken von Java allgemein (JFC) ansprechen. Swing ist ein praktisches Beispiel eines Konzepts, das massiv auf dem Eventmodell 1.1 aufbaut und eine wesentliche Erweiterung des AWTModells darstellt. Wohlbemerkt, eine Erweiterung. Die bisherigen AWTTechniken lassen sich in Java immer anwenden und im Prinzip auch mit Swing-Elementen mischen, was aber nicht sonderlich sinnvoll ist. Swing implementiert einen neuen Satz von GUI-Komponenten mit anpassungsfähigem Look and Feel. Swing ist vollständig in 100 % purem Java implementiert und basiert auf dem JDK 1.1 Lightweight UI Framework. Lightweight bedeutet, dass keine Peer-Klassen mehr benötigt werden. Das Aussehen und die Reaktionen von GUI-Komponenten passen sich auf Wunsch automatisch an jede unterstützte Betriebssystemplattform (Windows, Solaris, Macintosh) an. Sie schwingen – daher der Name Swing – sozusagen zwischen den verschiedenen Welten hin und her (wenn Sie es wollen). Um dies zu realisieren, gibt es in Swing den UIManager mit Methoden wie setLookAndFeel() oder getSystemLookAndFeelClassName(). Swing-Komponenten beinhalten vollständig die bisherigen AWT-Komponenten (Button, Scrollbar, Label usw.), plus einen Satz von Higher-LevelKomponenten (Baumansichten, Listboxen usw.). Das Kapitel baut auf dem AWT-Kapitel auf und verzichtet deshalb auf einige Erklärungen, die dort bereits erfolgt sind.
11.1
Das Swing-API
Java 1.1 hat Swing das erste Mal eingeführt, aber Swing ist nicht gleich Swing. Die Swing-API-Referenz hat sich über die Entwicklung des Konzepts bis zu der Finalversion 1.2 des JDK erheblich verändert (danach ist es nur noch erweitert worden). Das gesamte API ist beim Wechsel von Java 1.1 zu Java 2 umstrukturiert und verlagert worden. Leider ist diese Umstrukturierung ziemlich chaotisch und schlecht dokumentiert erfolgt. Selbst die Beta3-Version des JDK 1.2 hatte Swing noch so organisiert, wie es unter dem JDK 1.1 üblich war. Erst die kaum beachtete – letzte – Betaversion des Java 2 Kompendium
623
Kapitel 11
Swing & Co JDK 1.2 veränderte dann die Struktur, was in der Entwicklerschaft zu ziemlichem Ungemach führte. Ab Java 2 befindet sich die gesamte Swing-Funktionalität in dem Hauptpaket javax. Swing besteht aus folgenden Paketen: javax.swing javax.swing.border javax.swing.colorchooser javax.swing.event javax.swing.filechooser javax.swing.plaf javax.swing.plaf.basic javax.swing.plaf.metal javax.swing.plaf.multi javax.swing.table javax.swing.text javax.swing.text.html javax.swing.text.html.parser javax.swing.text.rtf javax.swing.tree javax.swing.undo
Eine umfangreichere Dokumentation des Swing-API finden Sie im Anhang.
11.2
Swing und AWT im Vergleich
Um es noch einmal zu betonen: Swing ist eine Erweiterung des AWTs. Das bedeutet, viele bisherige Klassen, Methoden und Techniken sind unter Swing verbessert und erweitert worden. Dabei wurde bei Methoden vielfach der Name beibehalten (wenn die Methode in einer neuen Klasse verwendet wird) und/oder nur eine neue Methodenunterschrift eingeführt (Stichwort Polymorphismus). Bei einigen Klassen wurde nur ein neuer Konstruktor eingeführt. Im Allgemeinen wurden neue Klassen eingeführt, die bisherige Techniken unter dem gleichen Namen bereitstellen und/oder Techniken einführen, deren Bezeichner aus dem Vorgänger herleitbar ist. So basieren viele Swing-Klassen auf den gleichen Superklassen wie AWT-Klassen. Beispielsweise ist die Swing-Klasse JToolBar ein direkter Nachkomme von Container. Viele Swing-Klassen sind auch direkt aus alten AWT-Klassen abgeleitet. Diese direkte oder indirekte Verwandtschaft dokumentiert sich oft im Namen. Viele Klassen bekommen bei verwandter Funktionalität einfach ein J vorangestellt. Aus Button unter dem AWT wird JButton, aus TextField JTextField, aus Lable JLable usw. Sie werden sich vielleicht wundern, dass das Swing-Kapitel im Verhältnis zur Behandlung des konventionellen AWTs kürzer ist. Und das, obwohl das Swing-API erheblich umfangreicher als das AWT-API ist. Um es etwas drastisch zu formulieren – wenn man alle Details zu Swing behandeln wollte,
624
Java 2 Kompendium
Swing und AWT im Vergleich
Kapitel 11
könnte das gesamte Buch damit gefüllt werden. Das ist aber weder sinnvoll noch notwendig. Viele Details würden sich wiederholen, sodass wir uns hier auf eine Auswahl von wesentlichen Elementen beschränken. Entscheidend ist dabei auch, dass man bei Swing sämtliche Erkenntnisse aus den bisherigen Abhandlungen über das AWT (GUI-Gestaltung verbunden mit dem neuen Eventhandling) schlicht zusammenbringen muss und einfach übertragen kann. Wenn man konkret unter dem Swingkonzept programmieren möchte, ordnet man seine UI-Elemente wie gehabt auf einem Panel (unter Swing aus der Klasse JPanel erstellt) oder in einem auf Swing basierenden Applet an (Klasse JApplet als Superklasse). Das Swing-JPanel entspricht weitgehend dem bekannten Panel, benutzt aber wie alle Swing-Elemente keine Peer-Klasse. Außerdem werden quasi von Hause aus diverse Techniken unterstützt, die man unter dem AWT bzw. konventionellem Java »von Hand« selbst programmieren muss. Dazu zählt z.B. die Technik des Double Buffering, um das Flackern des Bildschirms zu verringern (Defaulteinstellung, die mit der Methode setBuffered(boolean)verändert werden kann). Die meisten Swing-Klassen – etwa JMenuBar, JMenu oder JmenuItem – sind mit den Menüklassen des konventionellen AWTs eng verwandt. Die Klasse JFrame besitzt beispielsweise als direkter Nachkomme von java.awt.Frame auch sämtliche der dort besprochenen Methoden und Eigenschaften, aber natürlich auch zahlreiche Erweiterungen. Zwar lassen sich durchaus Details finden, wo Vorgänge geringfügig verändert wurden. Prinzipiell gilt aber das, was auch in der Fahrschule gilt: Wenn man mit einem bestimmten Auto den Führerschein gemacht hat, kann man mit etwas Umgewöhnung jeden anderen Wagen fahren. Wir sprechen einmal eine exemplarische Erstellung einer Swing-Oberfläche durch. 1.
Als ersten Schritt sollten Sie, wenn Sie nicht im Quelltext jedes Mal voll qualifizierte Angaben machen wollen, neben den bisher üblichen Paketen noch javax.swing.* und die sonst aus dem Swing-Konzept verwendeten Pakete am Anfang importieren. Vergessen Sie dabei nicht die Klasse java.awt.event.*, wenn Sie die darauf basierenden Reaktionen behandeln wollen.
2.
Danach verwenden Sie einfach Swing-Komponenten statt der bisherigen Komponenten, um die Oberfläche zu gestalten, also etwa JPanel, JMenuBar, JMenu, JMenuItem, JButton usw.
3.
Die Verwendung des new-Operators erfolgt wie gehabt. Die Anordung auf dem JPanel funktioniert ähnlich wie bisher. Sie ist nur in einigen Details erweitert worden, die aber überwiegend auch im AWT schon möglich sind (dort gibt es aber noch viele Techniken, die explizit unter Swing so nicht mehr funktionieren). Swing stellt einige neuen Methoden und Layoutmanager bereit, die die Anordnung und das Aussehen erweitern. Dort steckt eine wesentliche Erweiterung der Gestaltungsmöglichkeiten. So erfolgt die Platzierung von Komponenten auf einem
Java 2 Kompendium
625
Kapitel 11
Swing & Co Container immer noch über die add()-Methode (wobei die ganz alte Variante mit nur einem Parameter unter Swing keine Verwendung mehr findet). Sie sollten allerdings bei sämtlichen Aktionen, die das Layout einer Oberfläche berühren, die dem Panel zugrundeliegende Gestaltung abfragen. Mit der Methode public Container getContentPane() bekommen Sie als Rückgabewert Informationen über das zugrunde liegende Layoutkonzept. Sie können, da ein Objekt vom Typ JRootPane zurückgegeben wird, direkt die add()-Methode auf die Methode per Punktnotation anwenden: getContentPane().add(). In der Dokumentation des jeweiligen Containers finden Sie die Details, auf die Sie achten müssen. 4.
Die Erstellung von Funktionalitäten in Form von eigenen Klassen und Methoden ist im Grundsatz identisch (außer, dass Sie mehr Möglichkeiten als bisher haben).
5.
Das Eventhandling muss unter Swing immer auf dem 1.1-Modell aufgebaut werden. Dazu gilt es, die passenden Listener-Klassen zu entwerfen und das zugehörige Eventhandling zu erstellen.
Das war es eigentlich. Nur sollte beachtet werden, dass die Swing-Komponenten oft zahlreiche Eigenschaften und Ereignisbehandlungsmethoden beinhalten, die wir aus oben genannten Gründen nicht vollständig durchsprechen. Die API-Dokumentation gibt aber bei Bedarf dazu mehr Informationen. Die Aussagen zu Swing lassen sich auch auf andere neue Techniken und Methoden übertragen. Es wird jeoch sehr oft vorkommen, dass Sie eine als deprecated gekennzeichnete Methode verwenden, denn diese Veränderungen sind fließend und finden ständig statt. Jede (Zwischen-)-Version von Java wird einige Methoden leicht verändern und den Vorgänger als deprecated kennzeichnen, ihn gleichwohl weiter unterstützen. Wenn Sie eine als deprecated gekennzeichnete Methode verwenden, können Sie in der aktuellsten Java-Dokumentation die Methode oder neue Variante der Methode nachschlagen, die statt dessen verwendet werden soll. Ob Sie diese dann verwenden oder nicht, hängt davon ab, ob Sie eine möglichst große Zielgruppe erreichen wollen oder eine leistungsfähigere und meist stabilere Variante vorziehen. Um aber nicht falsch verstanden zu werden – wenn kein entscheidendes Argument dagegen spricht, ist natürlich die neuere Lösung vorzuziehen.
11.2.1
Einige Swing-Probleme
Swing erweitert wie gesagt das AWT erheblich. Die Verwendung von Swing beinhaltet aber auch einige Probleme. Dies betrifft insbesondere die Performance und den Ressourcenbedarf. Swing-Applikationen sind in der Regel langsamer als vergleichbare Anwendungen, die auf dem reinen AWT basie-
626
Java 2 Kompendium
Swing in der Praxis
Kapitel 11
ren. Sie benötigen auch mehr Ressourcen in Hinblick auf den Prozessor und dem Hauptspeicher. Dazu kommen Berichte vergangener Java-Versionen, dass Swing-Appliaktionen die Speicherbereinigung durch den Garbage Collector nicht korrekt befolgt haben. Und nicht zuletzt sollten für Applets die im Buch schon mehrfach beschriebenen Probleme mit Java-Techniken jenseits vom JDK 1.0.2 beachtet werden.
11.3
Swing in der Praxis
Lassen Sie uns einige Swing-Beispiele durchspielen, um die Swing-Philosophie in der Praxis zu sehen. Dabei werden wir die im AWT-Kapitel behandelten Elemente direkt einsetzen.
11.3.1
Umschalten von Look and Feel
Um das Look and Feel von Swing-Applikationen zur Laufzeit umzuschalten, muss man einfach die setLookAndFeel()-Methode verwenden, wie wir es in dem folgenden Beispiel tun. Darüber wird der UIMangager (eine Klasse zum Anpassen des Look and Feel) angewiesen, das Look and Feel entsprechend der der Methode übergebenen Parameter umzuschalten. WindowsAnwender können beispielsweise zwischen Motif, dem Windows-Standard und Metal wählen. Dabei sollte man unbedingt beachten, dass das Wechseln eines Look and Feel einige Exceptions auslösen kann. Wir fangen diese im nachfolgenden Beispiel ab. Das Beispiel beinhaltet nur drei Button, die das Look and Feel jeweils auswählen und dann setzen. Beachten Sie, dass das Programm auf Befehlszeilenebene beendet werden muss. import java.awt.event.*;
import javax.swing.*; public class LookAndFeel extends JFrame implements ActionListener { public LookAndFeel() { super(); JPanel jBPanel = new JPanel(); JButton jB1 = new JButton("Metal"); jB1.addActionListener(this); jBPanel.add(jB1); JButton jB2 = new JButton("Motif"); jB2.addActionListener(this); jBPanel.add(jB2); JButton jB3 = new JButton("Windows"); jB3.addActionListener(this); jBPanel.add(jB3); getContentPane().add("South", jBPanel); } public void actionPerformed(ActionEvent event) { String cmd = event.getActionCommand();
Java 2 Kompendium
Listing 11.1: Dynamisches Umschalten des Look and Feel
627
Kapitel 11
Swing & Co try { // Look and Feel auswählen String laf = "unknown"; if (cmd.equals("Metal")) { laf = "javax.swing.plaf.metal.MetalLookAndFeel"; } else if (cmd.equals("Motif")) { laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; } else if (cmd.equals("Windows")) { laf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; } //Look and Feel umschalten UIManager.setLookAndFeel(laf); SwingUtilities.updateComponentTreeUI(this); } catch (UnsupportedLookAndFeelException e) { System.err.println(e.toString()); } catch (ClassNotFoundException e) { System.err.println(e.toString()); } catch (InstantiationException e) { System.err.println(e.toString()); } catch (IllegalAccessException e) { System.err.println(e.toString()); } } public static void main(String[] args) { LookAndFeel frame = new LookAndFeel(); frame.setLocation(100, 100); frame.pack(); frame.setVisible(true); }}
Abbildung 11.1: Metal-Look
Abbildung 11.2: Motif-Look
Abbildung 11.3: Windows-Look
628
Java 2 Kompendium
Swing in der Praxis
Kapitel 11
Mehr zu den Hintergründen, insbesondere zu Events, folgt im Laufe des Kapitels. Ansonsten wollen wir aber auf das dynamische Umschalten des Look and Feel im Folgenden meist verzichten.
11.3.2
Swing und Applets
Swing lässt sich im Prinzip leicht in Verbindung mit Applets realisieren. Als Erstes wollen wir ein ganz einfaches Applet nach dem Swing-Konzept erstellen, das nur ein paar Komponenten auf der Oberfläche anordnet (ohne Eventhandling). Dabei wird die Java-Syntax kaum Probleme bereiten. Sie kennen alle Komponenten – es ist immer nur ein vorangestelltes J zu dem bisherigen Fall verschieden. Beachten Sie, dass die grundsätzlichen Tools (Layoutmanager, Konstruktoren usw.) so gut wie identisch zu dem konventionellen Fall sind. Wichtigster Unterschied bei dem Beispiel ist, dass die Oberfläche betreffende Aktionen über die Methode getContentPane() »abgefedert« werden, damit das Layout sich auf die spezifisichen Bedingungen der Plattform einstellen kann. Das Beispiel wird dennoch Probleme machen, die von ganz anderer Seite herrühren. import java.awt.*;
import java.awt.event.*; import java.applet.*; import javax.swing.*; public class SwingApplet1 extends JApplet { JButton button1; JButton button2; JCheckBox Klick1; JLabel meinLabel; public void init() { getContentPane().setLayout(new FlowLayout()); button1 = new JButton("Ja"); button2 = new JButton("Nein"); Klick1 = new JCheckBox("Selektier mich"); meinLabel = new JLabel( "Ein einfaches Applet nach dem Swingkonzept"); getContentPane().add(button1); getContentPane().add(button2); getContentPane().add(Klick1); getContentPane().add(meinLabel); } }
Listing 11.2: Ein einfaches Swing-Applet
Sie benötigen zur Referenzierung eine übliche HTML-Datei mit dem <APPLET>-Tag, also eine Datei der folgenden Form:
<APPLET CODE = "SwingApplet1.class" WIDTH = 300 HEIGHT = 200>
Java 2 Kompendium
Listing 11.3: Eine Applet-Referenz für das SwingApplet
629
Kapitel 11
Swing & Co
Abbildung 11.4: Das einfache Swing-Applet im Appletviewer
Das Beispiel ist wirklich einfach und enthält nichts, was so auf den ersten Blick Probleme machen könnte. Oder doch? Dann laden Sie das Applet doch einmal in den Netscape Navigator 4.7 (ein wirklich nicht sonderlich alter Browser). Der Browser meldet einen Fehler. Abbildung 11.5: Probleme mit dem Swing-Applet im Navigator 4.7
Erst der Navigator 6.0 kommt mit dem Swing-Applet zurecht. Ebenso hat der Opera 5 keine Probleme. Das Problem tritt aber auch im Internet Explorer (selbst in der Version 5.5) auf. Dieser kommt erst dann mit dem Applet zurecht, wenn die – sehr kritische1 – Referenzierung über das -Tag erfolgt. Für den Navigator 4.7 referenziert man mit dem <EMBED>-Tag und verschachtelt die HTML-Datei so, dass jeder Browser automatisch seinen richtigen Tag auswählt. Die Referenzierung sieht dann so aus: Listing 11.4: Viel Aufwand für eine einfache Applet-Referenz
1
630
unverhältnismäß g langer Download des Plug-Ins, wenn es noch nicht vorhanden ist, Sicherheitsbedenken gegen ActiveX-Technologie, relativ komplexe Referenzierung
Java 2 Kompendium
Swing in der Praxis
Kapitel 11 Abbildung 11.6: Keine Probleme mehr im Navigator 6
<EMBED type="application/x-java-applet;version=1.3" CODE = "SwingApplet1.class" WIDTH = 300 HEIGHT = 200 scriptable=false pluginspage="http://java.sun.com/products/plugin/1.3/plugininstall.html">
Der in Kapitel 1 bzw. Kapitel 3 (JDK-Tools) besprochene HTML-Konverter von Sun hilft erheblich bei der Konvertierung von einer Applet-Referenzierung mit <APPLET> zu einer -Referenzierung. Diese Probleme bei der Verwendung von Java-Techniken, die jenseits von Java 1.0.2 anzusiedeln sind, macht in Verbindung mit Applets umfangreiche Tests in verschiedenen Browsern notwendig. Oder Sie müssen in den (sehr) sauren Apfel beißen und das - bzw. <EMBED>-Tag verwenden. Swing-Applet-Beispiel mit Interaktion durch Buttons und Radiobuttons Kommen wir aber zu einem etwas komplexeren Applet, mit dem wir auch das Eventhandling unter Swing demonstrieren wollen. Das Applet fügt wieJava 2 Kompendium
631
Kapitel 11
Swing & Co der einige Swing-Komponenten in eine Oberfläche ein und reagiert auf Interaktionen durch den Anwender (JButton und JRadioButton). Dabei werden wir hier ausnahmsweise mit Standard-Adaptern arbeiten. Wir beschränken uns auf Anklicken mit der Maus, aber das Verfahren ist allgemeingültig. Grundsätzlich werden wir uns in dem Kapitel meist auf die Standardereignisse der Swing-Komponenten beschränken. Die verschiedenen Komponenten besitzten meist jedoch zahlreiche mögliche Ereignisse, die bei Bedarf registriert und dann überschrieben werden können. Diese finden Sie allesamt in der API-Dokumentation beschrieben.
Listing 11.5: Ein Swing-Applet mit Eventhandling – Standard-Adapter
632
import javax.swing.*;
import java.awt.*; public class SwingApplet2 extends JApplet { // DEKLARIEREN der CONTROLS JButton jB1 = new JButton(); JButton jB2 = new JButton(); JRadioButton jRB1 = new JRadioButton(); JRadioButton jRB2 = new JRadioButton(); public void init() { // Layout setzen getContentPane().setLayout(new FlowLayout()); // Die nachfolgende Zeile ist reine // Vorsichtsmaßnahme. // Sie unterbindet die Meldung // "Swing: checked access to system event queue", // die bei gewissen Swing-Akionen in einige // Browsern erzeugt wird. getRootPane().putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE); // INIT_CONTROLS // Hintergrundfarbe setzen getContentPane().setBackground(java.awt.Color.red); // Grö ß e Applet setSize(450,275); // Belegen der CONTROLS mit Werten // danach hinzufügen. jB1.setText("Mache Gross"); getContentPane().add(jB1); jB2.setText("Mache klein"); getContentPane().add(jB2); jRB1.setText("Rot"); jRB1.setSelected(true); // vorselektiert getContentPane().add(jRB1); jRB2.setText("Blau"); getContentPane().add(jRB2); // REGISTIEREN und EINRICHTEN der LISTENER // Erster Schritt: Erzeugen eines Objekts der // Klasse, wo die Auswertung der Events erfolgt.
Java 2 Kompendium
Swing in der Praxis
Kapitel 11
MausReak meineMaus = new MausReak(); // Registrieren der Listener // – hier nur Mauslistener jB1.addMouseListener(meineMaus); jB2.addMouseListener(meineMaus); jRB1.addMouseListener(meineMaus); jRB2.addMouseListener(meineMaus); } // Klasse zum Auswerten der Reaktionen class MausReak extends java.awt.event.MouseAdapter { // Die Methode ruft je nach angeklicktem Control // die entsprechende zu behandelnde Methode auf. public void mouseClicked(java.awt.event.MouseEvent event) { Object object = event.getSource(); if (object == jB1) jB1_mouseClicked(event); else if (object == jB2) jB2_mouseClicked(event); else if (object == jRB1) jRB1_mouseClicked(event); else if (object == jRB2) jRB2_mouseClicked(event); } } void jB1_mouseClicked(java.awt.event.MouseEvent event) { // vergrössere this.setSize(600,400); } void jB2_mouseClicked(java.awt.event.MouseEvent event) { // klein this.setSize(200,100); } void jRB1_mouseClicked(java.awt.event.MouseEvent event) { // Setze Hintergrundfarbe des Applets auf rot. // Beachten Sie, dass der andere Radiobutton // explizit auf false gesetzt werden muss. getContentPane().setBackground(java.awt.Color.red); jRB2.setSelected(false); } void jRB2_mouseClicked(java.awt.event.MouseEvent event) { // Setze Hintergrundfarbe des Applets auf blau. // Beachten Sie, dass der andere Radiobutton // explizit auf false gesetzt werden muss. getContentPane().setBackground(java.awt.Color.blue); jRB1.setSelected(false); } }
Das Beispiel vergrö ß ert das Applet jeweils bei Klick auf den entsprechenden Button bzw. verkleinert es wieder (nur im Appletviewer!). Die Radiobuttons wechseln die Hintergrundfarben des Applets. Beachten Sie die Kommentare im Quelltext, die die entscheidenden Stellen erklären.
Java 2 Kompendium
633
Kapitel 11
Swing & Co
Abbildung 11.7: Groß und rot
Abbildung 11.8: Klein und blau
Swing-Textfelder und absolute Positionierung Sie können unter Swing auch dafür sorgen, dass Komponenten auf der Oberfläche absolut positioniert und in der Grö ß e festgelegt werden. Dafür gibt es die Methode public void setBounds(int x, int y, int breite, int hoehe) aus der Klasse java.awt.Component, die über die Angabe der linken oberen Ecke einer Komponente und seiner Breite/Höhe dafür sorgen. Wir werden dies in dem nächsten Beispiel, wo wir den Quelltext von eben erweitern wollen, anwenden. Aber Vorsicht, solche absoluten Angaben hebeln einen zentralen Vorteil von Java wieder aus: die Anpassung an äußere Umstände. Dies wird das Beispiel demonstrieren. Das Beispiel zeigt aber auch den Sinn von solchen Festlegungen der absoluten Grö ß e (zumindest von einzelnen Komponenten der Oberfläche). Wir belegen ein SwingTextfeld (JTextField) abwechselnd mit einem Text und löschen diesen mit einer anderen Schaltfläche wieder. Da das Textfeld bei der Erzeugung und Platzierung auf dem Panel noch leer ist, würde ein Layout-Manager – ohne
634
Java 2 Kompendium
Swing in der Praxis
Kapitel 11
die feste Vorgabe der Grö ß e – das Textfeld unter Umständen ganz klein darstellen. Bei einem Belegen müsste das Panel jedes Mal neu gezeichnet werden. Das Beispiel reagiert gelegentlich etwas »träge« auf Mausklicks. Eventuell müssen Sie etwas warten oder noch einmal klicken.
import javax.swing.*;
import java.awt.*; public class SwingApplet3 extends JApplet { // DEKLARIEREN der CONTROLS JButton jB1 = new JButton(); JButton jB2 = new JButton(); JButton jB3 = new JButton(); JButton jB4 = new JButton(); JTextField jTF1 = new JTextField(); JRadioButton jRB3 = new JRadioButton(); JRadioButton jRB4 = new JRadioButton(); public void init() { getRootPane().putClientProperty( "defeatSystemEventQueueCheck", Boolean.TRUE); // INIT_CONTROLS // Eventuelles Layout zurücksetzen getContentPane().setLayout(null); // Hintergrundfarbe setzen getContentPane().setBackground(java.awt.Color.red); // Grö ß e Applet setSize(450,350); // Belegen der CONTROLS mit Werten // danach hinzufügen. // Als dritten Schritt legen wir in dem // Beispiel die exakte Position und Grö ß e // des Controls fest jB1.setText("vergroessere"); getContentPane().add(jB1); jB1.setBounds(60,220,140,50); jB2.setText("verkleinere"); getContentPane().add(jB2); jB2.setBounds(228,220,140,50); jB3.setText("Schreibe Text"); getContentPane().add(jB3); jB3.setBounds(60,168,140,50); jB4.setText("Loesche Text"); getContentPane().add(jB4); jB4.setBounds(228,168,140,50); getContentPane().add(jTF1); jTF1.setBounds(60,24,324,38); jRB3.setText("Rot");
Java 2 Kompendium
Listing 11.6: Ein weiteres SwingApplet mit Eventhandling – Standard-Adapter
635
Kapitel 11
Swing & Co jRB3.setSelected(true); // vorselektiert getContentPane().add(jRB3); jRB3.setBounds(60,96,141,22); jRB4.setText("Blau"); getContentPane().add(jRB4); jRB4.setBounds(228,96,141,22); // REGISTIEREN und EINRICHTEN der LISTENER // Erster Schritt: Erzeugen eines Objekts der // Klasse, wo die Auswertung der Events erfolgt. jRB meineMaus = new jRB(); // Registrieren der Listener // – hier nur Mauslistener jB1.addMouseListener(meineMaus); jB2.addMouseListener(meineMaus); jB3.addMouseListener(meineMaus); jB4.addMouseListener(meineMaus); jRB3.addMouseListener(meineMaus); jRB4.addMouseListener(meineMaus); } // Klasse zum Auswerten der Reaktionen class jRB extends java.awt.event.MouseAdapter { // Die Methode ruft je nach angeklicktem Control // die entsprechende Methode zum Behandeln auf. public void mouseClicked(java.awt.event.MouseEvent event){ Object object = event.getSource(); if (object == jB1) jB1_mouseClicked(event); else if (object == jB2) jB2_mouseClicked(event); else if (object == jB3) jB3_mouseClicked(event); else if (object == jB4) jB4_mouseClicked(event); else if (object == jRB3) jRB3_mouseClicked(event); else if (object == jRB4) jRB4_mouseClicked(event); } } void jB1_mouseClicked(java.awt.event.MouseEvent event) { // vergrö ß ere this.setSize(600,400); } void jB2_mouseClicked(java.awt.event.MouseEvent event) { // verkleinere this.setSize(200,100); } void jB3_mouseClicked(java.awt.event.MouseEvent event) { // Schreibe Text jTF1.setText("Ei gude wie?"); }
636
Java 2 Kompendium
Swing in der Praxis
Kapitel 11
void jB4_mouseClicked(java.awt.event.MouseEvent event) { // Lösche Text jTF1.setText(""); } void jRB3_mouseClicked(java.awt.event.MouseEvent event) { getContentPane().setBackground(java.awt.Color.red); jRB4.setSelected(false); } void jRB4_mouseClicked(java.awt.event.MouseEvent event) { getContentPane().setBackground(java.awt.Color.blue); jRB4.setSelected(false); } }
Das Beispiel vergrö ß ert wieder jeweils bei Klick auf den entsprechenden Button das Applet bzw. verkleinert es wieder (nur im Appletviewer!). Dabei werden die Komponenten allerdings festgehalten, was die Probleme mit dieser Technik zeigen soll. Die beiden neuen Buttons schreiben und löschen Text im Textfeld. Die Radiobuttons wechseln wieder die Hintergrundfarben des Applets. Abbildung 11.9: Original-Layout
Java 2 Kompendium
637
Kapitel 11
Swing & Co
Abbildung 11.10: Mit Text, blau und Komponenten leicht zu weit links
Abbildung 11.11: Hier knallt es im Layout
11.4
Eigenständige Applikationen und Swing
Swing ist selbstverständlich nicht auf Applets beschränkt. Im Gegenteil – bei eigenständigen Applikationen treten die Probleme der Inkompatibilität von Browsern nicht auf. Hauptsächlich muss man die Applikation – statt auf Frame – auf JFrame aufbauen. Wir werden jetzt ein kleines Beispiel durchspielen, wo wir diese Technik in Verbindung mit einer eigenständigen Applikation einsetzen. Es handelt sich um eine Swing-Applikation, wo nur ein Button vorhanden ist. Dieser beendet das Programm. Listing 11.7: Eine ganz einfache eigenständige Swing-Applikation
638
import import import public
java.awt.*; javax.swing.*; java.awt.event.*; class SwingAppl extends JFrame {
Java 2 Kompendium
Eigenständige Applikationen und Swing
Kapitel 11
JButton jButton1 = new JButton(); FlowLayout flowLayout1 = new FlowLayout(); public SwingAppl() { initial(); } public static void main(String[] args) { SwingAppl swingAppl = new SwingAppl(); swingAppl.setSize(200,100); swingAppl.setVisible(true); } private void initial() { jButton1.setActionCommand("Ende"); jButton1.setText("Ende"); jButton1.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jButton1_actionPerformed(e);}}); getContentPane().setLayout(flowLayout1); setTitle("Swing-Applikation"); getContentPane().add(jButton1, null); } void jButton1_actionPerformed(ActionEvent e) { System.exit(0); }} Abbildung 11.12: Eine einfache Swing-Applikation
11.4.1
Eine Swing-Applikations-Schablone
Nachfolgend finden Sie eine Schablone für eine eigenständige Swing-Applikation, wo ein wenig mehr Funktionalität realisiert ist. Sie erstellt ein Fenster, installiert einige Reaktionsmöglichkeiten und einen Ende-Dialog. Darauf aufbauend können Sie funktionstüchtige Swing-Applikationen erstellen. import java.awt.*; import java.awt.event.*; import javax.swing.*; /** Eine Basis-Swing-Schablone für eine Applikation. */ public class SwingApplikaSchablone extends JFrame { public SwingApplikaSchablone() { // INIT_CONTROLS setTitle("Swing-Applikation"); Java 2 Kompendium
Listing 11.8: Eine Schablone für eigenständige Swing-Applikationen
639
Kapitel 11
Swing & Co setDefaultCloseOperation(javax.swing.JFrame.DO_NOTHING_ON_CLOSE); getContentPane().setLayout(new BorderLayout(0,0)); setSize(500,300); setVisible(false); // REGISTER_LISTENERS Fenst meinFenst = new Fenst(); this.addWindowListener(meinFenst); Akt meineAktion = new Akt(); } /* Erstellt eine neue Instanz von SwingApplikaSchablone mit dem im Konstruktor angebenen Titel. */ public SwingApplikaSchablone(String sTitle) { this(); setTitle(sTitle); } static public void main(String args[]) { try { // Optional Anpassen an das Look and Feel // des Nativesystems. /* try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { } */ // Neue Instanz des Applikationsfensters und // sichtbar machen. (new SwingApplikaSchablone()).setVisible(true); } catch (Throwable t) { t.printStackTrace(); // Ende mit Fehlermeldung im Falle von Problemen. System.exit(1); } } void exitApplication() { try { // Anzeige eines Ende-Dialogs int antwort = JOptionPane.showConfirmDialog(this, "Wollen Sie wirklich beenden?", "Swing-Applikation – Exit" , JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (antwort == JOptionPane.YES_OPTION) { this.setVisible(false); // Verstecke Frame this.dispose(); // Freigabe Systemressourcen System.exit(0); // Ende } } catch (Exception e) { } }
640
Java 2 Kompendium
Eigenständige Applikationen und Swing
Kapitel 11
class Fenst extends java.awt.event.WindowAdapter { public void windowClosing(java.awt.event.WindowEvent event) { Object object = event.getSource(); if (object == SwingApplikaSchablone.this) SwingApplikaSchablone_windowClosing(event); } } void SwingApplikaSchablone_windowClosing(java.awt.event.WindowEvent event) { SwingApplikaSchablone_windowClosing_Interaction1(event); } void SwingApplikaSchablone_windowClosing_Interaction1(java.awt.event.WindowEvent event) { try { this.exitApplication(); } catch (Exception e) { } } class Akt implements java.awt.event.ActionListener { public void actionPerformed(java.awt.event.ActionEvent event) { Object object = event.getSource(); } } } Abbildung 11.13: Die Schablone
Abbildung 11.14: Der zugehörige Swing-Ende-Dialog
Java 2 Kompendium
641
Kapitel 11
Swing & Co Beachten Sie die Methode showConfirmDialog(). Diese gehört wie zahlreiche weitere Methoden zum Anzeigen von verschiedenartigen Dialogfenstern zur Klasse public class JOptionPane extends JComponent implements Accessible. Dort finden Sie unter anderem die folgenden Dialogmethoden: static int showConfirmDialog(Component parentComponent, Object message) static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon) static String showInputDialog(Component parentComponent, Object message) static String showInputDialog(Component parentComponent, Object message, String title, int messageType) static Object showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) static String showInputDialog(Object message) static int showInternalConfirmDialog(Component parentComponent, Object message) static int showInternalConfirmDialog(Component parentComponent, Object message, String title, int optionType) static int showInternalConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) static int showInternalConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon) static String showInternalInputDialog(Component parentComponent, Object message) static String showInternalInputDialog(Component parentComponent, Object message, String title, int messageType) static Object showInternalInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) static void showInternalMessageDialog(Component parentComponent, Object message) static void showInternalMessageDialog(Component parentComponent, Object message, String title, int messageType) static void showInternalMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon) static int showInternalOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) static void showMessageDialog(Component parentComponent, Object message) static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) static void showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon) static int showOptionDialog(Component parentComponent, Object message,
642
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue)
11.5
Swing-Komponenten im Detail
Schauen wir uns anhand diverser Beispiele nun die wichtigsten (noch fehlenden) Swingkomponenten an und wie sie von der Syntax her integriert werden können. Die Ähnlichkeiten zu den konventionellen AWT-Komponenten sind offensichtlich, aber es gibt auch zahlreiche Neuerungen von Swing, denen keine Entsprechungen im AWT gegenüberstehen. Sie finden hier keine in je einem nummerierten Unterkapitel aufgeführten einzelnen Komponenten. Beim Aufbau dieses Abschnitts und der Zusammensetzung der besprochenen Swing-Komponenten soll explizit das AWTKapitel als Grundlage dienen, das einen solchen Aufbau realisiert. Motivation ist, die Komponenten in Form von praktischen Beispielen mit gut zusammenpassenden Elementen einzusetzen. Swing-Panels und Swing-Labels Das erste Beispiel ist eine kleine Erweiterung unserer ersten Swing-Applikation. Zusätzlich zu dieser arbeiten wir mit Swing-Panels und einem SwingLabel, das dynamisch beschriftet und gelöscht werden soll. Also ein Beispiel, das wir so auch mit dem AWT realisiert haben. Wir verwenden dabei anonyme Klassen zum Eventhandling. import java.awt.*; import javax.swing.*; import java.awt.event.*; public class SwingAppl2 extends JFrame { BorderLayout borderLayout1 = new BorderLayout(); JPanel jPanel1 = new JPanel(); FlowLayout flowLayout1 = new FlowLayout(); JButton jButton1 = new JButton(); JButton jButton2 = new JButton(); JButton jButton3 = new JButton(); JLabel jLabel1 = new JLabel(); public SwingAppl2() { initial(); } public static void main(String[] args) { SwingAppl2 swingAppl = new SwingAppl2(); swingAppl.setSize(300,100); swingAppl.setVisible(true); } private void initial() { this.getContentPane().setLayout(borderLayout1); this.setTitle("Swing-Applikation"); Java 2 Kompendium
Listing 11.9: Eine Swing-Applikation mit LayoutManager, Button, Panel und Label
643
Kapitel 11
Swing & Co jPanel1.setLayout(flowLayout1); jButton1.setText("Ende"); jButton1.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jButton1_actionPerformed(e);}}); jButton2.setText("Schreibe"); jButton2.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jButton2_actionPerformed(e);}}); jButton3.setText("Lösche"); jButton3.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jButton3_actionPerformed(e);}}); jLabel1.setHorizontalAlignment( SwingConstants.CENTER); this.getContentPane().add(jPanel1, BorderLayout.SOUTH); jPanel1.add(jButton1, null); jPanel1.add(jButton2, null); jPanel1.add(jButton3, null); this.getContentPane().add(jLabel1, BorderLayout.CENTER); } void jButton1_actionPerformed(ActionEvent e) { System.exit(0); } void jButton2_actionPerformed(ActionEvent e) { jLabel1.setText("No Pc no cry"); } void jButton3_actionPerformed(ActionEvent e) { jLabel1.setText(""); }}
Abbildung 11.15: Eine Swing-Applikation mit Panels und Label
Ja nach Button wird das Label geschrieben oder gelöscht. Der Button ganz links beendet das Programm. Menüs, Bildaufleisten, Slider, Progressbar und Toolbar unter Swing Das nächste Beispiel zeigt einige weitere Swing-Techniken und -Komponenten. Etwa einen Slider (JSlider), der im Wesentlichen einer Scrollbar (also 644
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
Bildlaufleiste – auch die wird in dem Beispiel verwendet) entspricht (unter Swing mit der Klasse JScrollbar realisiert) und eine Toolbar zum Anordnen von Komponenenten (JToolbar). Dazu kommt noch eine Progressbar (ein Fortschrittsbalken, der anzeigt, wie weit ein Prozess gediehen ist) (JProgressBar), die man zum Anzeigen des Fortschritts einer Aktion verwendet (beispielsweise um den Fortschritt einer Installation anzuzeigen). Zusätzlich wird ein Menü unter Swing realisiert. Beachtet werden sollte zudem, dass das Beispiel Bilder für Schaltflächen verwendet, die über die Klasse ImageIcon und und Methode setIcon() realisiert werden. Ebenso wird die Verwendung einer Quick-Info für Komponenten demonstriert (setToolTipText()). Das Beispiel besteht aus drei Dateien und ist etwas umfangreicher, aber ausführlich im Quelltext dokumentiert. Datei Nummer eins ist die eigentliche Applikation und recht klein, denn sie ruft nur das in der zweiten Datei zwei beschriebene Fenster auf. Dabei zeigt diese Datei als kleines Bonbon, wie man eine Applikation auf dem Bildschirm zentrieren kann. import javax.swing.UIManager; import java.awt.*; public class SwingAppl3 { boolean packFrame = false; /**Die Anwendung konstruieren*/ public SwingAppl3() { SwingFrame1 frame = new SwingFrame1(); // Frames überprüfen, die voreingestellte Grö ß e // haben, Frames packen, die nutzbare bevorzugte // Grö ß eninformationen enthalten, z.B. aus ihrem // Layout if (packFrame) { frame.pack(); } else { frame.validate(); } // Fenster auf Bildschirm zentrieren Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.height > screenSize.height) { frameSize.height = screenSize.height; } if (frameSize.width > screenSize.width) { frameSize.width = screenSize.width; } frame.setLocation((screenSize.width – frameSize.width) / 2, (screenSize.height – frameSize.height) / 2); frame.setVisible(true); } Java 2 Kompendium
Listing 11.10: Eine Swing-Applikation mit Slider, Scrollbar, Progressbar, Toolbar, Menü und Statuszeile
645
Kapitel 11
Swing & Co /** main()-Methode der Applikaiton */ public static void main(String[] args) { try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { e.printStackTrace(); } new SwingAppl3(); }} Die Auslagerung des Programmstarts Datei Nummer zwei beinhaltet die wesentliche Funktionalität des Beispiels. Beachten Sie bitte die Kommentare im Quelltext. import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.beans.*; public class SwingFrame1 extends JFrame { /* Die Objekte */ JPanel mPanel; JMenuBar jMBar1 = new JMenuBar(); JMenu jMFile = new JMenu(); JMenuItem jMFileExit = new JMenuItem(); JMenu jMHelp = new JMenu(); JMenuItem jMHelpAbout = new JMenuItem(); JToolBar jToolBar = new JToolBar(); JButton jB1 = new JButton(); JButton jB2 = new JButton(); ImageIcon image1; ImageIcon image2; JLabel statusZeil = new JLabel(); BorderLayout bdrLayout1 = new BorderLayout(); JPanel jPanel1 = new JPanel(); BorderLayout bdrLayout2 = new BorderLayout(); JProgressBar jPB1 = new JProgressBar(); JScrollBar jScBr1 = new JScrollBar(); JSlider jSld1 = new JSlider(); JLabel jLb1 = new JLabel(); JLabel jLb2 = new JLabel(); /* Der Konstruktor */ public SwingFrame1() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { initial(); } catch(Exception e) { e.printStackTrace(); }
646
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
} /**Initialisierung der Komponenten und Registrierung der Listener */ private void initial() throws Exception { // Swing-Panel gesetzt und initialisiert mPanel = (JPanel) this.getContentPane(); mPanel.setLayout(bdrLayout1); // Fenstergroesse und Titelzeile this.setSize(new Dimension(400, 300)); this.setTitle("SwingMuster 1"); // Label1 dient als Statuszeile – leer setzen statusZeil.setText(" "); // Menuebar beschriften jMFile.setText("Datei"); jMFileExit.setText("Beenden"); // Listener zum Beenden über das Menü jMFileExit.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { jMFileExit_actionPerformed(e); } }); // Hilfemenü jMHelp.setText("Hilfe"); jMHelpAbout.setText("Info"); // Listener zum Aufruf des Infodialogs jMHelpAbout.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { jMHelpAbout_actionPerformed(e); } }); // Listener Button 1 jB1.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jB1_actionPerformed(e); } }); // Quick-Info für Button 1 jB1.setToolTipText("Text im Label anzeigen"); // Grafik für Button 1 – ein jB1.setIcon(new ImageIcon(getToolkit().getImage("bild1.gif"))); // Analog Button 2 jB2.setIcon(new ImageIcon(getToolkit().getImage("bild2.gif"))); // Alternative für die Referenzierung eines Icons. // Hardcodierte Pfadangabe und Verwendung von // java.net.URL – AUSKOMMENTIERT /* jB1.setIcon(new ImageIcon(new java.net.URL("file:///C:/WINNT/Profiles/
Java 2 Kompendium
647
Kapitel 11
Swing & Co Administrator/jproject/SwingMuster1/src/swingmuster1/bild1.gif"))); */ jB2.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jB2_actionPerformed(e); } }); jB2.setToolTipText("Text im Label löschen"); // Panel Layout setzen jPanel1.setLayout(bdrLayout2); /* Slider vertikal ausrichten, Wert setzen und Listener registrieren */ jSld1.setOrientation(JSlider.VERTICAL); jSld1.setValue(0); jSld1.addChangeListener( new javax.swing.event.ChangeListener() { public void stateChanged(ChangeEvent e) { jSld1_stateChanged(e); } }); /* Label 1 formatieren und positionieren */ jLb1.setFont(new java.awt.Font("Dialog", 0, 42)); jLb1.setForeground(Color.red); jLb1.setHorizontalAlignment(SwingConstants.CENTER); // Label 2 dito, sowie Listener registrieren jLb2.setFont(new java.awt.Font("Dialog", 0, 24)); jLb2.setHorizontalAlignment(SwingConstants.CENTER); jLb2.setText("Swing"); jLb2.addMouseListener( new java.awt.event.MouseAdapter() { public void mouseEntered(MouseEvent e) { jLb2_mouseEntered(e); } public void mouseExited(MouseEvent e) { jLb2_mouseExited(e); } }); // Listener für Scrollbar registrieren jScBr1.addAdjustmentListener( new java.awt.event.AdjustmentListener() { public void adjustmentValueChanged(AdjustmentEvent e) { jScBr1_adjustmentValueChanged(e); } }); // Toolbar mit Button füllen jToolBar.add(jB1); jToolBar.add(jB2); // Menubar füllen jMFile.add(jMFileExit); jMHelp.add(jMHelpAbout);
648
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
jMBar1.add(jMFile); jMBar1.add(jMHelp); // Komponenten dem Fenster hinzufügen this.setJMenuBar(jMBar1); mPanel.add(jToolBar, BorderLayout.NORTH); mPanel.add(statusZeil, BorderLayout.SOUTH); mPanel.add(jPanel1, BorderLayout.CENTER); jPanel1.add(jPB1, BorderLayout.SOUTH); jPanel1.add(jScBr1, BorderLayout.EAST); jPanel1.add(jSld1, BorderLayout.WEST); jPanel1.add(jLb1, BorderLayout.CENTER); jPanel1.add(jLb2, BorderLayout.NORTH); } /**Aktion Beenden */ public void jMFileExit_actionPerformed(ActionEvent e) { System.exit(0); } /**Aktion Info – ein modaler Dialog, der immer zentriert im aufrufenden Fenster angezeigt wird. */ public void jMHelpAbout_actionPerformed(ActionEvent e) { SwingFrame1_Infodialog dlg = new SwingFrame1_Infodialog(this); Dimension dlgSize = dlg.getPreferredSize(); Dimension frmSize = getSize(); Point loc = getLocation(); dlg.setLocation((frmSize.width – dlgSize.width) / 2 + loc.x, (frmSize.height – dlgSize.height) / 2 + loc.y); dlg.setModal(true); dlg.show(); } /* Beenden über Schliessbutton */ protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { jMFileExit_actionPerformed(null); } } /* Veränderung der Scrollbar – Slider, Label und Progressbar zeigen die Veränderung */ void jScBr1_adjustmentValueChanged(AdjustmentEvent e) { jLb1.setText((new Integer(jScBr1.getValue())).toString()); jPB1.setValue(jScBr1.getValue()); jSld1.setValue(jScBr1.getValue()); } /* Veränderung des Sliders – Scrollbar, Label und Progressbar zeigen die Veränderung */ void jSld1_stateChanged(ChangeEvent e) {
Java 2 Kompendium
649
Kapitel 11
Swing & Co jLb1.setText((new Integer(jSld1.getValue())).toString()); jPB1.setValue(jSld1.getValue()); jScBr1.setValue(jSld1.getValue()); } /* Button 1 betätigt – Label wird angezeigt*/ void jB1_actionPerformed(ActionEvent e) { jLb2.setVisible(true); } /* Button 2 betätigt – Label wird ausgeblendet*/ void jB2_actionPerformed(ActionEvent e) { jLb2.setVisible(false); } /* Label 2 mit der Maus überstrichen – Text in Statuszeile */ void jLb2_mouseEntered(MouseEvent e) { statusZeil.setText("Das Label"); } /* Bereich von Label 2 mit der Maus verlassen – Text in Statuszeile wird gelöscht */ void jLb2_mouseExited(MouseEvent e) { statusZeil.setText(""); }}
Abbildung 11.16: Das Label und die Progressbar zeigen die Position des Sliders an.
Nun fehlt nur noch die dritte Datei, in der der Hilfedialog realisiert wird. Diese Datei arbeitet mit einem Dialogfenster und Swing, das auf JDialog basiert. Listing 11.11: Der Infodialog
650
import import import import /* Der
java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.border.*; Infodialog zu der Appplikation SwingAppl3 */
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
public class SwingFrame1_Infodialog extends JDialog implements ActionListener { /* Die Komponenten */ JPanel pl1 = new JPanel(); JPanel pl2 = new JPanel(); JPanel insetsPanel1 = new JPanel(); JPanel insetsPanel2 = new JPanel(); JPanel insetsPanel3 = new JPanel(); JButton bt1 = new JButton(); JLabel imageLabel = new JLabel(); JLabel lb1 = new JLabel(); JLabel lb2 = new JLabel(); JLabel lb3 = new JLabel(); JLabel lb4 = new JLabel(); BorderLayout bdLayout1 = new BorderLayout(); BorderLayout bdLayout2 = new BorderLayout(); FlowLayout flowLayout1 = new FlowLayout(); GridLayout gridLayout1 = new GridLayout(); String product = ""; String version = "1.0"; String copyright = "Copyright (c) 2001"; String comments = ""; JLabel jLb1 = new JLabel(); JLabel jLb2 = new JLabel(); JLabel jLb3 = new JLabel(); public SwingFrame1_Infodialog(Frame parent) { super(parent); enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { initial(); } catch(Exception e) { e.printStackTrace(); } pack(); } /**Initialisierung der Komponenten*/ private void initial() throws Exception { this.setTitle("Info"); setResizable(false); pl1.setLayout(bdLayout1); pl2.setLayout(bdLayout2); insetsPanel1.setLayout(flowLayout1); insetsPanel2.setLayout(flowLayout1); insetsPanel2.setBorder( BorderFactory.createEmptyBorder( 10, 10, 10, 10)); gridLayout1.setRows(4); gridLayout1.setColumns(1); lb1.setText("Version 1.0");
Java 2 Kompendium
651
Kapitel 11
Swing & Co lb3.setText(copyright); lb4.setText(comments); insetsPanel3.setLayout(gridLayout1); insetsPanel3.setBorder( BorderFactory.createEmptyBorder( 10, 60, 10, 10)); bt1.setText("OK"); bt1.addActionListener(this); jLb1.setText("RJS EDV"); jLb3.setText("WWW.RJS.DE"); insetsPanel2.add(imageLabel, null); pl2.add(insetsPanel2, BorderLayout.WEST); this.getContentPane().add(pl1, null); insetsPanel3.add(lb1, null); insetsPanel3.add(lb2, null); insetsPanel3.add(lb3, null); insetsPanel3.add(lb4, null); insetsPanel3.add(jLb1, null); insetsPanel3.add(jLb2, null); insetsPanel3.add(jLb3, null); pl2.add(insetsPanel3, BorderLayout.CENTER); insetsPanel1.add(bt1, null); pl1.add(insetsPanel1, BorderLayout.SOUTH); pl1.add(pl2, BorderLayout.NORTH); } /* Ende über Schließbutton */ protected void processWindowEvent(WindowEvent e) { if (e.getID() == WindowEvent.WINDOW_CLOSING) { cancel(); } super.processWindowEvent(e); } /* Dialog schließen*/ void cancel() { dispose(); } /**Dialog bei Schalter-Ereignis schließen*/ public void actionPerformed(ActionEvent e) { if (e.getSource() == bt1) { cancel(); } }}
Das Beispiel realisiert eine recht umfangreiche Funktionalität mit diversen Feinheiten, die im Quelltext ausführlich dokumentiert sind. Viel Funktionalität basiert auf der Methode getValue(), mit der im Allgemeinen Werte von Komponenten wie Slider oder Bildlaufleisten abgefragt werden können.
652
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11 Abbildung 11.17: Der Infodialog
Wenn Sie die Maus über die Buttons bewegen, wird eine Quick-Info angezeigt. Dazu wird die Methode setToolTipText() verwendet. Abbildung 11.18: Quick-Info
Wenn Sie auf den einen Button klicken, wird das Label mit dem Text »Swing« angezeigt, ansonsten versteckt. Die Buttons haben keine Beschriftung, sondern zeigen Icons. Diese werden mit der Anweisung jB1.setIcon(new ImageIcon(getToolkit().getImage("bild1.gif")));
gesetzt. Alternativ können Sie hier auch gut mit der Klasse java.net.URL und einer anderen Variante der Methode ImageIcon() arbeiten, wenn Sie ein Bild aus einer beliebigen URL laden. Ein Beispiel für einen hardcodierten Zugriff auf die Festplatte:
Java 2 Kompendium
653
Kapitel 11
Swing & Co jB1.setIcon(new ImageIcon(new java.net.URL("file:///C:/WINNT/Profiles/ Administrator/project/SwingMuster1/src/swingmuster1/bild1.gif")));
Unter Verwendung des http-Protokolls ist dies auch mit eine beliebigen Internet-URL möglich. Auch das Label mit dem Text »Swing« besitzt eine Funktionalität. Wenn der Mauszeiger den Bereich überstreicht, wird in der Statuszeile ein Text angezeigt. Abbildung 11.19: Überstreichen des Labels bewirkt eine Textausgabe in der Statuszeile.
Das Menü der Applikation ermöglicht das Beenden des Programms und die Anzeige eines Infodialogs. Abbildung 11.20: Das Menü – Beachten Sie, dass das Label mit dem Button ausgeblendet wurde
654
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
Popup-Menüs, Checkboxen, Listenfelder, Textfelder, Toggle-Buttons und JTabbedPanes Das vorletzte Beispiel zum Thema Swing soll den Einsatz von Popup-Menüs (Klasse JPopupMenu), Checkboxen (JCheckBox), Listenfeldern (JComboBox), Textfeldern (JTextArea) und Toggle-Buttons demonstrieren. Toggle-Buttons basieren auf der Klasse JToggleButton und erweitern neben einigen zusätzlichen Eigenschaften im Wesentlichen normale Buttons um die Eigenschaft, einen gedrückten Status anzeigen zu können. Dazu kommt der Einsatz von Registerblättern, wie sie beispielsweise aus Excel oder den verschiedensten Dialogfenstern unter Windows bekannt sind. Damit ist es möglich, in einem Fensterbereich abwechselnd verschiedene Inhalte anzuzeigen. Diese Registerblätter werden als ein besonderes Swing-Panel realisiert, das auf der Klasse JTabbedPane aufbaut. import javax.swing.*; import java.awt.*; import java.awt.event.*; public class VerschiedeneSwingKomponenten extends JFrame { // Die Komponenten BorderLayout borderLayout1 = new BorderLayout(); // Container für Tabs JTabbedPane jTabbedPane1 = new JTabbedPane(); JPanel jPanel1 = new JPanel(); JPanel jPanel2 = new JPanel(); BorderLayout borderLayout2 = new BorderLayout(); JPanel jPanel3 = new JPanel(); FlowLayout flowLayout1 = new FlowLayout(); // Toggle-Button JToggleButton jToggleButton1 = new JToggleButton(); BorderLayout borderLayout3 = new BorderLayout(); JPanel jPanel4 = new JPanel(); JPanel jPanel5 = new JPanel(); JToggleButton jToggleButton2 = new JToggleButton(); JLabel jLabel1 = new JLabel(); BorderLayout borderLayout4 = new BorderLayout(); JPanel jPanel6 = new JPanel(); // Checkbox JCheckBox jCheckBox1 = new JCheckBox(); JPanel jPanel7 = new JPanel(); JPanel jPanel8 = new JPanel(); // TextArea JTextArea jTextArea1 = new JTextArea(); BorderLayout borderLayout5 = new BorderLayout(); // Combobox JComboBox jComboBox1 = new JComboBox(); JLabel jLabel2 = new JLabel(); // Popup-Menü JPopupMenu jPopupMenu1 = new JPopupMenu();
Java 2 Kompendium
Listing 11.12: Popup-Menüs, Checkboxen, Listenfelder, Textfelder, Toggle-Button und JTabbedPanes
655
Kapitel 11
Swing & Co JMenuItem jMenuItem1 = new JMenuItem(); // Die main()-Methode public static void main(String[] args) { VerschiedeneSwingKomponenten u = new VerschiedeneSwingKomponenten(); u.setSize(300,300); u.show(); } // Konstruktor public VerschiedeneSwingKomponenten() { try { initial(); } catch(Exception e) { e.printStackTrace(); } } // Initialisierung private void initial() throws Exception { this.getContentPane().setLayout(borderLayout1); jPanel1.setLayout(borderLayout2); jPanel3.setLayout(flowLayout1); jToggleButton1.setText("Übertrage"); jToggleButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jToggleButton1_actionPerformed(e); }}); jPanel2.setLayout(borderLayout3); jToggleButton2.setText("Ende"); jToggleButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jToggleButton2_actionPerformed(e); } }); jPanel4.setLayout(borderLayout4); jCheckBox1.setSelected(true); jCheckBox1.setText("Text anzeigen"); jCheckBox1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jCheckBox1_actionPerformed(e); }}); jPanel8.setLayout(borderLayout5); jLabel2.setText("Textmuster"); jComboBox1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jComboBox1_actionPerformed(e); }}); // Zeilenumbruch in TextArea erlauben jTextArea1.setLineWrap(true); jMenuItem1.setText("Übertragen"); jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
656
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
public void actionPerformed(ActionEvent e) { jMenuItem1_actionPerformed(e); }}); jPanel3.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(MouseEvent e) { jPanel3_mouseClicked(e); }}); // Tab-Container hinzufügen this.getContentPane().add(jTabbedPane1, BorderLayout.CENTER); jTabbedPane1.add(jPanel1, "Text eintragen"); jPanel1.add(jPanel3, BorderLayout.NORTH); jPanel3.add(jToggleButton1, null); jPanel1.add(jPanel7, BorderLayout.SOUTH); jPanel7.add(jLabel2, null); // Listenfeld 4 Einträge hinzufügen jComboBox1.addItem(makeObj("Muster 1")); jComboBox1.addItem(makeObj("Muster 2")); jComboBox1.addItem(makeObj("Muster 3")); jComboBox1.addItem(makeObj("Muster 4")); jPanel7.add(jComboBox1, null); jPanel1.add(jPanel8, BorderLayout.CENTER); jPanel8.add(jTextArea1, BorderLayout.CENTER); jTabbedPane1.add(jPanel2, "Text anzeigen"); jPanel2.add(jPanel4, BorderLayout.CENTER); jPanel4.add(jLabel1, BorderLayout.CENTER); jPanel4.add(jPanel6, BorderLayout.SOUTH); jPanel6.add(jCheckBox1, null); jPanel2.add(jPanel5, BorderLayout.NORTH); jPanel5.add(jToggleButton2, null); // Popup-Menü Eintrag hinzufügen jPopupMenu1.add(jMenuItem1); // Popup-Menü dem Panel hinzufügen jPanel3.add(jPopupMenu1); } // Methode zum Generieren von Objekten // Wird beim Erzeugen von Eintägen für das // Listenfeld verwendet private Object makeObj(final String item) { return new Object() { public String toString() { return item; } }; } // Reaktion auf Klicks im Listenfeld void jComboBox1_actionPerformed(ActionEvent e) { // Unterscheidung, welcher Eintrag // ausgewählt wurde if(jComboBox1.getSelectedIndex()==0) { jTextArea1.setText("Es grünt so grün"); } else if(jComboBox1.getSelectedIndex()==1) { jTextArea1.setText("Die Antwort ist 42"); }
Java 2 Kompendium
657
Kapitel 11
Swing & Co else if(jComboBox1.getSelectedIndex()==2) { jTextArea1.setText("Wie denn, wo denn, was denn?"); } else if(jComboBox1.getSelectedIndex()==3) { jTextArea1.setText("Was unterscheidet einen Porsche von einer Ente? Eine Ente ist cooler!"); } } // Programm beenden void jToggleButton2_actionPerformed(ActionEvent e) { System.exit(0); } // Text aus TextArea übertragen in Label auf // anderem Tabellenblatt – per Button void jToggleButton1_actionPerformed(ActionEvent e) { jLabel1.setText(jTextArea1.getText()); } // Text aus TextArea übertragen in Label auf // anderem Tabellenblatt – per Item im Popup void jMenuItem1_actionPerformed(ActionEvent e) { jLabel1.setText(jTextArea1.getText()); } // Anzeigen Popup-Menü void jPanel3_mouseClicked(MouseEvent e) { // Nur wenn rechte Maustaste gedrückt if(e.getModifiers()==Event.META_MASK) { // Zeige Popup in angegebener Komponente // an den Koordinaten, wo Klick erfolgte jPopupMenu1.show(jPanel3,e.getX(),e.getY()); } } // Checkbox ist selektiert oder nicht void jCheckBox1_actionPerformed(ActionEvent e) { if(jCheckBox1.isSelected()) { jLabel1.setVisible(true); } else { jLabel1.setVisible(false); } }}
Wenn das Programm gestartet wird, werden Sie zwei Registerblätter vorfinden. Auf dem zugrunde liegenden Container werden diverse weitere Panels und Komponenten platziert. Auf dem ersten Registerblatt werden Sie einen Button im oberen Bereich, im Zentrum ein vorbelegtes Texteingabefeld (multizeilenfähig, was über die Anweisung jTextArea1.setLineWrap(true) realisiert wird) und im unteren Bereich ein einzeiliges Listenfeld mit vorangestelltem Label finden.
658
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11 Abbildung 11.21: Das erste Registerblatt wird angezeigt.
Sowohl der Button als auch das per Klick mit der rechten Maustaste auf den Nordbereich ausgelöste Popup-Menü erlauben die Übertragung des Textes im Texteingabefeld an das Label im zweiten Registerblatt. Dabei istdie Erzeugung eines Popup-Menüs recht einfach. Ein vorher erzeugter Eintrag wird mit der üblichen add()-Methode hinzugefügt (jPopupMenu1.add- (jMenuItem1)) und das Popup-Menü dem Panel oder der Komponenten, auf der es agieren soll, hinzugefügt. In unserem Beispiel ist das das jPanel3 (jPanel3.add(jPopupMenu1)). Mit etwas grö ß erem Aufwand verbunden ist die konkrete Methode, mit der auf Klicks des Popup-Menüs reagiert werden soll. Zwar kann recht unkompliziert die Übertragung des Textes aus der TextArea auf das Label auf dem anderem Tabellenblatt realisiert werden: void jMenuItem1_actionPerformed(ActionEvent e) { jLabel1.setText(jTextArea1.getText()); }
Jedoch ist es etwas Mühe, das Menü nur beim Klick mit der rechten Maustaste anzuzeigen (standardmä ß ig wird es auch beim Klick mit der linken Maustaste aktiviert). Das lässt sich aber mit dem der aufgerufenen Methode übergebenen Event-Objekt steuern (ebenso die Koordinaten des Popups). Das Objekt enthält Informationen über die gedrückte Maustaste, die mit Klassenkonstanten von Event verglichen werden können: void jPanel3_mouseClicked(MouseEvent e) { // Nur wenn rechte Maustaste gedrückt if(e.getModifiers()==Event.META_MASK) { // Zeige Popup in angegebener Komponente // an den Koordinaten, wo Klick erfolgte
Java 2 Kompendium
659
Kapitel 11
Swing & Co jPopupMenu1.show(jPanel3,e.getX(),e.getY()); } }
Die Übertragung des Textes von dem Textfeld mit dem Button erfolgt recht einfach: void jToggleButton1_actionPerformed(ActionEvent e) { jLabel1.setText(jTextArea1.getText()); }
Der Text im Eingabefeld kann frei geändert oder per Auswahl im unten stehenden Listenfeld vorgegeben werden. Das Listenfeld erhält seine Einträge über die Anweisungen der Form: jComboBox1.addItem(makeObj("Muster 1"));
Dabei erstellt die dort aufgerufene Methode makeObj() mit dem übergebenen String-Objekt über die Anweisungen return new Object() { public String toString() { return item; } };
Die beim Klick auf das Listenfeld ausgelöste Reaktionsmethode void jComboBox1_actionPerformed(ActionEvent e) unterscheidet mit der Methode getSelectedIndex(), welcher Eintrag ausgewählt wurde: if(jComboBox1.getSelectedIndex()==0) { jTextArea1.setText("Es grünt so grün"); } else if(jComboBox1.getSelectedIndex()==1) { jTextArea1.setText("Die Antwort ist 42"); } else if(jComboBox1.getSelectedIndex()==2) { jTextArea1.setText("Wie denn, wo denn, was denn?"); } else if(jComboBox1.getSelectedIndex()==3) { jTextArea1.setText("Was unterscheidet einen Porsche von einer Ente? Eine Ente ist cooler!"); } }
660
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11 Abbildung 11.22: Das Popup-Menü
Auf dem zweiten Registerblatt wird der übernommene Text angezeigt, wenn die Checkbox entsprechend selektiert ist. Dazu gibt es die Anweisung jCheckBox1.setSelected(true), um die Checkbox beim Laden zu selektieren. Die Reaktionsmethode, ob die Checkbox selektiert ist oder nicht, sieht so aus: void jCheckBox1_actionPerformed(ActionEvent e) { if(jCheckBox1.isSelected()) { jLabel1.setVisible(true); } else { jLabel1.setVisible(false); } }
Der Ende-Button erlaubt den Abbruch des Programms. Abbildung 11.23: Das zweite Registerblatt und der übertragene Text werden angezeigt.
Java 2 Kompendium
661
Kapitel 11
Swing & Co Ein Swing-Taschenrechner Das abschließende Beispiel ist eine etwas komplexere Anwendung – ein Taschenrechner. Hier kommen – neben der doch etwas komplexeren Funktionalität – einige Beeinflussungen von Komponenteneigenschaften hinzu. Beachten Sie bitte die Kommentare im Quelltext, die die einzelnen Schritte ausführlich erläutern.
Listing 11.13: Ein Swing-Taschenrechner als eigenständige Applikation
662
import java.awt.*; import java.awt.event.*; import javax.swing.*; class TaschenrechnerPanel extends JPanel implements ActionListener { private JTextField anzFeld; private double aktWerBer = 0; private String oprat = "="; private boolean begBer = true; public TaschenrechnerPanel() { // Definiere ein Borderlayout setLayout(new BorderLayout()); // Definiere anzFeld zur Ausgabe von // Tasteneingaben und berechnetem Ergebnis. Beim // Start soll es mit 0 vorbelegt sein. // Hintergrundfarbe ist default weiß, // Ausrichtung rechtsbündig. anzFeld = new JTextField("0"); anzFeld.setEditable(false); anzFeld.setHorizontalAlignment( JTextField.RIGHT); anzFeld.setBackground(java.awt.Color.white); // Anzeige im Nordbereich des Borderlayouts (oben) add(anzFeld, "North"); // Definiere ein neues JPanel, das als // Subpanel dem Hauptpanel hinzugefügt wird. // Es soll die Buttons des Tastenfeldes beinhalten. // Das Layout in ein // GridLayout mit 5 Zeilen und 4 Spalten. JPanel tastFeld = new JPanel(); tastFeld.setLayout(new GridLayout(5, 4)); // Hinzufügen der einzelnen Schaltflächen mit // einer selbst definierten Methode. // erste Reihe Tastenfeld fuegeBnHinzu(tastFeld, "C"); fuegeBnHinzu(tastFeld, "F"); fuegeBnHinzu(tastFeld, "Ende"); fuegeBnHinzu(tastFeld, "%"); // zweite Reihe Tastenfeld fuegeBnHinzu(tastFeld, "7"); fuegeBnHinzu(tastFeld, "8"); fuegeBnHinzu(tastFeld, "9"); fuegeBnHinzu(tastFeld, "/");
Java 2 Kompendium
Swing-Komponenten im Detail
Kapitel 11
// dritte Reihe Tastenfeld fuegeBnHinzu(tastFeld, "4"); fuegeBnHinzu(tastFeld, "5"); fuegeBnHinzu(tastFeld, "6"); fuegeBnHinzu(tastFeld, "*"); // vierte Reihe Tastenfeld fuegeBnHinzu(tastFeld, "1"); fuegeBnHinzu(tastFeld, "2"); fuegeBnHinzu(tastFeld, "3"); fuegeBnHinzu(tastFeld, "-"); // fünfte Reihe Tastenfeld fuegeBnHinzu(tastFeld, "0"); fuegeBnHinzu(tastFeld, "."); fuegeBnHinzu(tastFeld, "="); fuegeBnHinzu(tastFeld, "+"); // füge das Tastenfeld in den Haupt-Panel add(tastFeld, "Center"); } // Definition einer Methode, die einem // Container als Argument übergebene Schaltflächen // hinzufügt und beim ActionListener registriert. private void fuegeBnHinzu(Container uebergebenerContainer, String name) { // neuer Dummybutton JButton dummyButton = new JButton(name); // Einfügen uebergebenerContainer.add(dummyButton); // Registrieren dummyButton.addActionListener(this); } // Die Aktionsreaktionsmethode public void actionPerformed(ActionEvent evt) { String eingTast = evt.getActionCommand(); // Bei Betätigen der Ende-Taste Taschenrecher // beenden if (eingTast == "Ende") System.exit(0); // anzFeld auf 0 setzen, alle Operanden // Zurücksetzen und Beginn der Berechnung // aktivieren if (eingTast == "C") { aktWerBer = 0; anzFeld.setText("" + aktWerBer); eingTast = "="; begBer = true; } // anzFeld in der Farbe umsetzen if (eingTast == "F") { if (anzFeld.getBackground() == java.awt.Color.red) { anzFeld.setBackground(java.awt.Color.white); } else {
Java 2 Kompendium
663
Kapitel 11
Swing & Co anzFeld.setBackground(java.awt.Color.red); } } // Die %-Taste wird anders als die sonstigen // arithmetischen Operatoren behandelt. Grund: // nur ein vorangestellter Operand und nicht ein // dem Operator voran- und ein ihm nachgestellter // Operand. if (eingTast == "%") { aktWerBer = Double.parseDouble(anzFeld.getText()) / 100; anzFeld.setText("" + aktWerBer); } // Kontrolle, ob eine Zahl oder ein Dezimalpunkt // eingegeben wurde. Wenn ja, unterscheide, ob das // Anzeigefeld bisher noch keinen Wert beinhaltet // bzw. ob eine neue Berechnung gestartet wird // oder ob sich im Anzeigefeld bereits ein Eintrag // befindet, der zur Berechnung verwendet werden // soll. Falls nicht, schreibe den Wert der // ausgelesenen Eingabe-Taste direkt in das // Anzeigefeld. Ansonsten hänge ihn an den // bisherigen Wert an. if ('0' 1, d.h. zwei Seite wurden gedruckt if(page>1) return NO_SUCH_PAGE; String line = null; Graphics2D g2 = (Graphics2D)g; g2.scale(1.0 / SKALIERFAKTOR, 1.0 / SKALIERFAKTOR); int ypos = (int)pf.getImageableY() * SKALIERFAKTOR; int xpos = ((int)pf.getImageableX() + 2) * SKALIERFAKTOR; int yd = 12 * SKALIERFAKTOR; int ymax = ypos + (int)pf.getImageableHeight() * SKALIERFAKTOR – yd; //Seitentitel ausgeben ypos += yd; g2.setColor(Color.black); g2.setFont(new Font("Monospaced", Font.ITALIC, 12 * SKALIERFAKTOR)); g.drawString("Seite " + (page + 1), xpos, ypos); g.drawString(druckText, xpos, ypos*2); // Erneuter Aufruf von print() return druckErgeb; } public static void main(String[] args) { Textdruck3 druckProgr = new Textdruck3("Hello World"); if (druckProgr.setupPageFormat()) { if (druckProgr.setupJobOptions()) { try { druckProgr.drucke(); }
750
Java 2 Kompendium
Zusammenfassung
Kapitel 13
catch (Exception e) { System.err.println(e.toString()); System.exit(1); } System.exit(0); } } } } Abbildung 13.13: Ein plattformabhängiger StandardDialog zur Einstellung der SeitenEckdaten
13.17
Zusammenfassung
Ein- und Ausgabeoperationen zählen zu den grundlegendsten Aktionen, die von einem Programm bewerkstelligt werden. In Java werden diese Ein- und Ausgabeoperationen mittels Datenströmen realisiert – einem nicht-interpretierten Strom von Bytes. Ein Datenstrom kann von jeder beliebigen Quelle kommen, d.h., der Ursprungsort spielt überhaupt keine Rolle. Die Information über die Quelle steckt in einem Strom-Argument. Außerdem gibt es noch ein weiteres Argument, das angibt, in welches Zielobjekt die verarbeiteten Daten zurückgeschrieben werden sollen.
Java 2 Kompendium
751
Kapitel 13
Ein- und Ausgabe in Java
Abbildung 13.14: Ein plattformabhängiger StandardDruckdialog zur Einstellung der konkreten Seiten, der Kopien sowie des Druckers
Unter Java stehen zur Behandlung des Datenstrom-Modells zwei abstrakte Klassen zur Verfügung: InputStream OutputStream
Die beiden Klassen gehören zu dem Paket java.io. Die meisten Klassen zur Ein- und Ausgabe leiten sich von InputStream und OutputStream ab oder verwenden sie. Es gibt aber auch Klassen, die nicht auf diese beiden abstrakten Klassen zurückgehen. Eine der wohl wichtigsten Nicht-Streamklassen ist die Klasse File, die Dateinamen und Verzeichnisnamen in einer plattformunabhängigen Weise verwaltet. Die einfachen Strom-Methoden erlauben nur das Versenden von Bytes mittels Datenströme. Zum Senden verschiedener Datentypen gibt es die Schnittstellen DataInput und DataOutput. Sie legen Methoden zum Senden und Empfangen anderer Java-Datentypen fest. Mithilfe der Schnittstellen ObjectInput und ObjectOutput lassen sich ganze Objekte über einen Strom zusenden. Mit dem StreamTokenizer können Sie einen Strom wie eine Gruppe von Worten behandeln. Er ist dem StringTokenizer ähnlich, der das Gleiche mit Zeichenketten tut. Für die Kommunikation von einzelnen Threads gibt es die beiden Klassen PipedInputStream zum Lesen von Daten aus einem PipedOutputStream. Der PipedOutputStream dient also zum Schreiben in einen PipedInputStream. Alle Methoden, die sich mit Eingabe- und Ausgabeoperationen beschäftigen, werden in der Regel mit der throw IOExceptions oder aber EOFException abgesichert.
752
Java 2 Kompendium
Zusammenfassung
Kapitel 13
Ein wesentlicher Ausgabevorgang ist das Drucken, das in Java mit zwei unterschiedlichen Konzepte realisiert wird. Ab dem JDK 1.1 wurde das Konzept mit der Klasse PrintJob aus java.awt.Toolkit realisert, ab dem SDK 2 verlagerte man die Druckfunktionalität in das Paket java.awt.print.
Java 2 Kompendium
753
14
Java-Sicherheit
Fügen wir an dieser Stelle einen kleinen Break bezüglich der konkreten Programmierung ein und wenden uns einem wichtigen Hintergrundthema zu. Das Thema Sicherheit und Java gehören eng zusammen. Nicht zuletzt, weil es auch um das Internet als offenes Netzwerk geht. Bis vor einiger Zeit wurde die Sicherheit von Computern mit dem Verhindern von Daten-Crashs und der Abwehr von Computerviren gleichgesetzt. In geschlossenen Netzwerken galt zusätzlich der Abwehr von unbefugten Eindringlingen das Augenmerk. Das Internet selbst war offen und barg außer diesen Risiken keine Gefahren. Zumindest solange das auf dem HTTP-Protokoll basierende HTML die einzige Sprache des WWW war. Da man nur mithilfe eines Browsers (Telnet, FTP & Co. mal außen vor) Daten von einem Server abrufen konnte und echte Interaktivität kaum stattfand, konnte auch außerhalb des Browsers – sprich im restlichen Computersystem – nicht viel unbemerkt passieren. Dies hat sich mit dem Auftauchen von ActiveX, aber auch mit Java geändert. Es gehört jedoch zu den zentralen Argumenten für Java, dass dort dieses Thema Sicherheit ganz groß geschrieben wird. Dennoch darf man nicht in unkritische Euphorie verfallen, nur weil Java gegenüber der Konkurrenz eine neue Welt der Sicherheitsaspekte geöffnet hat und Programmierern eine bisher kaum gekannte Möglichkeit eröffnet, sicher ausgelegte Programme zu entwickeln. Immerhin ist in der Vergangenheit mehrfach gezeigt worden, dass auch Java nicht ganz frei von Sicherheitslücken war. Dennoch – das Konzept von Java ist durch und durch auf Sicherheit ausgelegt, was auch die zahlreichen auf Java basierenden Anwendungen im Bereich Online-Banking über Internet und bei verwandten Vorgängen zeigen.
14.1
Das Java-Sicherheitskonzept
Es gibt viele Aspekte, die bei einem schlüssigen Sicherheitskonzept zu berücksichtigen sind. Statt alle erdenklichen Angriffsszenarien abzudecken, postuliert Javas Sicherheitsmodell potenzielle Ziele, die Angriffen bzw. Angriffskategorien ausgesetzt sind. Insbesondere schützt das SicherheitsmoJava 2 Kompendium
755
Kapitel 14
Java-Sicherheit dell von Java den Hauptspeicher, den Festplattenspeicher eines Clients, das Betriebssystem und den Programmzustand sowie das Netzwerk vor Angriffen folgender Art: Beschädigung der Software auf dem Client-Rechner Zugriff auf Betriebsmittel des Client-Rechners Herausschmuggeln von Informationen aus dem Client-Rechner Identitätsannahme des Client-Rechners Javas Sicherheitsmechanismen greifen – rein auf das Sprachkonzept bezogen – auf vier Ebenen des Computersystems. Die erste Ebene ist die der Sprache an sich und der zugehörige Compiler samt kompilierter Klassen. Die zweite Ebene betrifft die Verifizierung des Bytecodes zur Laufzeit. Dort wird im Wesentlichen darauf geachtet, dass zentrale Sicherheitsregeln eingehalten werden. Ebene drei ist der Classloader, der Klassen beim Laden analysiert und nach verschiedenen Kriterien mit Rechten versieht. Außerdem lässt er nur »freundliche« Klassen passieren. Die letzte Ebene ist ein so genannter SecurityManager, der als abstrakte Java-Klasse zur Laufzeit zerstörerische Verhaltensweisen von Java-Programmen verhindert.
14.1.1
Die Missbrauchsfähigkeiten einer Sprache
Ein wichtiger Ansatzpunkt für die Sicherheit eines Systems sind sprachspezifische Sicherheitslücken durch diverse Zugriffsmöglichkeiten auf lokale Rechnerressourcen. Die C/C++-Sprachmöglichkeiten sind das wichtigste Beispiel für diese Missbrauchsfähigkeiten (bewusst und unbewusst durch nicht mehr kontrollierbare Fehlerquellen) einer Programmiersprache in einer weitgehend ungeschützten Umgebung. Grundsätzlich muss man festhalten, dass der Verzicht von Java auf C/C++-typische und sehr maschinennahe Sprachelemente wie Pointer, Zeigerarithmetik, ungeprüfte Typumwandlung, die Speicherallokation und die anschließende Freigabe über free() – Java nutzt statt dessen mit der Garbage Collection ein konservatives Mark/Sweep-Verfahren – ein erhebliches Maß an Sicherheit gebracht hat. Zum einen sind Java-Programme erheblich stabiler als vergleichbare C/C++-Programme (ein nicht zu verachtender Aspekt), zum anderen ist die Sprache vieler sprachspezifischer Missbrauchsfähigkeiten beraubt. Gerade die Unterbindung von direkten Zugriffen auf Objekte vermeidet erhebliche Bedrohungen. Ganz herheblich tragen die sprachintegrierten Exceptions zur Stabilität von Java bei. Sie ermöglichen in Java definierte und kontrollierte Programmabbrüche.
756
Java 2 Kompendium
Das Java-Sicherheitskonzept
Kapitel 14
Im Detail sind folgende Aspekte des Java-Designs auf maximale Sicherheit ausgelegt: Strikte Objektorientiertheit Java ist strikt objektorientiert, da jede einzelne Datenstruktur (und aus ihr abgeleitete Datenstrukturen) ein vollkommen eigenständiges Objekt erster Klasse darstellt. Das ist nicht nur unter dem Aspekt der Programmierung ein wichtiges Detail, sondern auch aus Sicherheitsgründen. Damit ist sichergestellt, dass in Java alle theoretischen Sicherheitsvorteile der objektorientierten Programmierung (OOP) sowohl in der Syntax als auch in der Semantik bei Programmen wiederzufinden sind. Dies meint im Wesentlichen das Verstecken von Daten hinter privaten Deklarationen. Auf diese darf man entweder gar nicht oder nur über öffentliche Methoden zugreifen, die dann eine gezielte Filterung erlauben. Diese Datenkapselung können wir mit einem kleinen Beispiel demonstrieren. Das Beispiel soll eine Geschwindigkeitsänderung eines Autos (sehr vereinfacht) demonstrieren. Die Geschwindigkeit (tempo) ist in der Klasse PrivateVar als private deklariert. Nach außen wird nur eine Methode tempoAendern() bekannt gegeben, die widerum aber diese Variable nutzt. Wenn nun aus der zweiten Klasse Speed heraus diese private Information genutzt werden soll, kann das nur über die filternde Methode erfolgen, nicht direkt. class PrivateVar { private int tempo=200; int tempoAendern(int gesch) { System.out.println( "Gewuenschte Geschwindigkeit: "+gesch); if(gesch>tempo) { System.out.println("Motor wird abgeriegelt"); gesch=200; } return(gesch); } } Private Variable und öffentliche Methode, die die Variable nutzt class Speed { public static void main(String args[]) { PrivateVar a = new PrivateVar(); /* a.tempo = 300; System.out.println("Geschwindigkeit: " + a.tempo); */ System.out.println("Max: " + a.tempoAendern(300)); System.out.println("Max: " + a.tempoAendern(199)); } }
Java 2 Kompendium
Listing 14.1: Zugriff auf die private Information nur über die öffentliche Methode
757
Kapitel 14
Java-Sicherheit Der Zugriff funktioniert nur so wie in dem nicht auskommentierten Teil demonstriert.
Abbildung 14.1: So funktioniert der Zugriff
Wenn Sie den auskommentierten Teil aktivieren, wird der Compiler den Zugriff nicht gestatten. Abbildung 14.2: Der Compiler erlaubt keinen direkten Zugriff auf private Informationen von außen.
Die strenge Einhaltung von diesen Zugriffsleveln bedeuten die Unterbindung von nicht gewünschen Zugriffen auf Datenstrukturen. Finale Klassen, Variablen und Methoden In Java können Klassen, Variablen und Methoden bekanntlich als final deklariert werden, womit eine weitere Ableitung der Klasse, das Verändern von Variablenwerten und das Überschreiben von Methoden nicht mehr möglich ist. Dementsprechend kann bereits überprüfter Code nicht böswillig verändert werden.
758
Java 2 Kompendium
Das Java-Sicherheitskonzept
Kapitel 14
Strenge Typisierung und sichere Typumwandlung Java ist streng typisiert. Die Typumwandlung wird in Java sowohl statisch als auch dynamisch geprüft, um sicherzustellen, dass der deklarierte Kompilierzeit-Typ eines Objekts mit einem eventuellen Laufzeit-Typen kompatibel ist, selbst wenn das Objekt in einen anderen Typ umgewandelt wird. Keine Pointer Dies ist wahrscheinlich der beste Garant für Sicherheit in Java. Da Java keine Pointer (zumindest nicht im Sinne von C/C++) verwendet, sondern Objektreferenzen, werden sämtliche Umwandlungen und Zugriffe vorab (d.h. vor der eigentlichen Laufzeit) bereits auf Zulässigkeit geprüft. Das Ausschließen von direkten Zeigern stellt immer sicher, dass kein Teil eines Java-Progamms jemals anonym ist. Der Zugriff auf jede einzelne Datenstruktur und auf jedes Code-Fragment kann zurückverfolgt werden. Die statt Pointern verwendeten Array-Strukturen in Java gleichen nicht nur das Fehlen der Pointer aus, sondern steigern die Sicherheit, indem die Grenzen eines Arrays strikt festgelegt sind. Zudem ist jedem einzelnen Java-Objekt ist Hash-Code (Kontrollcode) zugeordnet. Das bedeutet, dass der Status eines Java-Programms jederzeit aufgezeichnet werden kann. Damit sind aber nicht nur unbewusste Fehler vermieden, ebenfalls sind die Missbrauchsfähigkeiten eingeschränkt bzw. leichter erkennbar. Thread-sichere Datenstrukturen Java ist Multithreading-fähig. Dies erzwingt in Bezug auf Sicherheit und Stabilität einen Thread-sicheren Zugriff auf Datenstrukturen und Objekte. Java besitzt einen solchen, der viel zur allgemeinen Stabilität des Systems beiträgt. Sicherer Ansatz des Methoden- und Variablen-Aufrufs Java verwendet einen besonderen Ansatz, um Funktionen aufzurufen. Normalerweise rufen PC-Programme Funktionen über eine numerische Adresse auf. Da diese Adresse eine numerische Folge ist und diese Folge vom Programmierer beliebig programmiert werden kann, kann eine beliebige Zahl genommen werden, um dem Programm zu sagen, wie es eine Funktion ausführen soll. Damit wird eine Anonymität aufrecht erhalten, mit der es unmöglich ist herauszufinden, welche Funktionen bei der Programmausführung tatsächlich verwendet werden. Java seinerseits verwendet Namen zum Aufruf von Methoden und Variablen. Auf Methoden und Variablen kann allein mit dem Namen zugegriffen werden. Zu bestimmen, welche Methode und Variablen verwendet werden, ist also einfach. Diese Verifizierung wird dazu verwendet, sicherzustellen, dass der Bytecode nicht beschädigt oder verändert wurde und die Anforderungen von Java als Sprache erfüllt. Zusammenfassend kann man festhalten, dass Java also auf der Sprach- und Compilerebene bereits extrem sicher ist. Java 2 Kompendium
759
Kapitel 14
Java-Sicherheit
14.1.2
Viren
Viren innerhalb von Fremdsoftware sind ein Aspekt, gegen den bisher kaum schlüssige Konzepte auf der Ebene der Programmiersprachen und Entwicklungsumgebungen präsentiert wurden. Seit Jahren empfehlen Experten dringend, jedes fremde Programm und jeden fremden Datenträger auf Viren zu überprüfen, bevor man damit arbeitet. Und im Internet verfuhr man in der Vergangenheit oft so, als befände man sich in Fort Knox. Java bietet nun auf Sprachebene diverse Kontrollmöglichkeiten gegen Viren im Javacode und überprüft defaultmäß ig den Bytecode. Wie diese Kontrolle im Detail funktioniert, kann am besten in Zusammenhang mit unkontrollierten Zugriffen auf Systemressourcen erklärt werden.
14.1.3
Unkontrollierte Systemzugriffe
Eine ähnliche Gefahr wie Viren sind unkontrollierte Festplattenzugriffe (Löschen oder Verändern von Dateien, Formatieren von Datenträgern) und sonstige Zugriffe auf Systemressourcen. Zwar ist die konkrete Thematik hier noch komplexer als bei Viren, die Logik ist allerdings identisch. Auch im Falle von Java-Applets (oder vor allem ActiveX-Controls) werden Objekte auf dem lokalen Rechner abgelegt, deren genaue Funktionalität nicht immer vollständig klar ist. Microsofts ActiveX-Technologie wird von vielen Experten als das derzeit grö ß te Sicherheitsrisiko der EDV-Welt angesehen. Wer sagt denn, dass das nette ActiveX-Control nur ein harmloses Spiel ist und die permanenten Festplattenzugriffe ausschließlich Spielstände abspeichern? Man muss sich immer darüber im Klaren sein, dass es sich bei jedem dieser Objekte um eine Art lauffähige Programm handelt, das durchaus ein anonymes (schädliches) Doppelleben führen kann. Wenn im Detail unbekannte Objekte Schreiboperationen auf der Festplatte ausführen wollen, sollten Alarmglocken klingeln. Bei aller Euphorie über Java-Applets und sonstiger toller Internetanimationen darf man nicht vergessen, dass über das Netz (oder ggf. von lokalen Datenträgern) fremde Anwendungen auf den Rechner gelangen, denen man erst einmal ein gesundes Misstrauen entgegenbringen sollte. Java stellt da mit seinem Sicherheitskonzept einen Meilenstein dar. Bei Java-Applets können unkontrollierte Festplattenzugriffe – sogar von vollkommen unbekannten Applets – einigermaßen beherrscht werden. Verantwortlich dafür ist im Wesentlichen der Container (also der Browser oder der Appletviewer). Dieser analysiert mithilfe des Applet-Classloaders bereits beim Laden aus dem Netz den Applet-Code unter anderem auf Viren und Festplattenzugriffe oder andere unerlaubte Befehle. Damit wird bereits eine Pforte aufgebaut, die viele subversive Klassen erst gar nicht überwinden können. Und falls doch, unterbindet der Container – je nach internen Einstellungen – diese Zugriffe mithilfe eines permanent laufenden Hintergrundprozesses. Selbst wenn es also ein »schlechtes« Applet geschafft hätte, den 760
Java 2 Kompendium
Das Java-Sicherheitskonzept
Kapitel 14
umfangreichen Verifzierungsprozess von Java zu umgehen, wäre der Schaden, den es anrichten könnte, doch ziemlich begrenzt, da Java-Applets nur in einer eingeschränkten Umgebung – dem so genannten Sandkasten (Sandbox) – ausgeführt werden und dort Restriktionen zu setzen sind. Sie können sich ja bei der Sicherheitseinstellung des Appletviewers oder eines Browsers ansehen, welche Einstellungen dort möglich sind. Innerhalb dieser Containerumgebung hat ein Java-Applet normalerweisee nicht die Erlaubnis, bestimmte gefährliche Funktionen auszuführen, es sei denn, der Endanwender gibt explizit seine Erlaubnis. Aber wie erfolgt genau die Verifizierung des Bytecodes?
14.1.4
Verifizierung des Bytecodes
Vor der Ausführung einer Applikation durch einen Browser oder den Appletviewer bzw. den Java-Interpreter wird jeder Bytecode diversen Tests unterzogen. Es wird beispielsweise überprüft, dass keine Zugriffsbeschränkungen verletzt werden, dass Methoden keine unzulässigen Argumente enthalten oder dass der Stack nicht überläuft. Typinformationen und Anforderungen Einen wesentlichen Anteil an der Verifizierung des Bytecodes bilden die Informationen über Typen. Java-Bytecode enthält mehr Typinformationen als der Interpreter eigentlich benötigt, beispielsweise Symboltabellen. Dadurch kann zur Laufzeit sichergestellt werden, dass Java-Objekte und -Daten nicht unbemerkt manipuliert werden. Vor und nach der Ausführung eines Java-Programms hat jeder Wert in dem Stackbereich und jede Variable einen bestimmten Typ. Man nennt dies den Typzustand der Ausführungsumgebung. Dieser Typzustand ist statistisch zu überwachen und kann dafür verwendet werden, Pfadangaben und Verzweigungen eines Programms zu verfolgen. Außerdem kann mithilfe der zusätzlichen Typeninformationen ein spezieller Java-Mechanismus aktiv werden, der Verifier genannt wird.
14.1.5
Der Verifier
Der Bytecode-Verifier gehört zur Laufzeitumgebung von Java, also der JVM. Man kann ihn sich als ersten Grenzposten für eine fertige Klasse vorstellen, welchen die Klasse passieren muss, um überhaupt erst in die Laufzeitumgebung zu gelangen. Nur eine Klasse, die sich bzgl. wichtiger Aktionen als unbedenklich ausweisen kann, darf diese äußere Grenze der Laufzeitumgebung überschreiten. Anhand der zusätzlichen Typeninformationen in jeder .class-Datei überprüft der Bytecode-Verifier den vollständigen Bytecode und kontrolliert die Typen hinsichtlich aller Parameter, Namensraumkonflikte, Argumente und Ergebnisse. Damit kann man garanJava 2 Kompendium
761
Kapitel 14
Java-Sicherheit tieren, dass Bytecode, der vom Verifier nicht moniert wurde, auf keinen Fall Stack-Overflows (sowohl nach oben als auch nach unten) erzeugen, ungültige Registerzugriffe ausführen, falsche Parameter, Argumente oder Returnwerte verwenden oder ungültige Konvertierungen von Daten und Typen sowie illegale Zugriffe auf Objektfelder erzeugen. Letzteres bedeutet, dass der Bytecode-Verifier auf strikte Einhaltung von public, private, package und protected bei Methoden und Variablen prüft. Der Verifier trägt also ebenfalls viel zu einer – rein technischen – Sicherheit von Java bei.
14.1.6
Der Classloader
Etwas höher als der Verifier ist der so genannte Classloader (Klassenlader) als ein weiterer Grenzposten gegen unbefugte Sicherheitsverletzungen aufgebaut. Wenn eine neue Klasse in ein System geladen wird, muss sie auch diesen Grenzposten passieren. Je nachdem, von wo die neue Klasse in das System geladen wird, wird sie vom Classloader unterschiedlich behandelt. Standardmäß ig gibt es drei unterschiedliche Szenarien, von wo eine neue Klasse geladen werden kann: 1.
Aus dem Internet
2.
Aus einem per Firewall geschützten lokalen Netzwerk
3.
Vom lokalen Rechner selbst
Denkbar sind jedoch beliebig viele Szenarien. Beim lokalen Laden (die Definition von lokal war bis zum JDK 1.1 mit dem CLASSPATH verbunden, worauf nachfolgend noch eingegangen wird) von der Festplatte lädt und überprüft übrigens defaultmäß ig nicht mehr der Applet-Classloader, sondern der File-Loader des Dateisystems, was unter Umständen ein erhebliches Sicherheitsrisiko sein kann. Prinzipiell sind Applets grö ß ere Sicherheitsrisiken als eigenständige Applikationen. Wenn ein fremdes Applet über Diskette oder CD auf den Rechner und dort in scheinbar sichere Verzeichnisse, d.h. Verzeichnisse innerhalb der ursprünglichen CLASSPATHAngabe bzw. in den als sicher empfundenen Suchpfad des SDK 2 gelangt, wird es nicht mehr so intensiv überprüft. Ein solches Applet sollte sehr vertrauenswürdig sein, denn es hat damit meist einige Rechte, die der Applet-Loader sonst nicht gestatten würde. Beispielsweise können diese Applets – bei entsprechender Einstellung – von der lokalen Festplatte lesen und auf diese schreiben, Bibliotheken auf dem Client laden, externe Programme auf dem lokalen Rechner ausführen, sich der Überprüfung des Bytecode-Verifiers entziehen und sogar im Prinzip die virtuelle Maschine von Java verlassen.
762
Java 2 Kompendium
Das Java-Sicherheitskonzept
Kapitel 14
Der Classloader unterbindet auf jeden Fall das Ersetzen einer Klasse in einem höher priorisierten Bereich (etwa in einem per Firewall geschützten lokalen Netzwerk) durch eine Klasse aus einem niedriger priorisierten Bereich (etwa aus dem Internet). Insbesondere lässt der Classloader nicht zu, dass eine Klasse auf dem lokalen System durch eine Klasse von »außen« unbemerkt ersetzt wird. Zudem unterbindet der Classloader einen Aufruf von Methoden einer höher priorisierten Klasse durch Klassen aus einem niedriger priorisierten Bereich, es sei denn, diese Klassen sind explizit als public deklariert. Und last but not least unterbindet der Classloader ein Aufruf von Methoden eines Applets durch ein anderes Applet, es sei denn, dieses erlaubt es ausdrücklich. Dahinter steckt eine Technik, die Applets der gleichen Quelle (Host oder lokaler Rechner) in einem »Namespace«-Paket zusammenfasst. Damit teilt der Classloader die Welt der Applets in kleine Gruppen auf, denen von vornherein unterschiedliche Sicherheitsrisiken zugeordnet werden. Als Defaultwert überprüft der Classloader nur solche Klassen, die von außen (also von einem Host, einem lokalen Netzwerk oder auch einem Verzeichnis außerhalb des sicheren lokalen Pfads) kommen. Die getrennten Namensräume sind die Begründung, warum es wie oben beschrieben nicht möglich ist, Klassen auszublenden und durch manipulierte Klassen von außerhalb zu ersetzen. Wird eine Klasse benötigt, sucht der Classloader immer zuerst innerhalb des eigenen lokalen Namenraums und dann erst in weiteren Namensräumen. Damit haben lokal installierte Klassen immer Vorrang gegenüber den Klassen, die aus einem Netzwerk bezogen werden. Dieser Vorgang setzt sich nach der Priorität nach unten fort.
14.1.7
Der Sicherheitsmanager
Der SecurityManager ist eine Klasse innerhalb vom Java-System (als abstract definiert), die als zentrale Entscheidungsstelle der Sicherheitspolitik eines Systems in Bezug auf Applets verstanden werden kann. Sie ist die vierte Ebene in der Sicherheitsphilosophie und die stärkste Stufe. Der SecurityManager überprüft als letzte Instanz der Sicherheitskette alle sicherheitsrelevanten Operationen eines Java-Programms zur Laufzeit. Das bedeutet im Fall von Applets, dass selbst ein Applet, das sogar den Classloader überwunden hat, sich nicht sicher fühlen darf. Der SecurityManager wird immer automatisch beim Start eines Browsers bzw. des Appletviewers gestartet und bleibt so lange im Hintergrund aktiv, bis der Browsers bzw. der Appletviewer wieder beendet wird. Diese Implementierung des SecurityManager lässt sich nicht abstellen. Wird innerhalb eines Applets eine unerlaubte Operation ausgeführt, löst dies eine SecurityException aus. Sicherheitsrelevante Operationen eines Applets zur Laufzeit sind u.a. das Lesen und Schreiben von Dateien und der Aufbau von Online-Verbindungen. Die Art der Beschränkung durch den SecurityManager hängt jedoch sehr stark von Umgebung der Applets ab. Dies bedeutet, dass der SecurityManager zwischen Applets unterscheidet, die aus dem Netz oder vom Java 2 Kompendium
763
Kapitel 14
Java-Sicherheit lokalen System geladen wurden. Des Weiteren ist es ein massiver Unterschied, ob ein Applet in einem Browser (und welchem) gestartet wird oder im Appletviewer. Ein Applet gilt übrigens nur dann als lokal, wenn es sich im CLASSPATH (bzw. JDK 1.1) bzw. im bei der Installation festgelegten Suchpfad des SDK 2 befindet. Nur auf dem lokalen System abzulegen genügt nicht. Dies bedeutet, dass Klassen, die sich in einem so spezifizierten Verzeichnis befinden, gegenüber dort nicht abgelegten Klassen erweiterte Rechte haben. Zusammengefasst werden geladene Klassen in Java in grö ß ere Gruppen, welchen dann unterschiedliche Rechte zugeordnet werden. Das dahinter liegende Konzept heißt Name Space und bedeutet, dass jede geladene Klasse nach ihrem Namen und dem Herkunftsort identifiziert werden kann. Die diversen Sicherheitseinstellungen kann man grob in Lese- bzw. Schreibzugriffe auf lokale Ressourcen, Aufbau von Online-Verbindungen über Netzwerke und die Manipulation eines Threads durch einen anderen Thread klassifizieren. In Bezug auf Lese- bzw. Schreibzugriffe auf lokale Ressourcen und Netzzugriffe kann man von der Java-Theorie her Applets in vier Sicherheitsstufen eingliedern: unrestricted! Ungehinderte Lese- bzw. Schreibzugriffe auf lokale Ressourcen und Netzzugriffe firewall! Ungehinderte Lese- bzw. Schreibzugriffe auf lokale Ressourcen und Netzzugriffe innerhalb einer Firewall source! Das Applet darf bzgl. Lese- bzw. Schreibzugriffe auf lokale Ressourcen nicht zugreifen und keine allgemeinen Netzzugriffe ausführen, jedoch innerhalb des Ursprungsort (dem Host, von dem es stammt) darf das Applet alles machen und damit auch dorthin Kontakt aufnehmen. local! Keinerlei Lese- bzw. Schreibzugriffe auf lokale Ressourcen und keinerlei Netzzugriffe. In Bezug auf Sicherheit sind die Defaulteinstellungen des Appletviewers recht offen. Der Appletviewer überlässt dem Anwender sehr viel Freiheit, welche Sicherheitseinstellungen er vornehmen möchte. Viele Browser sind bzgl. der Sicherheitsvorkehrungen bei Java-Applets sehr viel restriktiver. Bereits für lokale Applets lassen viele Browser keine Festlegung – insbesondere kein Löschen – von Lese- und Schreibverzeichnissen oder -dateien zu. Lediglich das Lesen von einigen Feldern (etwa user.name) oder Bibliotheken, Fensteröffnungen ohne Warnung und die relativ freie Online-Verbindung werden zugestanden. Nicht lokale Applets werden sogar bei einigen Browsern fast vollständig kastriert. Außer einem Hilferuf zum eigenen Host dürfen sie fast nichts (außer bunte Bilder im Browser malen). So etwas ist
764
Java 2 Kompendium
Das Java-Sicherheitskonzept
Kapitel 14
als Defaulteinstellung sicher gut, aber ob obendrein eine Freigabe durch einen kundigen Anwender zu unterbinden ist, darf diskutiert werden. Es wird aufgefallen sein, dass bisher im Zusammenhang mit dem SecurityManager fast nur von Applets die Rede ist. Dies ist kein Zufall, denn eigenständige Java-Applikationen sind dessen Restriktionen nicht automatisch unterworfen. Eine eigenständige Java-Applikation darf defaultmä ß ig innerhalb des Java-Interpreters fast alles tun. Dies ist sinnvoll, wenn man beispielsweise eine Dateiverwaltung oder eine Textverarbeitung in Java erstellen möchte. Um eigenständige Java-Applikationen der Kontrolle des SecurityManagers zu unterwerfen, muss man explizit die Klasse SecurityManager aus dem Paket System im Source implementieren. Installieren des SecurityManagers erfolgt am besten in der ersten Zeile der main()-Methode. Dazu kann die folgende Source-Zeile verwendet werden: System.setSecurityManager(new MeinSpeziellerSicherheitsChef());
Wenn der SecurityManager eine bestimmte Operation unterbinden soll, muss die dafür relevante Methode entsprechend überschrieben werden. Wenn jedoch der SecurityManager in einer Applikation implementiert wurde, wird jede nicht überschriebene Security-Methode eine SecurityException auslösen, sofern das zugehörige Ereignis ausgelöst wird. Deshalb ist hier viel Sorgfalt vom Programmierer gefordert.
14.1.8
Digitale Unterschriften eines Applets und Verschlüsselung in Java
Eine wichtige Neuerung im Sicherheitsbereich vollzog Sun mit der Version 1.1 des JDK im ersten Quartal 1997. Seit dieser Version können Applets und Daten (Bilder, Sounds usw.) mit einer digitalen Unterschrift versehen werden. Dadurch kann ein Applet eindeutig seinem Hersteller zugeordnet werden. Umgekehrt kann man bei einer fehlenden digitalen Unterschrift eine Ausführung des Applets unterbinden. Die Sicherheitsschnittstelle von Java bietet seit der Version 1.1 eine Unterstützung für die so genannte Public-Key-Verschlüsselung an, was Java in Bezug auf das Versenden von Daten über das Internet erheblich aufgewertet hat. Die Tools des SDK 2 und das dort außerordentlich erweiterte Sicherheitskonzept hat gerade in diese Richtung noch einmal erhebliche Fortschritte gebracht.
14.1.9
Native Code
Ein erhebliches Sicherheitsproblem bei der Analyse eines Java-Programms ist die Möglichkeit zur Einbindung von nativem Maschinencode in Java. Im Gegensatz zu dem Java-Zwischencode (einem relativ leicht zu analysierenden Bytecode) lässt sich Maschinencode nicht so einfach untersuchen. Java
Java 2 Kompendium
765
Kapitel 14
Java-Sicherheit versucht, dieses Problem mit dem SecurityManager in den Griff zu bekommen, der die systemkritischen Ressourcen sichert. Trotzdem bleibt hier sicher ein Restrisiko, und es ist eines der wichtigsten Argumente gegen die Verwendung von nativem Code in Java-Programmen (neben dem Verlust der Plattformunabhänigkeit).
14.1.10
Weitere unerwünschte Aktionen
Es gibt natürlich Sicherheitsfragen, die nicht ohne Weiteres in Java behandelt werden können. Es kann nicht Aufgabe der Entwicklungsumgebung sein, hier einen absoluten Schutz zu garantieren. Dazu zählen etwa die übermä ß ige Beanspruchung der Rechnerleistung oder des Hauptspeichers des Clients, etwa durch den Start einer beliebigen Menge an Threads, ein Aufrufen von Fenstern über eine Endlosschleife oder auch unerwünschte Inhalte von Applets. Eine andere Art von Sicherheitsverletzungen können aus den immer schon vorhandenen Schwächen der Internet-Protokolle entstehen. Hier hat Java keinerlei Kontrollmöglichkeiten auf technischer Ebene. Weitere denkbare Aktivitäten von Java-Applets und Programmen sind Aktionen wie Sperren von Ressourcen, unerwünschten Effekte auf Ausgabegeräte oder Diebstahl der Identität eines Benutzers, um mit dieser Aktivitäten auszuführen (etwa Online-Überweisungen). Java unterbindet solche Aktionen wie wir gesehen haben weitgehend. Vollkommen geht so etwas aber technisch nie, sonst kann man keine funktionstüchtigen Programme erstellen. Aber in diesem Bereich sind andere aus dem Internet kommende Programme (vor allem ActiveX-Controls) wahre Meister der potenziellen Schädigung, wie diverse Tests gezeigt haben. Damit diese Behauptung nicht ganz ohne Fundament im Raum steht (und die Qualität des Java-Sicherheitskonzeptes noch deutlicher wird), soll kurz das ActiveX-Sicherheitskonzept (?) angerissen werden.
14.2
ActiveX-Sicherheitskonzept im Vergleich
Um ActiveX-Controls im Vergleich mit Java-Applets zu sehen, wollen wir zuerst kurz klären, was es mit diesen ActiveX-Controls überhaupt auf sich hat.
14.2.1
Was sind ActiveX-Controls?
ActiveX-Controls werden oft als Microsoft-Alternative zu Java-Applets gesehen. Der Begriff ActiveX bezeichnet jedoch nach Aussage von Microsoft keine einzelne Technik oder SDK, sondern ist ein übergeordneter Name für Microsofts Internet und Multimedia-Technologien. Unter ActiveX ist eine Verbindung von vielen verschiedenen Entwicklungstechniken zu verste-
766
Java 2 Kompendium
ActiveX-Sicherheitskonzept im Vergleich
Kapitel 14
hen, die alle auf dem Component Object Model (COM) und/oder der Win32 API aufbauen. ActiveX ist ein ganzes Set von offenen Techniken, die die Leistungsfähigkeit von PCs auf das Internet/Intranet und Netzwerk allgemein übertragen soll. Dieses Set wird permanent von Microsoft weiterentwickelt und in Windows integriert. Insbesondere versteht Microsoft die ActiveX-Technologie nicht als direkte Konkurrenz zu Java, sondern als eine Ergänzung. Allerdings sollten sich dann die Entwickler darüber im Klaren sein, dass sie eine Haupteigenschaft von Java aufgeben, wenn sie ActiveX mit Java verbinden – die Plattformunabhängigkeit. ActiveX ist nämlich im Gegensatz zu HTML oder Java explizit nicht plattformunabhängig, sondern läuft (zurzeit) nur auf einer Computerarchitektur und einer Betriebssystemfamilie – INTEL-PCs und WINDOWS (und mit Einschränkungen auf Power Macintosh). Von der Einschränkung des potenziellen ActiveX-“Kundenkreises« auf die WINTEL-Plattform verspricht sich Microsoft ganz massive Vorteile. ActiveX-Controls sind in der Lage, alle Leistungen des Betriebssystems Windows auszuschöpfen. Sie sind eine direkte Nachfolgegeneration der OCX-Controls, die wiederum ja eine speziell für die 32-BitUmgebung von Windows 95/NT hergeleitete Weiterentwicklung der VBXControls sind. Ein ActiveX-Control kann also auf alle Möglichkeiten des Win32-API zurückgreifen und wird auch als ein in eine HTML-Seite eingebundenes Element genauso aussehen und zu bedienen sein wie ein »normales« WindowsSteuerelement. Im Mittelpunkt der Microsoft-Internetphilosophie steht die OLE-Funktionalität (Object Linking and Embedding, Objekte verbinden und einbetten) von Windows. Lange war die OLE-Technik nur als Verbindung von dynamischem Linken (der DDE = Dynamic Data Exchange) und statischem Einbetten (in etwa wie der Datenaustausch über die Zwischenablage), beziehungsweise als eine Erweiterung dieser beiden Techniken um integrierte Hinweise auf ihre Ursprungsanwendungen bekannt. Insbesondere konnten die OLE-Objekte lange nur lokal, das heißt auf einem Rechner eingesetzt werden. Als Beispiel sei die Einbindung einer EXCEL-Tabelle in WINWORD genannt. Im Rahmen der Netzwerkentwicklung von Windows wird die lokale Einschränkung aufgehoben. Die Weiterentwicklung von OLE (DCOM = Distributed Component Object Model) war schlichtweg die Übertragung der OLE-Technik auf Netzwerke und vor allem das Internet. Mit dieser Technik spielt es keine Rolle mehr, ob ein Objekt auf dem lokalen Rechner oder einem beliebigen Server im Netz beheimatet ist. Auf Grund der integrierten Hinweise auf ihre Ursprünge wird bei einer Aktivierung eines externen Elements der zugehörige Rechner kontaktiert und dort die notwendige Aktion ausgeführt.
Java 2 Kompendium
767
Kapitel 14
Java-Sicherheit Eine besondere Art von OLE-Objekten sind die Windows-Steuerelemente, die Controls. Auch bei den ActiveX-Controls handelt es sich wie schon erwähnt um eine Weiterentwicklung der herkömmlichen OLE-Controls. Vor allem sind die ActiveX-Controls gegenüber den OCX-Controls auf das Wesentliche reduziert und damit verglichen mit diesen bedeutend kleiner. Die OCX-Controls schleppen eine Unmenge an im Prinzip überflüssigem Ballast aus der MFC (Microsoft-Foundation-Classes) mit, der hier durch ein neues Konzept weggelassen werden kann. ActiveX-Controls verzichten zudem auf eigene Fenster, sondern delegieren diese Aufgabe an den Container, beispielsweise einen Webbrowser. Neben der Verkleinerung der Controls bringt dieses Verfahren einen weiteren Vorteil – die Controls sind nicht mehr an die Fensterform gebunden. Jede denkbare Form ist im Prinzip realisierbar. Allerdings hat der Container dann eine Menge zu tun, um »Löcher« oder »Flicken« im Bildschirm zu verhindern und Benutzerinteraktionen des Controls zu verarbeiten. ActiveX-Controls lassen sich wie Java-Applets in jede HTML-Seite einbinden. Die ActiveX-Controls werden wie Java-Applets bei Bedarf automatisch aus dem Internet auf den Client geladen und installiert. Das HTML-Tag bindet das ActiveX-Control in die Webseite ein. Diese kann ja seit HTML 4.0 auch zum Einbinden von beliebigen Objekten (insbesondere auch Applets) in eine Webseite genutzt werden. Ursprünglich wurde die Object-Tag-Syntax nur für ActiveX-Controls verwendet: [ActiveX-Control-Eigenschaften]
Die neuere Variante des Tags referenziert ActiveX-Controls etwas anders. Etwa so, als ob man ein Plug-In für die JVM als ActiveX-Control angeben möchte:
Bei beiden Varianten gilt aber, dass bei der Referenzierung mit CLASSID das Control über einen weltweit eindeutigen 128-Bit-Wert identifiziert und mit WIDTH=[Wert] HEIGHT=[Wert] die Grö ß e des Controls festgelegt wird. Über die CLASSID kann ein Browser entscheiden, ob ein Control bereits geladen wurde 768
Java 2 Kompendium
ActiveX-Sicherheitskonzept im Vergleich
Kapitel 14
und ob es ggf. eine neuere Version eines bereits vorhandenen Controls ist. Auf dieser CLASSID baut jedoch zugleich das Sicherheitskonzept von ActiveX auf.
14.2.2
Sicherheitskonzept von ActiveX
Für ActiveX-Controls gibt es eigentlich gar kein echtes Sicherheitskonzept, denn der Anwender muss im Wesentlichen einer Registrierungsnummer des Controls vertrauen, die als digitale Unterschrift über spezielle Tools der ActiveX-SDK in diese eingebaut wurde. Sofern ein Anwender ein ActiveXControl auf seinen Rechner lädt, wird diese digitale Unterschrift überprüft und – falls der Browser entsprechend konfiguriert ist – bei fehlender Registrierungsnummer das Laden verweigert. Diese Überprüfung lässt sich zu allem Überfluss auch noch bei manchen Browsern vollständig deaktivieren. Wer nicht glaubt, dass ActiveX-Controls böse Dinge mit dem lokalen Rechner anstellen können, wenn die Sicherheitsschranke zum Download nicht zertifizierten Codes deaktiviert ist, sollte im Internet einmal gezielt nach Demos suchen. Es gibt zahlreiche Webseiten, die als Demo für die Unsicherheit von ActiveX-Controls dienen. So gab es schon sehr früh das Control Exploder (kein Schreibfehler – http://www.halcyon.com/mclain/ActiveX), das einen PC aus einer Webeite heraus sauber herunterfährt. Wohl bemerkt, es handelt sich nicht um einen Virus, sondern ein ActiveX-Control zu Demonstrationszwecken. Auf der Seite finden Sie zahlreiche interessante Hinweise zu dem Thema. Abbildung 14.3: ActiveX oder wie man Nuklearbomben in Webseiten einbindet
Java 2 Kompendium
769
Kapitel 14
Java-Sicherheit Microsoft teilt zwar die Internetwelt in seinem Browser in vier Zonen ein, für die unterschiedliche Sicherheitstufen eingestellt werden (Internetzonen, Lokale Intranetzone, Zone für vertrauenswürdige Seiten und Zone für eingeschränkte Seiten). Je nach eingestellter Stufe (von hoch bis angepasst) werden verschiedene Maßstäbe an das Zertifikat gestellt. Die einzelnen Zonen haben jeweils voreingestellte Sicherheitslevel, sind also eigentlich nur eine andere Ausdrucksweise für die Sicherheitslevel (und bieten zusätzlich etwas Verwaltungskomfort). Nur in der niedrigen Stufe kann die Überprüfung der Zertifizierung vollkommen abgeschaltet werden. Aber noch einmal zurück zu der digitalen Unterschrift. Was bringt diese an Sicherheit und woher kommt sie überhaupt? Diese digitale Unterschrift bekommt ein ActiveX-Control, sobald es sich (d.h. sein Entwickler) bei einer von Microsoft lizensierten Organisation registrieren lässt, etwa bei der Firma Verisign. Die Funktion des ActiveX-Control wird allerdings nicht überprüft und es wird damit nicht gesagt, dass das Control harmlos ist. Aber zumindest weiß der Anwender im Schadensfall, wer ihm die Festplatte zerstört hat. Wenn das Control über das Netz geladen wird, erscheint ein Hinweis, dass das Control von der Firma xyz als vertrauenswürdig eingestuft wurde. Das hilft zwar nichts, aber es beruhigt doch ungemein, dass Microsoft zumindest glaubt, niemand bringe ein unregistriertes (d.h. ohne oder mit gefälschter ID) Control in Umlauf. Außerdem hat noch niemand in der EDV-Welt etwas von fehlerhaften Programmen gehört. Sämtliche Naturgesetze stellen doch sicher, dass Programme nie Fehler haben. Oder ist Ihnen jemals ein Fehler in einem Programm untergekommen? Wie kann da ein ActiveX-Control Fehler haben? Eine Überprüfung ist also rein naturwissenschaftlich überflüssig. Sie stimmen sicher zu, dass dies unmöglich ist, oder :-)?! Aber im Ernst, das Registry-and-Trust-Sicherheitskonzept von ActiveX-Controls liegt auf dem Niveau der Aussage »Für was brauche ich einen Sicherheitsgurt, ich habe doch ein vierblättriges Kleeblatt im Handschuhfach« (Bill Gates möge entschuldigen). Nicht umsonst lassen sich mit (zugegeben meist unregistierten) ActiveX-Controls alle möglichen Dinge anstellen, die einem Anwender schaden können. Dagegen kann man glatt sämtliche Schwachstellen im Java-Komzept fast vergessen. Wenn Sie wollen, können Sie die (Missbrauchs-)Möglichkeiten von ActiveX-Controls gerne mit der Datei activeX.html testen. Sie finden sie auf der Buch-CD oder unter http:// rjs.de/activeX.html (Groß- und Kleinschreibung beachten)1. Laden Sie die Datei im Internet Explorer mit herunter gelassenen Toren, d.h. mit aktivierten ActiveX-Controls (auch nicht-signierte) und geöffneter Internet-Verbindung. Das in der Webseite integrierte ActiveX-Control zeigt Ihnen im Internet Explorer im Rahmen der Webseite den Inhalt der Festplatte C: an. Sie 1
770
Die Webseite http://www.astalavista.de, wo diverse Hacker- und Auswertungsmöglichkeiten im Rahmen einer HTML-Seite (meist recht harmlose Techniken wie Cookies oder Scripte) gezeigt werden, verwendet das ActiveX-Control als Highlight auch.
Java 2 Kompendium
Bekannte Sicherheitslücken der Java-Vergangenheit
Kapitel 14
können beliebig Verzeichnisse öffnen, Ansichten wechseln und auch Kontextmenüs aktivieren und deren Befehle nutzen. Mehr an Schaden verursacht das Control erst einmal nicht, aber dennoch – es ist eine Einladung zum offenen Missbrauch des eigenen Rechners. Abbildung 14.4: Der Dieb klopft an (zumindest, wenn nicht alle Sicherheitseinstellungen vollkommen deaktiviert sind).
Abbildung 14.5: Der Dieb ist drin und wildert auf der Festplatte.
Es ist bezeichnend, dass die Unsicherheit von ActiveX auf der im August stattgefundenen HIP 97, dem grö ß te Hackertreffen Europas in Almere, Holland, mit 2500 Teilnehmern eines der Hauptthemen war. Mehr Informationen zum ActiveX-Sicherheitskonzept und ActiveX im Allgemeinen (FAQ) gibt es im Internet unter der bereits genannten Adresse (Contra) http://www.halycon.com/mclain/activeX/2 oder als Pro-Anwalt http://www.microsoft.com/activex/ bzw. http://www.microsoft.com/com/.
14.3
Bekannte Sicherheitslücken der Java-Vergangenheit
Selbstverständlich gab und gibt es auch in Java diverse Sicherheitslücken. Absolute Sicherheit ist eine Illusion und kann man höchstens von der Religion erwarten. Darüber wird es sicher keine Diskussionen geben. 2
oder – falls die Seite verlagert wurde – in einem anderen Verzeichnis unter diesem DNS-Namen
Java 2 Kompendium
771
Kapitel 14
Java-Sicherheit
Abbildung 14.6: Pro-ActiveXControl-Infos von Microsoft
Einige Bugs in Java wurden in der Vergangenheit ziemlich bekannt. Deshalb sollen sie angesprochen werden. Die Auswahl erhebt aber keinen Anspruch auf Vollständigkeit.
14.3.1
Der Bytecode-Bug
Manche Festplattenzugriffe durch Applets sind nicht destruktiv und es ist sicher nicht jedermanns Sache, vor dem Start eines Applets jedes Mal die Optionen des Browsers umzustellen, wenn man ein Applet verwenden will, das Systemzugriffe benötigt. Aber wer weiß schon genau, was er dann auslöst, wenn er – sogar bewusst – Festplattenzugriffe erlaubt? Zwar lassen sich viele destruktive Verhaltensweisen eines Applets abfangen, jedoch in älteren Java-Versionen konnten die Sicherheitseinstellungen von Containern von Java-Applets bzgl. Festplattenzugriffen durch Simulation eines Laufzeitfehlers ausgehebelt werden. Genauer handelte es sich dabei um einen Bug im Bytecode-Verifizierer, der eine Sicherheitslücke im Java-System bedeutete. Laut Aussagen der Entdecker des Fehlers (Drew Dean, Ed Felten und Dan Wallach) konnte ein Applet fähig sein, Maschinencode zu erzeugen, der in der Lage war, ein Applet mit gleichen Rechten auszustatten, wie sie der Anwender auf dem Rechner besitzt. Anschließend durfte ein Applet alle Befehle aufrufen, die dem Anwender erlaubt waren. Der Fehler lag in dem Teil des Interpreters, der über das Netz geladene Applets auf ungültige oder verbotene Befehle hin überprüft. Ein Applet konnte bei genauer Kenntnis dieses Fehlers den Restriktionsmechanismus außer Kraft setzen. Dieser Fehler ist seit Jahren beseitigt.
772
Java 2 Kompendium
Bekannte Sicherheitslücken der Java-Vergangenheit
14.3.2
Kapitel 14
Schwarze Witwen und der DNS-Bug
Neben der Gefahr eines destruktiven Verhaltens auf Datenträgern lauert hinter Java-Applets immer ein weiteres Schweinchen. Spionage! Wenn Sie Online arbeiten, können Sie selbstverständlich nicht nur Daten empfangen. Bewusst versenden Sie E-Mails, Dateien oder permanent Anforderungen für Webseiten oder FTP-Pakete. Applets können im Prinzip Mechanismen integriert haben, die ebenfalls – allerdings heimlich – Daten versenden, wenn eine Online-Verbindung besteht, z.B. den Inhalt Ihrer Datenträger oder die Adressen von mitprotokollierten Internetseiten. Keine sonderlich beruhigende Vorstellung. Von der Java-Theorie her darf es das zwar nicht geben, aber die ersten Spionage-Applets wurden Mitte 1996 unter dem Namen »Schwarze Witwen« bekannt. Zwar lassen sich im Prinzip von vielen Browsern bzw. dem Appletviewer sowohl Lesezugriffe auf die Festplatte als auch die Kommunikation mit Hosts unterbinden, aber Java war in der Vergangenheit in der Lage, auf einigen Plattformen über den Umweg eines DLLFunktionsaufrufs diese Hürde zu umgehen. Die ungewollten Verbindungsaufnahmen gingen in der Vergangenheit sogar so weit, dass prinzipiell beliebige Server von Java-Applets kontaktiert werden konnten. Dabei sollte von der Java-Theorie her ein Applet bei entsprechender Einstellung des Containers (Appletviewer bzw. Browser) nur maximal Kontakt zu dem Server aufnehmen können, von dem es stammt (wer unbeschränkte Kontaktaufnahme im Appletviewer oder in einen justierbaren Browser eingestellt hat, der verdient es einfach nicht besser). Ein Fehler, der sowohl Netscape 2.0 als auch den Appletviewer JDK 1.0 betroffen hat, ist der so genannte DNS-Bug. Der Fehler basierte darauf, dass ein Applet-Programmierer einem beliebigen Host im Internet eine zusätzliche IP-Adresse und einen dementsprechenden Namen zuweist. Diese Adresse muss dann aus der Domain stammen, aus der die Applets angefordert werden. Weiterhin muss sie an erster Stelle innerhalb der Liste der IPAdresse stehen. Java führt eine Kontrolle durch, ob eine Verbindung zu dem Server erlaubt ist und stellt dann direkten Kontakt zum ersten Eintrag in der Liste her, sogar wenn dies nicht die Ursprungsadresse war. Es gab also somit keine Überprüfung der IP-Adressen, sondern nur der Namen. Durch diese Lücke war es ebenso möglich, jede Firewall auszutricksen. Dieser Fehler ist jedoch offiziell seit der Netscape-Version 2.01 und der JDK-Version 1.01 behoben. Für neuere Varianten ist das Problem irrelevant.
14.3.3
Der CLASSPATH-Bug
Auch der so genannte CLASSPATH-Bug in Verbindung mit dem Navigator 2.01 machte deutlich, dass das Sicherheitskonzept von Java in der Vergangenheit Lücken hatte. Laut der Spezifikation kann ein Applet nur lokale Java-Klassen nachladen. Das waren im damaligen Konzept also Klassen, die sich innerhalb der mit CLASSPATH gesetzten Pfade befinden. Die dort Java 2 Kompendium
773
Kapitel 14
Java-Sicherheit befindlichen Klassen besitzen erweiterte Zugriffsrechte. Deshalb wurde schon von Anfang an empfohlen, dort nur die Originalklassen von Sun und eigene, getestete Klassen zu platzieren. David Hopwood von der Oxford University hat aber nun entdeckt, dass es mit dem Interpreter von älteren Netscape-Versionen trotzdem möglich ist, Klassen aus beliebigen lokalen Verzeichnissen nachzuladen. Diese haben dann ebenfalls erweiterte Rechte. Dieser Bug ist in allen Nachfolgeversionen des Navigators 2.01 behoben und hat im Prinzip nichts mit dem eigentlichen Java-Sicherheitskonzept zu tun. Zusätzlich wird ja auch im SDK 2 der CLASSPATH nicht mehr verwendet, sondern ein neues Konzept zur Freigabe von Rechten verfolgt.
14.3.4
Weitere Bugs
Den gerade explizit genannten bekannteren, frühen Bugs folgten diverse weitere. In der Hochphase der Java-Euphorie schien es zu einer Art Sport geworden zu sein, Bugs im Java-Sicherheitskonzept zu finden, so konstruiert und unwahrscheinlich die Ausgangssituationen auch waren. Hauptsache, das Konzept hatte irgendeine Lücke. Im Frühsommer 1997 gingen beispielsweise Horrormeldungen durch die Medien, dass Forscher der University of Washington im Rahmen des Kimera Project 24 neue Sicherheitsrisiken in der damals aktuellen Version des JDK 1.1 entdeckt hätten. Bestätigt wurde davon nur ein echter Fehler. Dennoch entstand der Eindruck, dass, wo Rauch ist, meistens auch Feuer ist. Warum jedoch diese Diskrepanz? Es liegt wohl im Wesentlichen an zwei Dingen. Ein Aspekt ist die Bewertung der gefundenen Bugs. Was ist ein Sicherheitsrisiko und was ein Fehler, der nur in extremen Ausnahmesituationen auftritt? Ein »Fehler« wurde beispielsweise in dem Teil der virtuellen Java Maschine entdeckt, der den Bytecode überprüft. Beim Füttern des »Bytecode Verifiers« mit zufällig gewählten Bytefolgen konnte es zu einem Stack-Überlauf kommen und damit zum Absturz der JVM (auch nach allgemeiner Einschätzung kein Sicherheitsrisiko, nichtsdestotrotz hatte SUN natürlich ein Bug-Fix entwickelt). Wer mit Windows-Software arbeitet, wird garantiert zustimmen, dass dort Abstürze und Fehlleistungen der Windowsprogramme oder des Betriebssystems unter weniger konstruierten Bedingungen zur Tagesordnung gehören. Dennoch hisst niemand gleich die Panikflagge. Ein weiterer Grund für die Diskrepanz der Fehlerzahlen lag in den unterschiedlichen Testmethoden. Grundsätzlich wurde um Java-Bugs viel Sturm in einem Wasserglas veranstaltet. Man unterscheidet bei den Bugs zwischen Security Bugs, System Bugs und Language Bugs. Echte Sicherheitsbugs sind über die Java-Zeit nur äußerst selten entdeckt worden. Und in der letzten Zeit nehmen die Meldungen rund um Sicherheitsprobleme von Java immer mehr ab. Dies darf als gutes Zeichen gewertet werden, denn das Interesse bestimmter Kreise, Sun und Java zu schaden, ist nicht geringer geworden. Wenn diese Kreise keinen Wind mehr machen, haben sie auch nichts Erwähnenswertes mehr gefunden. 774
Java 2 Kompendium
Zusammenfassung
14.3.5
Kapitel 14
Informationen zur Sicherheit
Mehr Informationen zu bisher bekannt gewordenen Java-Bugs und allgemeinen Sicherheitsfragen rund um Java gibt es unter http://java.sun.com/ security/. Dies betrifft sowohl allgemeine FAQs, aber auch eine Bug-Chronologie. Abbildung 14.7: Sicherheitsinformationen zu Java
14.4
Zusammenfassung
Es gibt keine absolute Sicherheit. Auch nicht in Java. Zwar sind mittlerweile diverse Bugs erkannt und beseitigt, aber wo eine Sicherheitslücke erkannt wird, können sich durchaus noch weitere verbergen. Darüber muss man sich im Klaren sein. Aber man sollte beachten, dass die Sicherheitslücken in Java sehr spezielle Situationen voraussetzen und von subversiven Elementen nur sehr schwierig zu nutzen sind. Auch das sicherste Verkehrsmittel der Welt, das Linienflugzeug, stürzt gelegentlich ab. Dennoch fliegen viele Leute, weil es im Verhältnis zum Risiko einfach die beste – und teilweise einzig sinnvolle – Lösung ist. So sollte man auch das Java-Sicherheitskonzept sehen. Und wem es zu ungenügend erscheint, der sollte nur noch einmal einen kurzen Blick auf das ActiveX-Control-Konzept werfen. Obwohl es noch den letzten Beweis schuldig ist, scheint das Java-Sicherheitskonzept zu den derzeit besten Systemen auf dem EDV-Markt zu zählen.
Java 2 Kompendium
775
15
Andere Sprachen in Verbindung mit Java
Wenden wir uns nun Java und seiner Verbindung anderen Programmiersprachen und Technikwelten zu. Es geht also im Kern um die Beziehung von Java und so genanntem nativen Code. Als wichtiger Vertreter soll der direkte Programmiervorfahre von Java behandelt werden, C/C++. Daneben werden wir uns mit JavaScript und anderen Scriptsprachen im Web beschäftigen und wie sie in Verbindung mit Java genutzt werden können.
15.1
C/C++ – Unterschiede und Gemeinsamkeiten sowie die Einbindung
Java hat als direkter C/C++-Ableger viele Gemeinsamkeiten mit seinem Programmierahn. Wir wollen die entscheidenden Gemeinsamkeiten und vor allem die wichtigsten Unterschiede und Vorteile von Java etwas genauer betrachten.
15.1.1
Unterschiede und Gemeinsamkeiten
Die Gemeinsamkeiten von Java und C/C++ beginnen auf der Syntaxebene. Man kann es so ausdrücken: Was in beiden Sprachen von der Funktion her vollkommen gleich ist, wird auch in der Syntax gleich sein. Sun wollte damit Java für C/C++-Progammierer schon auf den ersten Blick vertraut und verständlich machen und die Einarbeitungszeit kurz halten. Diese Vertrautheit birgt jedoch das Risiko, dass geübte C/C++-Progammierer gleichermaßen viele Dinge so in Java versuchen, wie sie es aus C/C++gewohnt sind, selbst wenn Java dafür andere Mechanismen vorgesehen hat. Bei der Java-Sicherheit haben wir ja schon gesehen, dass Java im Gegensatz zu C/C++ keine Pointer, keine Mehrfachvererbung, keine Zeigerarithmetik oder ungeprüfte Typumwandlung benutzt. Außerdem entfällt die Speicherallokation. Lassen Sie uns die wichtigsten Unterschiede jetzt im Einzelnen ein bisschen genauer beleuchten. Pointer Java besitzt keinen expliziten Pointer-Typ, sondern verwendet dafür immer Referenzen. Diese impliziten Referenzen werden für Objekte, VariablenzuJava 2 Kompendium
777
Kapitel 15
Andere Sprachen in Verbindung mit Java weisungen, an Methoden weitergegebene Argumente und Array-Elemente verwendet. Eigentlich ist es eine kleine Lüge, wenn man Referenzen und Pointer als absolut verschiedene Dinge bezeichnet, denn streng genommen sind sie im Wesentlichen das Gleiche. Auch Java muss ja auf irgendeine Weise Speicher zuweisen und zugewiesenen Speicher durch Verweise ansprechen können. Daher sind diese Referenzen, auch wenn sie anders bezeichnet werden, im Grunde genommen nur die Javaversion von Zeigern. Mit einem kleinen, aber feinen (und in Bezug auf Sicherheit extrem wichtigen) Unterschied – man kann auf Referenzen keine Pointer-Arithmetik anwenden und muss es durch das ausgefeilte Referenzkonzept auch nicht. Durch den Wegfall der Pointerarithmetik ist es ebenso nicht möglich, Objekt- und Array-Referenzen in Integerwerte zu casten oder die Grö ß en der primitiven Datentypen in Bytes zu berechnen. Dieses ausgefeilte Referenzkonzept von Java ermöglicht ebenfalls das einfache Erstellen von Strukturen wie verknüpften Listen, und zwar ohne die Verwendung von expliziten Pointern! Vielmehr wird lediglich ein verknüpfter Listenknoten mit Variablen, die auf den nächsten und vorherigen Knoten zeigen, erstellt. Um dann Elemente in die Liste einzufügen, werden diese Variablen anderen Knotenobjekten zugewiesen. Arrays Arrays sind in Java Klassenobjekte, und Referenzen auf Arrays und ihre Inhalte werden wie gerade gesehen nicht durch Pointer-Arithmetik, sondern durch explizite Referenzen realisiert. Die Array-Grenzen werden streng eingehalten, was in Hinblick auf die Sicherheit Java extrem zuverlässig in diesem Bereich macht. In der Praxis bedeutet dies, dass ein Versuch, über das Ende eines Arrays hinaus zu lesen, zu einem Kompilier- oder Laufzeitfehler führt. Wie bei allen Objekten wird durch Weitergabe eines Objekts an eine Methode eine Referenz auf das Originalobjekt erzeugt, also im Falle von Arrays eine Referenz auf das Original-Array. Verändert sich der Inhalt der Array-Referenz, ändert sich auch das Objekt des Original-Arrays. Die Beseitigung von Arrays aus dem Speicher läuft wie bei allen Objekten automatisch über den Garbage Collector. Es gibt bei Java-Arrays noch eine Besonderheit gegenüber C/C++. In Java gibt es keine multidimensionalen Arrays wie C und C++, sondern es müssen Arrays erstellt werden, die dann als Inhalt andere Arrays enthalten. Strings Strings sind in C und C++ Zeichenketten, die immer mit einem Nullzeichen (\0) enden. Strings werden in C und C++ genauso wie andere Arrays behandelt. Deshalb muss man auch dort extrem aufpassen, dass man mit Pointern
778
Java 2 Kompendium
C/C++ – Unterschiede und Gemeinsamkeiten sowie die Einbindung
Kapitel 15
das Ende einer Zeichenketten nicht überschreitet. In Java gibt es als rein objektorientierte Sprache ja nur Objekte und deshalb werden natürlich auch Strings als Objekte behandelt. Damit werden alle Methoden, die auf Strings angewandt werden, einen String nur als komplette Einheit behandeln. Strings werden nicht durch ein Nullzeichen (\0) beendet, und das Ende eines Strings kann dementsprechend nicht versehentlich überschritten werden. Speichermanagement In C/C++ muss sich ein Programmierer immerfort manuell um die Speicherverwaltung kümmern. Dies beinhaltet das Beschaffen von Speicher für Variablen, Funktionen usw.. Noch entscheidender ist, dass er sich gleichermaßen um das explizite Freigeben von Speicher für jedes Objekt kümmern muss. Hier sind neben fehlerhafter Pointerverwaltung die meisten Probleme bei C/C++-Programmen zu finden. Es wird einfach regelmäß ig vergessen, allokierten Speicher mit free() wieder freizugeben. In Java erfolgt das gesamte Speichermanagement automatisch. Speicher wird beim Erstellen eines Objekts mit dem new-Operator automatisch zugewiesen. Die Garbage Collection – ein Papierkorb, der zur Laufzeit immer als Hintergrundprozess mitläuft – gibt den jeweils zugewiesenen Speicher wieder frei, wenn auf das Objekt keine Referenz mehr vorhanden ist. C-Funktionen wie malloc() und free() existieren in Java nicht mehr. Sollte es aus irgendeinem Grund notwendig sein, manuell den Speicher freizugeben, kann man die Garbage Collection aus Java aufrufen, um die Freigabe des von einem Objekt belegten Speichers zu erzwingen. In diesem Fall werden wie bei der automatischen Freigabe alle Referenzen auf das Objekt entfernt (Zuweisung von Variablen, die es auf Null halten, Entfernen des Objekts von Arrays usw.). Bei der nächsten Ausführung gibt der Java-Papierkorb den zugeteilten Speicher zurück. Vererbung und Schnittstellen Sowohl C/C++ als auch Java arbeiten mit dem Mechanismus der Vererbung. Im Gegensatz zu C++ unterstützt Java jedoch keine Mehrfachvererbung. Das erscheint erst einmal als eine große Einschränkung, macht Java-Programme allerdings stabil und leicht wartbar. Dafür bietet Java ja einen ähnlich leistungsfähigen Mechanismus, der dennoch die Wartbarkeit erhält – das Konzept der Schnittstellen, die es in dieser Form in C++ nicht gibt. Objekte können in Java eine beliebige Anzahl an Schnittstellen oder abstrakten Klassen implementieren. Die Java-Schnittstellen sind wie IDLSchnittstellen (Interface Description Language) aufgebaut. Eine Schnittstelle ist in der Java-Sprache eine Sammlung von Methodennamen ohne konkrete Definition sowie Konstanten. Obwohl eine einzelne Java-Klasse nur genau eine Superklasse haben kann (und genau eine haben muss!), können in einer Klasse mehrere Schnittstellen implementiert werden.
Java 2 Kompendium
779
Kapitel 15
Andere Sprachen in Verbindung mit Java Datentypen Die Standardmenge der Datentypen aus C/C++ wird innerhalb von Java um die Datentypen boolean und byte erweitert. In Java haben alle primitiven Datentypen auf allen Plattformen feste Grö ß en und Eigenschaften. In Java wird also die Grö ß e einfacher Datentypen genau spezifiziert, und auch, wie sich die Arithmetik (Berechnungsvorschriften) gegenüber diesen Datentypen verhält. Fast alle wichtigen Prozessoren unterstützen diese Java-Spezifikation und außerdem haben die Java-Bibliotheken portierbare Schnittstellen für die wichtigsten Plattformen integriert. Unter C/C++ gibt es vorzeichenlose Datentypen. Java kennt sie mit Ausnahme von char, einer vorzeichenlosen 16-Bit-Ganzzahl, nicht. Datentypen entstehen in Java ausschließlich durch Verwendung von Klassendefinitionen. Kombinationen von Datentypen wie short int gibt es in Java nicht. Die C/C++-Schlüsselwörter struct, union und typedef gibt es nicht mehr, nur noch Klassendefinitionen. Bzgl. der Umwandlung von Datentypen in andere Datentypen ist Java bedeutend restriktiver als C/C++. Besonders, wenn es um automatische Umwandlung geht, wo unter C/C++ dabei Informationsgehalt verloren gehen kann. Automatisch wird in Java nur umgewandelt, wenn kein Risiko eines Informationsverlustes besteht (also im Wesentlichen nur dann, wenn der Zieltyp aus gleich vielen oder mehr Byte besteht). Alle anderen Umwandlungen müssen explizit angefordert werden. Insbesondere sind die primitiven Datentypen und Objekte gegen eine direkt Umwandlung ineinander abgeschottet. Dafür gibt es in Java Methoden und spezielle WrapperKlassen, um Werte zwischen Objekten und Primitivtypen zu konvertieren. In Java werden einfache Datentypen immer als Call-by-Value und Referenztypen immer als Call-by-Reference behandelt. Java kennt keine nicht-initialisierten Variablen, sondern jede Variable erhält einen wohldefinierten Anfangszustand. Die C/C++-typischen Probleme mit nicht initialisierten Variablen können nicht vorkommen. In Java erhalten alle Referenzdatentypen den Wert null. Dieses reservierte Schlüsselwort weist darauf hin, dass eine Variable nicht auf ein Objekt verweist. Boolesche Werte In C/C++ beruhen Entscheidungen auf Grund boolescher Werte innerhalb von Programmsteuerungsanweisungen wie if, while, for oder do genauso wie in Java (wo sie syntaktisch vollkommen gleich sind) auf den beiden möglichen Ausprägungen true und false dieser booleschen Werte. Der entscheidende Unterschied ist, dass Java einen tatsächlichen booleschen Wert (true oder false) als Typ benötigt, während für C und C++ true oder false »0« oder »ungleich 0« sind. Dabei bedeutet »ungleich 0« eine beliebige
780
Java 2 Kompendium
C/C++ – Unterschiede und Gemeinsamkeiten sowie die Einbindung
Kapitel 15
Ganzzahl. Somit ist es in Java nicht möglich, ein Casting von einem boolean-Typ in einen nicht-boolean-Typ durchzuführen. Der Unicode-Standard Java benutzt für die Darstellung eines char-Typs immer 16 Bit, C/C++ wie die meisten konventionellen Programmiersprachen nur 8 Bit. Dies ist darauf zurückzuführen, dass C/C++ den ASCII-Zeichensatz verwendet und Java die neuere Unicode-Codierung, die eine 16-Bit-Codierung für Zeichen benötigt. Auf dieser Unicode-Codierung beruht die Fähigkeit von Java, landesspezifische Zeichen darzustellen, denn selbstverständlich lassen sich in 16 Bit mehr Zeichen codieren als in 8 Bit. package und import Das Packet-Konzept von Java gibt es nicht in C/C++. Dementsprechend gibt es dort die Anweisungen package und import nicht. In Java dient die Anweisung package dazu, mehrere Klassen zu einem Paket zusammenzufassen. Durch die Anweisung import werden einzelne Pakete in einem Programm verfügbar gemacht. Die C/C++-Anweisung include zur Einbinden von Klassen/Dateien wird durch das Statement import und die Paketstruktur in Java völlig überflüssig. Der Compiler und der Interpreter wissen immer exakt, wo sich die einzelnen Klassen befinden. Der new-Operator Die meisten Operatoren werden in Java genauso wie in C/C++ verwendet. Eine Besonderheit ist der Operator new, um die Instanz einer Klasse zu erzeugen. Diesen new-Operator gibt es in C/C++ und in Java. Das Schlüsselwort new zum Erstellen eines neuen Objekts wird jedoch in Java viel besser in das Gesamtkonzept integriert. Der Befehl new hat in Java die gleiche Bedeutung wie der Befehl malloc() unter C. Mit malloc() wird in C der Speicher für die Instanz einer struct allokiert. new hat in Java ebenfalls die Aufgabe einer dynamischen Allokierung von Speicher. Wie wir bei der Objektorientierung von Java gesehen haben, definiert man zur Einhaltung des streng objektorientierten Konzeptes so genannte Metaklassen. Die einzigen Objekte von Metaklassen sind Klassen, und sie vererben die Klassenmethoden. Diese werden nicht an das Objekt selbst, sondern an die Objektklasse vererbt (Methoden zum Erzeugen von Objekten oder zur Initialisierung von Klassenvariablen). Neben der Konsistenz ist ein weiterer Vorteil des Metaklassenkonzepts, dass die Klassenmethoden in den Klassen überladen werden können. Gibt es für alle Klassen nur eine einzige Metaklasse, dann gibt es für alle Klassen dieselben Klassenmethoden.
Java 2 Kompendium
781
Kapitel 15
Andere Sprachen in Verbindung mit Java C++ verfügt über keine Klassenmethoden und unterstützt das Metaklassenkonzept nicht. An ihre Stelle treten Systemfunktionen, wie etwa besagter new-Operator. Er fällt jedoch unter dem objektorientierten Denkansatz in C++ einfach vom Himmel, während er in Java bedeutend besser in das logische Konzept integriert ist. Operatoren im Allgemeinen Java unterstützt fast alle Standard-C-Operatoren. Diese Operatoren haben in Java die gleichen Prioritäten und Verknüpfungen wie in C. Es gibt jedoch Ausnahmen. So unterstützt Java nicht den Kommaoperator, wie er in C existiert, um zwei Ausdrücke in einem Ausdruck zusammenzufassen. Da Java keine Pointer-Arithmetik ermöglicht, fehlen die zugehörigen Operatoren zur Referenzierung * und Dereferenzierung &, sowie der Operator sizeOf. Weiterhin sind die Zeichen ‘[]’ und ‘.’ keine Operatoren in Java. Dafür gibt es in Java einige Operatoren, die eine spezielle Bedeutung haben oder sogar gänzlich neu sind: Wenn der Operator + in Verbindung mit Zeichenketten verwendet wird, bewirkt er in diesem Fall die Verknüpfung der Zeichenketten zu einer neuen Zeichenkette. Wenn dahingegen nur einer der beiden zu verbindenden Operanden ein String ist, wird der andere Operand automatisch in einen String verwandelt. Die Priorität des + Operators ist identisch mit der Priorität des arithmetischen +. Für die Bearbeitung von Strings gibt es ebenso den Operator +=. Auch dieser ist von der Funktionalität identisch mit der arithmetischen Version. Beim Operator >>> handelt es sich um einen Shift-Operator. Da in Java alle Datentypen außer char als Datentyp mit Vorzeichen definiert sind, bewirkt der konventionelle Operator >> einen Shift nach rechts mit Vorzeichenerweiterung. Der Operator >>> ermöglicht, dass der Wert ohne Vorzeichen nach rechts geschoben wird. Das bedeutet, dass die Bits mit einer 0-Erweiterung nach rechts geschoben werden. Der Operator >>>= ist die dazu passende Übertragung für >>=. Die Operatoren & und | zeigen den in Java gemachten Unterschied zwischen den integralen Datentypen und dem boolean-Datentyp. Bei dem bitweisen UND- und ODER-Operator muss dementsprechend gleichermaßen unterschieden werden. Wenn die beiden Operatoren & oder | auf die integralen Datentypen angewendet werden, bewirken sie die bitweisen UND- und ODER-Operationen. Dies ist analog zu C/C++. Wenn die beiden Operationen allerdings auf den boolean-Datentyp angewendet werden, verhalten sie sich mit einer kleinen Einschränkung wie die logischen UND- bzw. ODER-Operatoren. Die logische Operation in dieser Situation vergleicht in jedem Falle beide Seiten des Ausdrucks, auch wenn das Ergebnis durch die linke Seite bereits festgelegt worden ist. Wenn diese komplette Auswertung des Ausdrucks jedoch
782
Java 2 Kompendium
C/C++ – Unterschiede und Gemeinsamkeiten sowie die Einbindung
Kapitel 15
nicht erwünscht wird, müssen die normalen logischen Operatoren && beziehungsweise || angewendet werden, die nur dann eine rechtsseitige Auswertung durchführen, wenn sie nötig ist. Der Operator instanceof gehört zu der gleichen Prioritätsebene wie die Operatoren =. Er ist true, falls der Operand auf der linken Seite ein Objekt derselben Klasse ist, wie die Klasse des Operanden auf der rechten Seite. Ansonsten gibt instanceof den Wert false zurück. Der Operator instanceof funktioniert ebenso mit Schnittstellen. Überladung von Operatoren Im Gegensatz zu C++ können in Java keine Operatoren überladen werden. Länge der Argumentenliste In C/C++ gibt es Mechanismen für wahlweise Argumente oder Argumentlisten mit variabler Länge für Funktionen. In Java müssen alle Methodendefinitionen eine festgelegte Anzahl von Argumenten haben. Befehlszeilenargumente Auch Befehlszeilenargumente (Programmaufruf-Parameter) verhalten sich in Java anders als in C/C++. Das erste Element im Argumentenvektor (argv[0]) ist in C/C++ immer der Name des Programms. In Java ist das erste Argument das erste der zusätzlichen Argumente. Der Argumentvektor ist also in Java um ein Feld verschoben, und das erste Element im Argumentenvektor (argv[0]) kann leer sein. Kommentare Java hat neben den zwei in C/C++ vorhandenen Kommentartypen /* Eingeschlossener Kommentar */ und // noch einen weiteren Kommentartyp, der vom Dokumentationstool javadoc verwendet wird. Er beginnt mit /** und endet mit */. Präprozessor In Java gibt es keinen Präprozessor. Dementsprechend gibt es in Java die C/C++-Anweisung #defines, #include oder #ifdef nicht mehr. Makros Java besitzt keine Makros. Konstanten Java realisiert Konstanten ausschließlich mit dem Schlüsselwort final. Jede Variable, die mit dem Schlüsselwort final deklariert wird, wird damit zu einer Konstanten. Der Wert dieser Variablen muss direkt bei der Initialisie-
Java 2 Kompendium
783
Kapitel 15
Andere Sprachen in Verbindung mit Java rung mit angegeben werden und kann während des Programmverlaufs nicht mehr geändert werden. Das C/C++-Schlüsselwort const gibt es nicht mehr. Exceptions Die Ausnahmebehandlung ist zwar eine aus C/C++ stammende Spracheigenschaft von Java. Jedoch ist sie dort nicht integraler Bestandteil der Basissprache (also C), sondern nur unter C++ aufgesetzt. In Java gehören Exceptions zum grundlegenden Sprachkonzept. Objektorientiertheit Java ist kompromisslos objektorientiert, während man das von C/C++ nicht behaupten kann. Bereits beim new-Operator haben wir gesehen, dass Java durch das Metaklassenkonzept im Kontrast zu C++ das objektorientierte Konzept einhält. Es gibt keine globalen Variablen oder Methoden. Der Verzicht auf globale Variablen und Methoden oder den Typ von Konstanten, die unter C/C++ durch das Schlüsselwort const realisiert werden – in Java ist das Schlüsselwort nicht mehr vorhanden – und die Unterbindung von Funktionen, die nicht mit einer Klasse verbunden sind (gibt es in C/C++), lassen die Aussage zu, dass Java im Gegensatz zu C++ kompromisslos objektorientiert durchkonzipiert ist.
15.2
Die Verbindung von Java und nativem Code
Java besitzt ein Verfahren, das als die Einbindung von nativem Code bezeichnet wird. Das Wort nativ bezieht sich dabei auf Sprachen wie C und C++. Allerdings können auch andere Sprachen in Java eingebunden werden, was jedoch seltener geschieht. Im Prinzip werden alle Java-Methoden, die in einer anderen Sprache als Java implementiert sind, als native Methoden bezeichnet. Wir werden uns auf C/C++ als Beispiel beschränken, denn das Einbinden von nativem Code ist nicht unproblematisch. Es gibt zwar einige Argumente dafür: Bereits existierende Codes können schnell umgearbeitet und eingebunden werden oder sogar über die Methodenschnittstelle als komplettes Programm einer anderen Sprache in Java eingebunden werden, die Ausnutzung anwendungsspezifischer Stärken anderer Sprachen, Performance oder in anderen Sprachen vorhandenes Know-how der Programmierer. Die Nachteile sind jedoch genauso unzweifelhaft und überwiegen. Einige wesentliche Nachteile einer Verwendung von nativem Code sind die folgenden: Native Methoden werden nicht von den Java-Laufzeit-Sicherheitsmechanismen, wie zum Beispiel dem Klassenlader und den Bytecode-Überprüfer, verifiziert. Es entsteht ein erhebliches Sicherheitsrisiko. Native Methoden sind plattformabhängig.
784
Java 2 Kompendium
Die Verbindung von Java und nativem Code
Kapitel 15
Die Bereinigung der sprachspezifischen Mängel wie unter C/C++ durch Java wird unterlaufen. Das Verfahren ist recht kompliziert und setzt auf jeden Fall gute Kenntnisse der anderen Sprache voraus. Nicht zuletzt gibt es zusätzlichen Code. Falls trotz der massiven Bedenken native Code-Elemente mit Java verbunden werden sollen, werden Funktionen, die in anderen Sprachen geschrieben wurden, in dynamisch ladbare Objekte kompiliert (shared libraries auf UNIX-Plattformen und DLLs auf Windows-Plattformen) und in einen Methodenaufruf von Java eingebaut. Zur Laufzeit werden diese Funktionen dann genau wie alle Java-Methoden aufgerufen.
15.2.1
Konventioneller Einbau von C-Code in Java
Wir wollen in diesem Abschnitt die Vorgänge beleuchten, wie C-Code auf einem konventionellen Weg – wir werden das JNI als Alternative gegenüberstellen – über die Schnittstelle der nativen Methode in Java eingebaut wird. Man kann den Einbau eines C-Programms mittels der Schnittstelle der nativen Methode in Java in sieben hintereinander folgende Schritte gliedern. 1.
Schreiben Sie den Java-Code mit dem Aufruf der nativen Methoden.
2.
Kompilieren Sie den Java-Code wie gewohnt mit dem Java-Compiler.
3.
Erstellen Sie die .h-Datei mit dem JDK-Tool javah.
4.
Erstellen Sie mit javah eine Stub-Datei.
5.
Schreiben Sie die C-Funktion als eine .c-Datei.
6.
Erstellen Sie aus der .h-Datei, der Stub-Datei und der .c-Datei, die Sie in den Schritten 3, 4 und 5 erstellt haben, ein dynamisch ladbares Objektmodul (Shared Libraries auf UNIX-Plattformen und DLLs auf Microsoft Windows 95/NT-Plattformen).
7.
Starten Sie das Programm.
Schritt 1: Schreiben des Java-Codes Um eine native C-Funktion zu deklarieren und aufzurufen, stellen Sie das Schlüsselwort native einer nativen Methode voran. Das Schlüsselwort native signalisiert dem Klassenlader, dass die betreffende Methode der Klasse in einer anderen Programmiersprache geschrieben ist. Diese Definition gibt nur die Signatur der nativen Methode an, jedoch nicht ihre Implementierung. Die konkrete Implementierung wird in einer separaten C-Quelldatei vorgenommen.
Java 2 Kompendium
785
Kapitel 15
Andere Sprachen in Verbindung mit Java Beispiel: class TestNativeMethode { public native void NativeMethode(); ..... weitere Methoden ......... }
Der C-Code, der die native Methode implementiert, muss zu einem dynamisch ladbaren Objekt kompiliert und in die Klasse geladen werden, die dieses benötigt. Erst das Laden des Objekts in die Java-Klasse verbindet die Implementierung der nativen Methode mit ihrer Definition. Das folgende Codestück lädt eine entsprechende Bibliothek namens nativeMethodenbibliothek: static { System.loadLibrary("nativeMethodenbibliothek"); }
Dieses Codestück muss nach der Definition der nativen Methode in der Klasse platziert werden. Als Nächstes erstellen Sie in einer separaten Quelldatei namens Main.java eine Java-Klasse Main, die die Klasse TestNativeMethode instanziert und die native Methode NativeMethode() aufruft. Beispiel für das Hauptprogrammklasse für die Klasse TestNativeMethode: class Main { public static void main(String args[]) { new TestNativeMethode().NativeMethode(); } }
Aus dem obigen Codestück ist ersichtlich, dass Sie eine native Methode genau wie eine echte Java-Methode aufrufen. Alle Parameter, die ggf. an die Methode weitergegeben werden sollen, können in Klammern hinter dem Methodennamen eingefügt werden. Schritt 2: Das Kompilieren des Java-Codes Hierzu gibt es nicht viel zu sagen. Benutzen Sie den Compiler wie gewohnt, um den Code, den Sie in Schritt 1 geschrieben haben, zu kompilieren.
786
Java 2 Kompendium
Die Verbindung von Java und nativem Code
Kapitel 15
Schritt 3: Erstellen der .h-Datei Wir werden das JDK-Tool javah in Anhang A noch besprechen. Der javahGenerator erstellt C-Header (Erweiterung .h) und C-Quelldateien für die angegebenen Klassen. Diese so generierten Dateien enthalten alle notwendigen Informationen zur Implementierung von nativen Methoden, beispielsweise #include- und #define-Anweisungen, typedef-Konstrukte u.ä. Normalerweise generiert javah nur ein Headerfile für die angegebenen Klassen. Innerhalb dieses Headerfiles wird eine C-struct deklariert, die alle notwendigen Felder enthält, die mit den Instanzfeldern der ursprünglichen JavaKlassen korrespondieren. Innerhalb dieser Header-Datei wird ebenfalls bereits eine Funktion für jede native Methode definiert, die in der zugehörigen Quelldatei implementiert werden muss. Verwenden Sie also in diesem Schritt das javah-Werkzeug, um aus der Klasse mit der nativen Methode (in unserem Beispiel TestNativeMethode.java) eine C-Header-Datei (.h-Datei) zu erstellen. Die Header-Datei enthält wie gesagt dann eine Struktur, die auf der C-Seite die Java-Klasse und eine C-Funktionsdefinition für die Implementation der in der Java-Klasse definierten nativen Methode einbindet. Für die genauen Befehlsparameter sei auf den Anhang mit der Besprechung der JDK-Tools und die Online-Dokumentation verwiesen. javah platziert normalerweise die resultierende .h-Datei in das gleiche Verzeichnis wie die Klassendatei und erstellt die Header-Datei mit demselben Namen wie der Klassenname mit der Erweiterung .h. In unserem Beispiel wird also eine Datei namens TestNativeMethode.h erzeugt. Der Inhalt dieser Datei sieht dann ungefähr so aus: /* DO NOT EDIT THIS FILE – it is machine generated */ #include /* Header for class TestNativeMethode */ #ifndef _Included_ TestNativeMethode #define _Included_ TestNativeMethode typedef struct ClassTestNativeMethode { char PAD;/* ANSI C requires structures to have a least one member */ } ClassTestNativeMethode; HandleTo(TestNativeMethode); extern void TestNativeMethode _ NativeMethode(struct HTestNativeMethode *); #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif #endif
Die Header-Datei enthält die Definition für eine Struktur mit der Bezeichnung der Klasse. Die Glieder dieser Struktur spiegeln die Glieder der entsprechenden Java-Klasse wider. Die Felder in der Struktur entsprechen den
Java 2 Kompendium
787
Kapitel 15
Andere Sprachen in Verbindung mit Java Instanzvariablen in der Klasse. Da aber in unserem Beispielfall keine Instanzvariablen vorhanden sind, ist das Feld in der Struktur leer. Die Glieder der Struktur ermöglichen der C-Funktion den Zugriff auf die Instanzvariablen der Java-Klasse. Die Header-Datei enthält zusätzlich zur C-Struktur, die die Java-Klasse widerspiegelt, auch noch den Prototyp einer C-Funktion (in unserem Beispiel extern void TestNativeMethode_NativeMethode(struct HTestNativeMethode *);). Dies ist der Prototyp der C-Funktion, die Sie in Schritt 5 implementieren müssen. Wenn Sie die eigentliche C-Funktion schreiben, müssen Sie genau diesen Funktions-Prototyp benutzen. Wenn in unserem Beispiel noch weitere native Methoden in der Klasse enthalten wären, so würden auch deren Funktionsprototypen hier stehen. Der Name der C-Funktion wird aus dem JavaPaketnamen, dem Klassennamen und dem Namen der nativen Methode hergeleitet. Daher wird in unserem Beispiel aus der nativen Methode NativeMethode() in der Klasse TestNativeMethode der Funktionsname TestNativeMethode_ NativeMethode(). Da kein Paketname vorhanden ist, fehlt dieser beim Namen des Prototyps im Beispiel. Die C-Funktion besitzt einen Parameter, den die in der Java-Klasse definierte native Methode nicht hat. Dieser Parameter ist in C++ in etwa mit der Variablen this in Java zu vergleichen. Schritt 4: Erstellen einer Stub-Datei Verwenden Sie nun javah mit den entsprechenden Optionen, um aus der Java-Klasse eine Stub-Datei zu erstellen. Stub-Dateien sind C-Dateien, die neben der Header-Datei zusätzliche, notwendige Rumpffunktionen für die Einbindung von nativen Methoden in der Java-Umgebung enthalten. Das Tool generiert standardmäß ig eine C-Datei in dem aktuellen Verzeichnis, deren Name identisch zu dem im Aufruf spezifizierten Klassennamen ist. Wenn dieser Klassenname ein Paket enthält, enthalten die C-Dateien sämtliche Komponenten des Paketnamens. Allerdings werden diese nicht durch Punkte, sondern durch Unterstriche getrennt. Bei Angabe der entsprechenden Option zur Erzeugung von Stub-Dateien generiert in unserem Beispiel eine C-Datei mit Namen TestNativeMethode.C, die schematisch wie folgt aussieht: /* DO NOT EDIT THIS FILE – it is machine generated */ #include <StubPreamble.h> /* Stubs for class TestNativeMethode */ ... weitere Angaben ...
Auf das genaue Aussehen der Stub-Datei braucht nicht unbedingt detaillierter eingegangen zu werden, denn sie wird ja automatisch generiert und Sie müssen sie nur zu einer dynamischen Bibliothek in Schritt 6 kompilieren. 788
Java 2 Kompendium
Die Verbindung von Java und nativem Code
Kapitel 15
Schritt 5: Schreiben der C-Funktion Für diesen Schritt muss natürlich vorausgesetzt werden, dass Sie sich soweit in C auskennen, um eine entsprechende C-Datei zu erstellen. Es ist nicht Sinn eines Java-Buchs, auf C-Programmierung einzugehen1. An dieser Stelle finden Sie die wichtigsten Informationen zum Schreiben des eigentlichen Code für die native Methode in einer C-Quelldatei: Die Funktion muss den gleichen Namen wie der Funktionsprototyp haben, der in Schritt 3 durch javah in der .h-Datei erstellt wurde. Der C-Code für diese Funktion enthält als wesentliche und immer vorhandene Angaben neben einer Funktion mit dem gleichen Namen wie der Funktions-Prototyp zwei #include-Anweisungen. Zum einen #include <StubPreamble.h>, zum anderen den #include-Befehl für die Header-Datei (also in unserem Beispiel #include "TestNativeMethode.h"). StubPreamble.h stellt dem C-Code Eingriffe für die Interaktion mit dem Laufzeitsystem von Java zur Verfügung, die zweite Datei enthält die C-Struktur, die die Java-Klasse widerspiegelt, für die Sie die native Methode schreiben. Sie enthält auch den Funktionsprototyp für die native Methode, die Sie in diesem Schritt erstellen. Jeder weitere Code der C-Datei ist optional an die Bedingungen der C-Funktion gekoppelt. Schritt 6: Erstellen einer dynamisch ladbaren Bibliothek Dieser Schritt ist betriebssytemspezifisch und nutzt zudem die entsprechenden Befehle Ihrer Plattform, um den C-Code, den Sie in Schritt 5 erstellt haben, in eine DLL (dynamisch gelinkte Bibliothek) oder Objektdatei zu verwandeln. Es sprengt natürlich den Rahmen dieses Buchs, auf die diversen plattformspezifischen Besonderheiten und vor allem die vielfältigen C/C++Entwicklungstools einzugehen. Der Befehl zum Erstellen eines dynamisch ladbaren Objektmoduls sollte aber auf jeden Fall sowohl die C-Datei mit der Implementierung der nativen Methode als auch die in Schritt 4 erstellte Stub-Datei umfassen. Schritt 7: Der Programmstart Hierzu gibt es wieder nicht viel zu sagen. Benutzen Sie den Java-Interpreter wie gewohnt, um Ihr Programm zu starten. Sollte Sie eine ähnliche Liste von Fehlermeldungen wie die folgende erhalten, dann haben Sie ihre Bibliothek nicht in Ihren Pfad mit aufgenommen: java.lang.NullPointerException at java.lang.Runtime.loadLibrary(Runtime.java) 1
Deshalb soll und kann auch das gesamte Verfahren nur sehr theoretisch besprochen werden.
Java 2 Kompendium
789
Kapitel 15
Andere Sprachen in Verbindung mit Java at java.lang.System.loadLibrary(System.java) at ListDirJava.(TestNativeMethode.java:5) at java.lang.UnsatisfiedLinkError ListDirCat Main.main(Main.java:3)
Der Pfad für die Bibliotheken ist eine Liste mit Verzeichnissen, die das Laufzeitsystem von Java beim Laden von dynamisch gelinkten Bibliotheken durchsucht. Das Verzeichnis, in dem sich die Bibliothek befindet, muss in diesem Pfad enthalten sein.
15.2.2
Das Java Native Interface (JNI)
Wenn man von der Einbindung von nativem Quelltext in Java redet, muss man seit der Version 1.1 das Java Native Interface (JNI) erwähnen. Wir werden es der konventionellen Verbindung von Java und C-Code gegenüberstellen und sehen, dass es viele Gemeinsamkeiten gibt. Es handelt sich um die Standard-Programmierschnittstelle zum Schreiben von nativen JavaMethoden und der Verbindung von der JVM und nativen Applikationen bzw. Sourcequellen. Das primäre Ziel dabei ist die binäre Kompatibilität von nativen Methoden-Libraries über alle JVM-Implementationen hinweg. Das JNI-Konzept vereinfacht die Verwendung von nativem Code gegenüber der frühen Einbindung von nativem Code in Java. Es gilt jedoch immer noch, dass diese Einbindung kompliziert ist und wesentliche Kenntnisse der Programmiersprache voraussetzt, deren nativen Code man verwenden möchte. Außerdem gelten auch unter JNI im Wesentlichen die gleichen Argumenten gegen die Verwendung von nativem Code wie bei einer konventionellen Einbindung. Das JNI-Design Wir wollen hier kurz wesentlichen Aspekte des JNI-Designs anreißen. Native Codezugriffe erfolgen im JNI-Konzept über die Verwendung von JNI-Funktionen. Diese sind über einen Schnittstellenpointer verfügbar. Ein solcher Schnittstellenpointer im JNI-Konzept ist ein Pointer auf einen Pointer. Dieser Pointer zeigt auf ein Array von Pointern, die wiederum jeweils auf eine Schnittstellenfunktion zeigen. Das JNI-Interface ist wie eine virtuelle C++-Funktionstabelle oder ein COM-Interface organisiert. Der wesentliche Vorteil dieses Konzepts ist, dass JNI-Namesräume unabhängig von dem nativen Code werden. Native Methoden empfangen die JNI-Schnittstellenpointer als ein Argument. Weitergehende Informationen finden Sie unter /guide/jni/index.html in der JDK-Dokumentation.
790
Java 2 Kompendium
Die Verbindung von Java und nativem Code
15.2.3
Kapitel 15
JNI-Grundlagen
Um mit dem JNI-Konzept eine Verbindung zwischen Java und C-Code (oder auch anderem nativem Code) zu erstellen, sind im Wesentlichen fünf Schritte erforderlich: 1.
Erstellen der Java-JNI-Funktionsdeklaration
2.
Generierung der C-Header-Datei
3.
Erstellen der C-JNI-Methoden
4.
Laden der JNI-Bibliothek in Java
5.
Linken der dynamischen Bibliothek
Erstellen der Java-JNI-Funktionsdeklaration Wenden wir uns dem ersten Schritt zu – dem Erstellen der Java-JNI-Funktionsdeklaration. Wir kennen diesen Schritt im Prinzip schon, denn die Ähnlichkeit zu der bisher besprochenen Technik ist groß. Um native Methoden in Java-Klassen zu benutzen, muss man in der Deklaration der Methode zuerst das Schlüsselwort native einfügen. Beispiel: public native void meineNativeMethode(); Anschließend wird die Methode System.loadLibrary() in den Java-Source eingebunden. Das Schlüsselwort native signalisiert sowohl dem Java-Compiler als auch dem Java-Interpreter, dass sich der Rumpf der Methode in einer DLL befindet. Die Methode System.loadLibrary() dient zum konkreten Aufrufen dieser dynamische Bibliothek. In dem folgenden Beispiel lädt die Initialisierungmethode der Klasse eine plattformspezifische native Bibliothek, in der die native Methode definiert ist: package pkg; class Cls { native double f(int i, String s); static { System.loadLibrary("pkg_Cls"); } }
Das Argument der Methode System.loadLibrary() ist ein vorgegebener Library-Name. Alternativ stehen die Methoden Runtime.getRuntime().loadLibrary() und System.load() zum Laden einer Bibliothek zur Verfügung. Damit können auch Bibliotheken außerhalb des Suchpfades benutzt werden, denn sie werden anhand eines vollständigen Pfadnamens gesucht. Die JNI-Methode
Java 2 Kompendium
791
Kapitel 15
Andere Sprachen in Verbindung mit Java RegisterNatives() kann ebenfalls zur Registrierung einer nativen Methode verwendet werden. Die JNI-Methode FindClass() dient zur Suche von Klassen.
Wenn eine native Bibliothek respektive Methode eingebunden ist, wird anschließend der Java-Code wie üblich kompiliert. Generierung der C-Header-Datei Der nächste Schritt besteht darin, aus der .class-Datei eine entsprechende Header-Datei mit der Erweiterung .h zu erzeugen. Dazu wird wie gehabt das javah-Tool aus dem JDK eingesetzt. Allerdings müssen Sie die Option -jni verwenden. Der Aufruf sieht also so aus: javah -jni Datei Erzeugt wird dadurch die C-Header-Datei Datei.h. In der Header-Datei wird durch die typedef-struct-Anweisung der nativen C-Routine mitgeteilt, wie die Daten in der Java-Klasse angeordnet sind. Die einzelnen Variablen in der Struktur können benutzt werden, um die Klassen und Instanzvariablen von Java zu benutzen. Weiterhin wird in der HeaderDatei ein Prototyp angegeben, um die Methode aus dem objektorientierten Namensraum der Java-Klasse in einen C-Namensraum zu überführen. Der Name einer Funktion, der eine native Methode implementiert, ergibt sich dabei immer aus dem Paket-Namen, dem Klassen-Namen und dem Namen der nativen Methode von Java, getrennt durch einen Unterstrich (wir kennen das bereits). Erstellen der C-JNI-Methoden In diesem Schritt kommen wir zu einer Neuerung, denn nun müssen die nativen JNI-Methoden implementiert werden. Üblicherweise werden die Implementationsdateien mit dem Klassennamen und einer eindeutigen Endung versehen. Die Implementationsdatei muss die Datei jni.h mittels #include-Anweisung einbinden. jni.h ist im include-Verzeichnis des JDK enthalten. Ebenfalls muss die mittels javah -jni erzeugte Header-Datei eingebunden werden. Der Funktionskopf in der Implementationsdatei muss den generierten Prototypen aus der Headerdatei entsprechen. Erstellung der dynamischen Bibliothek Nachdem nun alle benötigten Dateien vorhanden sind, muss die Implementierungsdatei nur noch übersetzt und mit der Java-Bibliothek zu einer dynamischen Bibliothek zusammen gelinkt werden. Dies entspricht unseren Schritten 4 und 5 bei der konventionellen Technik.
792
Java 2 Kompendium
Die Verbindung von Java und nativem Code
15.2.4
Kapitel 15
Datenaustausch zwischen Java und C
Der Datenaustausch zwischen Java und C ist – wie wir bereits wissen – nicht ganz unproblematisch. Jedem elementaren Typ in Java wird ein Typ in der Prototyp-Funktion und damit auch in C zugeordnet. Ein gewisses Problem ist dabei der Typ char, der in Java nach dem Unicode-Standard kodiert ist und in C seinem ASCII-Gegenstück zugeordnet werden muss. Dem JavaTyp String kann sogar nur eine Struktur zugeordnet werden. Wenn Variablen nicht als Parameter einer Methode, sondern als Klassenvariable angelegt werden, ermöglicht dies einen einfachen Zugriff von C aus. Dieser Zugriff wird als »Call by Reference« bezeichnet. Übergibt man die Variablen als Parameter, nennt man diesen Zugriff einen »Call by Value«. Alle Klassenvariablen werden in der .h-Datei zu einem struct zusammengefasst. Auf diesen erhält die aufgerufene C-Funktion als Parameter ein Handle-Pointer. Das in StubPreamble.h definierte unhand()-Makro ermöglicht den Zugriff auf die einzelnen Klassenvariablen. Das unhand()-Makro übernimmt einen Pointer auf das Handle einer Klasse und gibt einen Pointer auf die im .h-File erzeugte Klassenstruktur zurück. Über den Rückgabewert des Makros lassen sich die Instanzvariablen der Java-Klasse direkt auswerten und verändern. Strings Wie wir wissen, sind Strings in Java eine eigene Klasse. Möchte man einen String von Java nach C oder umgekehrt übergeben, muss man javaString.h in der C-Implementationsdatei mit einbinden. In javaString.h finden sich die Typdefintionen und Funktionen, um Strings von Java nach C und umgekehrt zu transformieren. Es gibt noch weitere Methoden, um Strings zu bearbeiten, wie z.B. MoveString_GetString(), CString() oder makeJavaString(). Java-Strings bilden eine eigene Klasse, somit wird bei der Konvertierung nicht nur ein elementarer Typ, sondern eine ganze Klasse an die native Methode durchgereicht. Dieses Konzept lässt sich auch auf andere Klassen erweitern. Felder Felder werden von Java nach C übergeben, indem vom javah-Tool ein Funktionsparameter vom Typ struct HArrayOf * erzeugt wird. Dieser enthält einen Element-Body, mit dem auf die Feldelemente zugegriffen werden kann. Der Zugriff auf das Feld erfolgt mit dem unhand()-Makro und dem body -Element. Allgemeines zu JNI-Typen und Datenstrukturen Es gibt zu jedem Java-Typ ein passendes JNI-Äquivalent, das dem Namen in der Regel nur ein j voranstellt. Um unter JNI-Javatypen in native C-Typen zu mappen, benötigen Sie grundlegende Informationen über die primitiven Java 2 Kompendium
793
Kapitel 15
Andere Sprachen in Verbindung mit Java Typen. Die nachfolgende Tabelle beschreibt die primitiven Java-Typen und ihre maschinenabhängigen nativen Äquivalente:
Tabelle 15.1: Die JNI-Typen
Java Typ
Native Typ
Beschreibung
boolean
jboolean
unsigned 8 bits
byte
jbyte
signed 8 bits
char
jchar
unsigned 16 bits
short
jshort
signed 16 bits
int
jint
signed 32 bits
long
jlong
signed 64 bits
float
jfloat
32 bits
double
jdouble
64 bits
void
void
N/A
Speichermanagement In Java wird die Speicherverwaltung automatisch vom Garbage Collector erledigt. Wird in einer C-Funktion einer nativen Methode Speicher angelegt, muss sich der Programmierer selbst um die Freigabe kümmern. Da der JavaInterpreter von diesem manuellen Speichermanagement normalerweise nichts mitbekommt, müssen eigene native Methoden implementiert werden, um Speicher freigeben zu können. Unter gewissen Umständen können die Speicherbereiche auch aus Java heraus freigegeben werden. Eine einfache Variante der Freigabe ist der explizite Aufruf der Methode dispose().
15.2.5
Java-C++-Verbindung
Die Ähnlichkeit von Java und C++ legt die Vermutung nahe, dass es relativ einfach ist, C++-Code in Java einzubetten. Leider ist das Gegenteil der Fall. Aus Sicht der Schnittstelle betrachtet unterscheiden Java und C++ die folgenden Charakteristika: Die Laufzeit-Schnittstelle für native Methoden in Java ruft das eigentliche dynamische Objekt über eine C-(nicht C++)-Funktions-Aufrufsequenz auf. In C++ ist der Name einer Funktion in der Objektdatei nicht mit dem Namen identisch, der in der C++-Quelldatei verwendet wird. Daher kann eine C++-Methode in einer Objektdatei einen ganz anderen Namen haben. Dies wird als Name Mangling bezeichnet und ist eine Eigenschaft, die alle C++-Compiler besitzen. 794
Java 2 Kompendium
Verbindung von Java zu JavaScript und anderen Scriptsprachen
Kapitel 15
Aus der Konsequenz dieser beiden Faktoren ergibt sich, dass Sie, wenn Sie eine C++-Methode aus Java aufrufen, nicht denselben Namen benutzen können, den Sie der Methode in C++ zugewiesen haben. Derzeit besteht die einzige Möglichkeit, C++ in Java einzubinden, darin, dass Sie einen C-Wrapper für die C++-Methoden definieren und diese C-Wrapper-Funktionen dann über die native Methodenschnittstelle aus Java aufrufen. Dieser Umweg hat neben Performanceverlusten einige weitere Nachteile. Zum einen können C++-Ausnahmen nicht ohne Weiteres behandelt werden, zum anderen muss der Parameteraustausch zwischen Java und dem eigentlichen C++-Code exakt gehandhabt werden. Ferner müssen Ihnen die wichtigen zusätzlichen Unterschiede zwischen Java und C++ bekannt sein, die am Anfang des Kapitels besprochen wurden, und natürlich von Ihnen beim Programmieren berücksichtigt werden.
15.2.6
Alternativen zum direkten Einbinden von nativen Methoden
Native Methoden sind nicht die einzige Möglichkeit, C- oder C++-Programme mit Java zu verbinden. Es gibt in der Tat Alternativen, um JavaProgramme mit anderen Programmen zu verbinden. Zwei auch in vielen anderen Sprachpaarungen praktizierte Varianten sind die folgenden: Die beiden Programme können so aufgebaut werden, dass sie als Client/Server-System funktionieren. Das bedeutet, ein Programm ruft das andere über einen Shell-Befehl auf. Die Kommunikation läuft über ein Socket oder mittels Übergabeparameter (in eine Richtung). Dazu gibt es in Java im Wesentlichen die Klassen Socket und ServerSocket. Sie sind die Repräsentation eines Clients bzw. Servers bei einer so aufgebauten Client-Server-Beziehung (wir kommen im Abschnitt zu Netzwerkprogrammierung im Kapitel über die erweiterten Java-Techniken darauf zurück). Strukturieren Sie die beiden Programme so, dass Sie Daten über das Lesen und Schreiben von Dateien austauschen können. Es gibt in dem Fall also Schnittstellen auf Datenträgern, die abwechselnd geschrieben und gelesen werden können. Dazu muss dann in einem Programmpart nur noch ein Aufruf des anderen Programmparts und dessen Synchronisation realisiert werden.
15.3
Verbindung von Java zu JavaScript und anderen Scriptsprachen
Die Verbindung von Java zu Scriptsprachen im Rahmen einer Webseite ist gut möglich. Wir wollen hier zu einem der beiden wichtigsten Vertreter von Scriptsprachen kommen. In Zusammenhang mit Java wird immer wieder
Java 2 Kompendium
795
Kapitel 15
Andere Sprachen in Verbindung mit Java der Begriff JavaScript genannt. Die Ähnlichkeit im Namen suggeriert aber eine Verwandtschaft, die so gar nicht vorhanden ist. Insbesondere handelt es sich bei JavaScript nicht um eine von der Syntax an C/C++ angelehnte, objektorientierte Programmiersprache. JavaScript ist viel einfacher als Java und hat seine Existenzberechtigung da, wo Java überdimensioniert ist, vor allem aufseiten des Clients im WWW. Dies gilt für viele Aktionen im Rahmen einer Webseite oder der Steuerung eines Browsers. JavaScript (in der Betaversion noch LiveScript genannt) wurde in Zusammenarbeit von Sun und Netscape als Java-Ableger entwickelt und sollte als Steuerungstechnik für den Netscape-Navigator 2.0 agieren. Im Dezember 1995 haben die Netscape Communications Corporation und Sun Microsystems JavaScript angekündigt und recht bald als eine offene, plattformunabhängige Scriptsprache eingeführt. Obwohl JavaScript viel einfacher als Java ist, lehnt sich die Syntax an Java an. Bei den so genannten Scriptsprachen (JavaScript oder auch Microsofts VBScript) handelt es sich um Interpretersprachen. Sie sind allgemein von relativ einfacher Struktur. Scriptsprachen müssen – server- oder clientseitig – als Interpretersprachen in irgendeinen Interpreter implementiert werden, damit sie zu Leben erwachen. Auf einem Web-Client realisiert man die Verwendung von Scriptsprachen, indem man die Scriptelemente in HTML einbindet. Anschließend werden sie dann von dem Browser (der natürlich diese Scriptsprache verstehen muss) interpretiert. JavaScript zum Beispiel ist so als eine unmittelbare Ergänzung und Erweiterung zu HTML zu sehen und nur als eingebundener Bestandteil eines HTML-Gerüsts zu verwenden. JavaScript-Programme werden im Gegensatz zu Java-Applets direkt in der HTML-Datei geschrieben oder zumindest als Klartext-Dateien dort referenziert. Sie sind damit in gewisser Weise normaler Bestandteil des HTMLDokuments, ähnlich wie Überschriften, Verweise oder andere Referenzen. Sie werden auch nicht wie Java-Applets als vorkompilierte Module in die HTML-Datei integriert, sondern analog HTML als Klartext zur Laufzeit interpretiert. Trotzdem handelt es sich bei JavaScript im Gegensatz zu HTML nicht nur um eine Beschreibungssprache, sondern um eine vollwertige Programmiersprache, wenn auch auf reiner Interpreterbasis. Damit hat JavaScript alle durch das Interpreter-Prinzip bedingten Vorteile, leider aber auch die Nachteile. JavaScript bietet sich daher für kleine und einfache Programmabläufe an, die Aktionen erfordern, die unter HTML nicht oder nur umständlich zu bewerkstelligen sind und Java als zu schweres Geschütz outen.
796
Java 2 Kompendium
Verbindung von Java zu JavaScript und anderen Scriptsprachen
Kapitel 15
Scriptsprachen können wie gesagt bei einem Client-Server-System sowohl auf Server, als auch dem Client eingesetzt werden. Wir wollen uns hier nur mit dem clientseitigen Einsatz von JavaScript beschränken. Eigentlich ist es so, dass im Browser eingesetzte Scriptsprachen im Wesentlichen den relativ dummen Browser intelligenter machen. Dazu müssen auf der Client-Seite Fähigkeiten hinzugefügt werden, die dem angefragten Dokument oder dem anfragenden Browser eine Veränderung des Dokuments ermöglichen. Diese Fähigkeit bringt die Möglichkeiten von serverseitigen Programmen zum Client, sie macht den Browser also leistungsstärker und intelligenter. Obwohl ein Browser normalerweise außer dem Anfordern und Versenden von Daten höchstens noch als Darstellungssoftware für Multimedia-Effekte dient, ist in modernen Browsern die Nutzung dieser Scriptsprache(n) integriert, um sie mit weitergehenden Fähigkeiten auszustatten. Scripte erlauben einem Webbrowser, auf eine intelligente Weise mit Situationen, die sonst ein Programm auf dem Webserver erforderlich machen würden, umzugehen. Darüber hinaus hat der Anwender den Eindruck, dass die Situation viel schneller abgehandelt wird, da der Browser keine Anfrage an den Server schicken und die Antwort nicht anzeigen muss. Mit Sprachen wie JavaScript wird also eigentlich der Browser programmiert.
15.3.1
Kleiner Exkurs zu JavaScript-Interna
Wir sprechen hier zwar hauptsächlich über Java, aber als ein direkter JavaAbleger macht es Sinn, auch JavaScript ein bisschen eingehender zu beleuchten. Deshalb nun ein kleiner Exkurs zu den JavaScript-Interna. Wir werden als Erstes ohne lange Vorrede mit einem kleinen Beispiel einsteigen. Ein kleines und sehr bekanntes Beispiel in JavaScript ist die Laufschrift in der Statuszeile des Browsers. Der Source dafür ist ziemlich einfach und leicht nachzuvollziehen, wenn man Java und Objekte kennt. Die einzelnen Details werden etwas weiter hinten im Kapitel erläutert. <script language="JavaScript"> 100) { seed--; var cmd="scrollit_r2l(" + seed + ")"; timerTwo=window.setTimeout(cmd,100); }
Java 2 Kompendium
Listing 15.1: Eine JavaScriptLaufschrift in der Statuszeile des Browsers
797
Kapitel 15
Andere Sprachen in Verbindung mit Java else if (seed 0) { for (c=0 ; c < seed ; c++) { out+=" "; } out+=msg; seed--; var cmd="scrollit_r2l(" + seed + ")"; window.status=out; timerTwo=window.setTimeout(cmd,100); } else if (seed Willkommen auf meiner Homepage
Abbildung 15.1: Laufschrift in der Statuszeile per JavaScript
Die Einbindung von JavaScript (oder auch anderen Scripten) in HTML-Seiten erfolgt in der Regel über das <SCRIPT>-Tag.
798
Java 2 Kompendium
Verbindung von Java zu JavaScript und anderen Scriptsprachen
Kapitel 15
<SCRIPT language="JavaScript">
Das <SCRIPT>-Tag kann an einer beliebigen Stelle innerhalb der Webseite platziert werden. Wenn das Script im -Bereich platziert wird, wird es bereits interpretiert, bevor der Textkörper des Dokuments vollständig geladen wurde. Deshalb sollten Sie Funktionen und Initialisierungscode in den -Abschnitt oder zumindest vor den Body schreiben. Direkt nach dem einleitenden <SCRIPT>-Tag sollte ein HTML-Kommentar
SSI basiert auf der Grundlage des Server-Parsing. Bei gewöhnlichen Webseiten erhält der Webserver eine Anforderung für eine Webseite und sendet diese ohne jegliche Überprüfung an den Client zurück. Wenn eine Seite jedoch Server-Parsing fordert, analysiert der Webserver die HTML-Seite vor der Rücksendung und sucht dabei nach serverbasierenden Befehlen. Erkennt der Webserver einen solchen Befehl, führt er die entsprechende Aktion aus. Grundsätzlich muss bei der Arbeit mit SSI beachtet werden, dass nicht alle Webserver diese Technik unterstützen oder erlauben. Damit die Verwendung von SSI-Anweisungen in einer Webseite für den Server sofort offensichtlich wird, werden solche Webseiten meist die Dateierweiterungen .SHTM oder .SHTML bekommen (das ist aber in der Serverkonfiguration anzupassen). Webseiten mit den normalen Endungen .HTM oder .HTML werden von den meisten Servern nicht geparst und damit werden die SSI-Anweisungen nicht beachtet. Schauen wir uns nun das Beispiel für ein vollständiges Servlet an. Zuerst die Java-Datei, die ein Servlet darstellt: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class MeinServlet extends HttpServlet { private static final String CONTENT_TYPE = "text/html"; /**Globale Variablen initialisieren*/ public void init(ServletConfig config) throws ServletException { super.init(config); } /**Die HTTP-Anforderung GET bearbeiten*/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Java 2 Kompendium
Listing 16.6: Ein Servlet, das auf doGET() reagiert.
867
Kapitel 16
Weiterführende Themen response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println( ""); out.println("Das Servlet hat ein GET empfangen und keine Lust zu einer sinnvolleren Antwort ;-)."); out.println(""); } /**Ressourcen bereinigen*/ public void destroy() { }}
Wir benötigen für den SSI-Fall noch eine Webseite (in der Regel mit der Dateierweiterung .shtml versehen, damit der Server sie nach Anweisungen parst), über die ein Client eine Anfrage an das Servlet stellt. Das Servlet wird in diesem Beispiel – eng verwandt mit einem Applet (allerdings fehlen logischerweise Angaben wir Höhe und Breite) – mit dem Tag <SERVLET> in die Webseite integriert. Wenn das Servlet beim Laden aufgerufen werden soll und noch eine zusätzliche Möglichkeit in der Webseite für einen Start per Hyperlink existieren soll, sieht die Webseite folgendermaßen aus: Listing 16.7: Die Webseite zum Aufruf des Servlets
Ausgabe von Servlet MeinServlet GET:
<servlet codebase="" code="MeinServlet.class">
Klicken Sie hier, um Servlet MeinServlet erneut aufzurufen
Zum Start der gesamten Geschichte muss das Servlet wie gesagt in ein passendes Serverprogramm implementiert werden und von einem Client aus die Webseite geladen werden. Der oben erwähnte Tomcat-Server von Apache ist beispielsweise so ein Serverprogramm. Im Client sehen Sie nach dem Laden die teilweise vom Servlet generierte, zum Teil auch aus purem HTML aufgebaute Seite. Abbildung 16.14: Die Antwort des Servlets
Wenn Sie den Hyperlink anklicken, wird das Servlet erneut kontaktiert und nur die Rückgabe des Servlets im Client angezeigt.
868
Java 2 Kompendium
Netzwerkzugriffe, Sockets und Servlets
Kapitel 16
Ein zweites Beispiel zeigt die Anwendung von JSP. JSP-Dateien (im Prinzip reine HTML-Dateien) werden meist mit der Erweiterung .jsp gespeichert und rufen über die Anweisung der Form <jsp:useBean id="ServletID" scope="session" /> das Servlet auf. Erstellen Sie zunächst die Datei jsp1.jsp: <jsp:useBean id="JspBId" scope="session" /> <jsp:setProperty name="JspBId" property="*" />
Bitte einen Wert eingeben :
Wert der Eigenschaft Bean ist:<jsp:getProperty name="JspBId" property="sample" />
Listing 16.8: Die Webseite zum Aufruf des Servlets
Die Java-Datei selbst ist ziemlich einfach: public class JspB { private String sample = "Vorbelegung"; // Beispieleigenschaft abfragen public String getSample() { return sample; } // Beispieleigenschaft setzen public void setSample(String newValue) { if (newValue!=null) { sample = newValue; } } }
Listing 16.9: Das JSP-Servlet
Wenn Sie die JSP-Datei aufrufen (das Servlet sollte natürlich im Server lauffähig bereit stehen), erhalten Sie ein Eingabeformular. Abbildung 16.15: Die Webseite zum Entgegennehmen der Benutzereingaben und dem Aufruf des Servlets
Im Eingabeformular können Sie etwas eintragen, dann mit dem Button das Servlet aufrufen und ihm den Wert übermitteln.
Java 2 Kompendium
869
Kapitel 16
Weiterführende Themen
Abbildung 16.16: Das geht an den Server.
Das Servlet generiert eine neue Seite, wo der eingebene Wert als dynamische Information enthalten ist. Abbildung 16.17: Die Antwort des Servlets
16.4.2
Allgemeine Netzwerkzugriffe
Für allgemeine Netzwerkzugriffe steht Java das Paket java.net zur Verfügung. Die darin enthaltenen Klassen erlauben unter Java relativ einfache, plattformübergreifende Vernetzungsoperationen. Darunter fallen das Lesen und Schreiben von Dateien über das Netzwerk oder das Verbinden mit den üblichen Internet-Protokollen. Um die Einschränkungen von Lese- und Schreiboperationen bei Applets wissen Sie bereits (Stichwort Sicherheit), aber ansonsten sind Netzwerkzugriffe mit Java leichter zu realisieren als mit den meisten anderen Sprachen. Man unterscheidet in Java (wie auch in allgemeiner Netzwerktechnik) im Wesentlichen zwischen paketorientierter Kommunikation über das Netzwerk und der verbindungsorientierten Kommunikation. Die erste Variante versendet einfach ein Datenpaket mit der Adresse des Zielrechners (in den meisten Fällen eine IP-Adresse und Port) und kümmert sich nicht weiter darum (weder um den genauen Weg, noch darum, ob es überhaupt ankommt). So etwas findet man meistens bei WAN-Netzwerken (Wide Area Network) wie dem Internet. Die zweite Variante baut eine permanente Verbindung zu einem Zielrechner auf, die im Laufe der Kommunikation immer wieder verwendet wird. Sie wird einmal aufgebaut und dann gehalten, bis die Arbeit abgeschlossen ist. Dies nennt man eine semi-permanente Verbindung.
870
Java 2 Kompendium
Netzwerkzugriffe, Sockets und Servlets
Kapitel 16
Sie finden diese hauptsächlich bei LAN-Netzwerken (Local Area Network), wo sich Betriebsmittel und Leitungen in einer Hand befinden, aber auch bei einer direkten Wahlverbindung zwischen zwei Rechnern. Wenden wir uns zuerst der verbindungsorientierten Kommunikation zu. Die URL-Klassen von Java Internet und Java gehören zusammen. Damit aber auch Java und Netzwerke jeder Art. Java ist von Anfang an als eine Netzwerksprache entworfen worden. Die URL-Klasse bietet einige interessante Möglichkeiten, um eine Internet-Ressource unter Java zu spezifizieren. Die URL-Klasse (URL steht für Uniform Resource Locator) besitzt Konstruktoren und Methoden für die Verwaltung einer URL. Dies können beliebige Objekte oder Dienste im Internet sein. Das TCP-Protokoll, über das Sie normalerweise einen Netzwerkzugriff auf einen Server realisieren werden, benötigt zwei Teile zur Information: die IP-Adresse des Rechners und die Port-Nummer. Holen eines URL-Objektes Die IP-Adresse des Rechners werden Sie meist nicht direkt angeben (und grö ß tenteils auch nicht wissen), sondern statt dessen verwenden Sie den DNS-Namen des Rechners. Dieser Name wird mittels spezieller Namensserver dann automatisch in die IP-Nummer übersetzt, wenn die Information auf der Reise zum Zielserver benötigt wird. Wir sind darauf bei der beschreibung der Funktionsweise des Internets eingegangen. Den Port benötigen Sie nicht immer, denn normalerweise ist Port 80 für den Web-Dienstport reserviert. Wenn Sie also keinen Port angegeben, wird der adressierte Server normalerweise diesen Port defaultmä ß ig verwenden. Es gibt jedoch keine feste Regel, die besagt, dass Port 80 der Web-Port sein muss. Es ist einfach Usus, aber nicht zwingend. Die URL-Klasse berücksichtigt diese möglichen Spezifikations-Variationen. Um eine neue URL zu erstellen, sind diverse Konstruktoren möglich. Nachfolgend drei Beispiele: Konstruktor
Beschreibung
public URL(String url_zeichenkette) throws MalformedURLException;
Dieser Konstruktor erzeugt ein URLObjekt, das in der url_zeichenkette sämtliche notwendigen Informationen für den Zugriff (Protokoll, Host, evtl. Port, Pfad und/oder Dateiname) enthalten sollte.
Java 2 Kompendium
Tabelle 16.3: URL-Konstruktoren
871
Kapitel 16 Tabelle 16.3: URL-Konstruktoren (Forts.)
Weiterführende Themen
Konstruktor
Beschreibung
public URL(String protokoll, String host, int port, String Datei) throws MalformedURLException;
Dieser Konstruktor erzeugt ein URLObjekt, das sämtliche notwendigen Informationen für den Zugriff (Protokoll, Host, Port, Pfad und/oder Dateiname) als einzelne Parameter benötigt.
public URL(String protokoll, String host, String Datei) throws MalformedURLException;
Dieser Konstruktor erzeugt ein URLObjekt, das für den Zugriff außer dem Port sämtliche notwendigen Informationen (Protokoll, Host, Pfad und/oder Dateiname) als einzelne Parameter benötigt.
Die ausgeworfene Ausnahme sollten Sie jedes Mal gezielt abfangen (trycatch-Block), denn das Holen eines URL-Objekts ist ein sehr instabiles Unterfangen. Dazu können Sie folgenden Code verwenden (Syntax mit dem ersten Konstruktor): String url = ... // irgendeine Url try { meinUrl = new URL (url); } catch(MalformedURLException e) { // tue etwas sinnvolles }
Anzeigen eines URL-Objekts in einem Browser Um ein URL-Objekt aus einem Applet an einen Browser weiterzugeben, brauchen Sie nur eine einzige Zeile Code: getAppletContext.showDocument(meineURL);
Die Methoden showDocument(meineURL) bzw. showDocument(meinURL, String) gehören zum Interface java.applet.AppletContext und zeigen in einem Browser den URL an. Testen wir das in einem kleinen Beispiel: Listing 16.10: Das Applet lädt unmittelbar die angegebene URL.
872
import java.net.URL; import java.net.MalformedURLException; public class Netz1 extends java.applet.Applet { URL homepage; public void init() { try { homepage=new URL("http://localhost/"); } catch (MalformedURLException e) {
Java 2 Kompendium
Netzwerkzugriffe, Sockets und Servlets
Kapitel 16
System.out.println( "Nix gibt's:" + e.toString()); } getAppletContext().showDocument(homepage); }}
Das Applet lädt bei der Initialisierung die Startpage des lokalen Hosts (in unserem Fall) und zeigt sie direkt statt des Applets an. Eingebunden wird das Applet wie üblich: <APPLET code="Netz1.class" height=200 width=200>
Listing 16.11: Die Webseite zum Aufruf des Applets
Öffnen von Webverbindungen Statt ein URL-Objekt nur anzuzeigen, kann man es auch direkt in einem Applet verwenden. Sicherheitsgründe begrenzen jedoch diese Form von Netzwerkverbindungen. Ein Applet kann normalerweise nur eine Verbindung zu dem Host aufbauen, von dem es ursprünglich geladen wurde (falls der Browser es überhaupt kommunizieren lässt). Sicherheitslücken und zu freizügige Einstellungen des Browsers seien bei dieser Aussage außer Acht gelassen. Die Klasse URL definiert eine Methode public final InputStream openStream() throws IOException, die eine Netzwerkverbindung mit einer bestimmten URL öffnet und eine Instanz der Klasse InputStream ausgibt. Wir haben in dem Kapitel über die Ein- und Ausgabe in Java gesehen, dass man einen solchen Strom in einen DataInputStream konvertieren kann. Damit können Sie die Zeichen aus dem Strom auf vielfältige Weise lesen und anschließend verarbeiten. Wenn Sie beispielsweise wie oben eine URL in meineURL gespeichert haben, können Sie folgenden Code verwenden, um zeilenweise die Zeichen zu verarbeiten: try { InputStream eingabe = meineURL.openStream(); DataInputStream data_wert = new DataInputStream(new BufferedInputStream(eingabe)); String zeile; while ((zeile = data_wert.readLine()) != null) { // tue etwas mit den Zeilen } } catch (IOException e);{ // tue etwas sinnvolles }
Java 2 Kompendium
873
Kapitel 16
Weiterführende Themen Die URLconnection-Klasse Bei der openStream()-Methode handelt es sich um eine vereinfachte Variante einer Methode aus der allgemeineren URLconnection-Klasse. Diese abstrakte Klasse enthält diverse Möglichkeiten, Dateien anhand beliebiger URLs aus dem Netz zu laden und bietet eine weitaus grö ß ere Flexibilität zur Handhabung von URL-Verbindungen. Sie ist die Superklasse für alle Klassen, die eine Verbindung zwischen einer Anwendung und einer URL repräsentieren. Über diese Klasse können Verbindungen sowohl zum Lesen als auch zum Schreiben über diesen Kanal aufgebaut werden.
16.4.3
Sockets
Die Klassen URL und URLconnection bieten nur relativ eingeschränkte Möglichkeiten für Netzwerkverbindungen. Für die meisten Fälle werden sie zwar ausreichen, aber es gibt genügend Anwendungen für weitergehende Funktionalitäten, etwa andere Protokolle. Dafür stellt Java neben den schon angesprochenen Techniken für verteilte Anwendungen und Servlet-Kontakte die Klassen Socket und ServerSocket zur Arbeit mit Sockets zur Verfügung. Die Klasse Socket ist für die Erstellung und Verwaltung von Sockets auf der Clientseite und die Klasse ServerSocket für die Erstellung und Verwaltung von Sockets auf der Serverseite zuständig. Java besitzt die gleichen UNIX-Wurzeln wie das Internet. Die von UNIXSockets abgeleitete Klasse Socket stellt ein Grundobjekt in der InternetKommunikation dar, das das TCP-Protokoll unterstützt. Die Socket-Klasse verfügt über diverse Datenstrommethoden zur Ein- und Ausgabe, was das Auslesen und Schreiben in die Socket-Klasse sehr vereinfacht. Um eine Verbindung über die Socket-Klasse aufzubauen, erstellen Sie eine Instanz von der Klasse. Dies geschieht mit der folgenden Syntax: Socket verbindung = new Socket(hostname, portnummer);
Dabei ist hostname durch den tatsächlichen Namen des Hosts und portnummer durch die Nummer des Ports zu ersetzen. Dabei ist die Klasse InetAddress aus dem Paket java.net sehr nützlich. Ein aus dieser Klasse erstelltes Objekt enthält sowohl den symbolischen DNS-Namen als auch die IP-Adresse des jeweiligen Rechners. Und einige sehr nützliche Methoden: Die Methode public String getHostName() liefert den Namen des Hosts für diese IP-Addresse. Wenn ein Securitymanager aktiv ist, wird eine SecurityException ausgeworfen, wenn die Abfrage nicht erlaubt ist. Dazu wird die Methode SecurityManager.checkConnect(java.lang.String, int) genutzt. 874
Java 2 Kompendium
Netzwerkzugriffe, Sockets und Servlets
Kapitel 16
Die Methode public byte[] getAddress() liefert die IP-Addresse des InetAddress-Objekts als byte-Array. Die Methode public String getHostAddress() liefert die IP-Adresse als String in der Form »%d.%d.%d.%d«. Die Methode public static InetAddress getByName(String host) throws UnknownHostException bestimmt die IP-Addresse eines Hosts, wenn der Name des Hosts gegegeben ist. Dieser Hostname kann in der From www.rjs.de oder als eine String-Repräsentation der IP-Addresse angegeben werden. UnknownHostException wird ausgeworfen, wenn der Host
nicht gefunden werden kann. Die Methode public static InetAddress[] getAllByName(String host) throws UnknownHostException liefert alle IP-Addressen von einem Host als Array, wenn der Name des Hosts gegeben ist. Dieser Hostname kann in der From www.webscripting.de oder als eine String-Repräsentation der IP-Addresse angegeben werden. UnknownHostException wird ausgeworfen, wenn der Host nicht gefunden werden kann. Wenn ein Securitymanager aktiv ist, wird eine SecurityException ausgeworfen, wenn die Abfrage nicht erlaubt ist. Dazu wird die Methode SecurityManager.checkConnect(java.lang.String, int) genutzt. UnknownHostException wird ausgeworfen, wenn für den Host keine IP-Adresse gefunden werden kann. Besonders interessant ist die Methode public static InetAddress getLocalHost() throws UnknownHostException, die den lokalen Host in Form seiner IP-Adresse zurückliefert. Wenn ein Securitymanager aktiv ist, wird eine SecurityException ausgeworfen, wenn die Abfrage nicht erlaubt ist. UnknownHostException wird ausgeworfen, wenn der Host nicht gefunden werden kann. Sobald die Verbindung geöffnet ist, können Sie wie üblich mit Ein- und Ausgabeströmen arbeiten. Die Eingabe könnte so realisiert werden: DataInputStream eingabe = new DataInputStream(new BufferedInputStream(verbindung.getInputStream()));
Die Ausgabe könnte analog laufen: DataOutputStream ausgabe = new DataOutputStream(new BufferedOutputStream(verbindung.getOutputStream()));
Sehr sinnvoll sind in diesem Zusammenhang serialisierte Objekte, die zwischen Socket und ServerSocket hin- und hergesendet werden. Wir werden das im nachfolgenden Beispiel tun. Ein Socket sollte geschlossen werden, wenn alle Arbeiten erledigt sind. Dazu dient die close()-Methode. Java 2 Kompendium
875
Kapitel 16
Weiterführende Themen Beispiel: verbindung.close(); Die Klasse ServerSocket kümmert sich um Client-Anforderungen, wobei ServerSocket diesen Service nicht selbst ausführt, sondern ein Socket-Objekt im Auftrag des Clients erstellt. Die Kommunikation wird dann über dieses Objekt ausgeführt. Man nennt diese Objekte serverseitige Sockets. Ein ServerSocket richtet sich nach einem TCP-Port, um eine Client-Verbindung aufzubauen. Wenn sich nun ein Client an diesen Port anschließt, muss diese Verbindung mittels einer eigenen Methode – der accept()-Methode – akzeptiert werden. Wenn Sie diese Methode im Server notiert haben, wird der Server dort auf eine Verbindung zu einem Client warten. Um ein ServerSocket zu erstellen, gehen Sie ähnlich vor wie bei den clientseitigen Sockets. Als Erstes erstellen Sie eine Instanz von der Klasse. Dies geschieht mit der folgenden Syntax: ServerSocket verbindung = new ServerSocket(portnummer);
Dabei ist portnummer durch die Nummer des Ports zu ersetzen. Sie haben damit einen Port festgelegt, den Sie dann für Client-Anfragen mit der accept()-Methode freigeben können. Beispiel: verbindung.accept(); Danach können Sie wieder die Ein- und Ausgabeströme verwenden, um mit dem Client über Lese- und Schreibvorgänge zu kommunizieren. Spielen wir den Vorgang in einem Beispiel durch, wobei wir hier mit serialisierten Daten arbeiten. Zuerst erstellen wir den Quelltext für den Server. Listing 16.12: Der ServerSocketPart
876
import java.io.*; import java.net.*; import java.util.*; public class MeinServer { // Serversocket erstellen und den Strom zum // Empfang von serialisierten Objekten verwenden public static void main(String args[]) { ServerSocket meinServerSocket = null; Socket meinSocket = null; String str1 = null; String str2 = null; try { meinServerSocket = new ServerSocket(1234); System.out.println("Server ist gestartet und wartet auf einen Client."); // Warten auf eine Verbindung zu diesem // Socket meinSocket = meinServerSocket.accept(); // Eingabestrom von serialisierten Objekten Java 2 Kompendium
Netzwerkzugriffe, Sockets und Servlets
Kapitel 16
// entgegennehmen InputStream o = meinSocket.getInputStream(); ObjectInput s = new ObjectInputStream(o); str1 = (String) s.readObject(); str2 = (String) s.readObject(); s.close(); // Ausgabe der vom Client übergebenen Werte System.out.println(str1); System.out.println(str2); } catch (Exception e) { System.out.println("Nix is: " + e.getMessage()); System.exit(1); } }}
Der Client sieht so aus: import java.io.*; import java.net.*; import java.util.*; public class MeinClient { public static void main(String args[]) { try { // Socket erstellen Socket meinSocket = new Socket(InetAddress.getLocalHost(), 1234); // Outputstream erstellen, mit Socket // verbinden und serialisieren OutputStream o = meinSocket.getOutputStream(); ObjectOutput s = new ObjectOutputStream(o); System.out.println( "Ab geht es an den Server."); s.writeObject( "Server, das sagt dir dein Client:"); s.writeObject(args[0]); s.flush(); s.close(); System.out.println("Das war's. Und ciao."); } catch (Exception e) { System.out.println("Nix is: " + e.getMessage()); System.exit(1); } }}
Java 2 Kompendium
Listing 16.13: Der Client-Part
877
Kapitel 16
Weiterführende Themen Starten Sie zuerst den Server und dann in einer eigenen DOS-Box bzw. einer zusätzlichen Shell das Clientprogramm. Der Server meldet sich mit einer kurzen Ausgabe und wartet dann auf eine Verbindung zum Client. Der Client übergibt die serialisierten Strings an den Server, der diese dann in seiner Shell ausgibt. Sollte das Beispiel nicht funktionieren, wird es unter Umständen am Port liegen. Probieren Sie einen anderen Port aus.
Abbildung 16.18: Socket-Kommunikation über zwei Shells hinweg
Wenn ein Server mehrere Clients bedienen soll, muss er sinnvollerweise Multithreading-fähig sein. Ein Thread wartet dabei permanent auf Verbindungen. Datagram-Sockets Kommen wir nun zu einer paketorientierten Verbindungsart. Über DatagramSockets zu kommunizieren ist einfacher als über die Klassen Socket und ServerSocket, die auf TCP basierende Sockets sind. Die Kommunikation ist sogar schneller, da der Verbindungsaufwand bedeutend geringer ist. Das TCP-Protokoll ist ein sehr sicheres Protokoll. So versucht es beispielsweise, Pakete nochmals zu versenden, wenn ein Fehler auftritt. Die darauf aufsetzenden Sockets können und müssen diese Fähigkeiten auch nutzen, was zwar sicher ist, jedoch zu Lasten der Geschwindigkeit geht. Ein Datagram-Paket dagegen wird einfach als eine Ansammlung von Bytes an ein empfangendes Programm gesendet. Das empfangende Programm wartet 878
Java 2 Kompendium
Netzwerkzugriffe, Sockets und Servlets
Kapitel 16
in der Regel an einer bestimmten IP-Adresse und einem zugehörigen Port. Man nennt diese Kommunikation über Datagramme UDP (Unreliable Datagram Protocol): Das Empfängerprogramm wird zum Sender, wenn es dem sendenden Programm eine Antwort schicken möchte. Dazu wird einfach an die aus dem empfangenen Sendevorgang bekannte IP- und Portadresse des ursprünglichen Senders zurückgeschickt. Das Verfahren ist aus der Funktechnik bekannt. Eine Station wird abwechselnd zum Sender und Empfänger. Datagram-Sockets sind dann zur Kommunikation sinnvoll, wenn es auf
Geschwindigkeit und/oder geringe Übertragungsmengen ankommt und die Übertragungssicherheit nicht so wichtig oder anderweitig gewährleistet ist. Letzteres ist z.B. dann gegeben, wenn die Kommunikation nur lokal stattfindet oder die Leitungen störungsfrei und sicher sind. Versenden eines Datagram-Pakets Um ein Datagram-Paket zu versenden, erstellen Sie zuerst eine Instanz von der Klasse. Dies geschieht beispielsweise mit der folgenden Syntax: DatagramPacket meinPacket = new DatagramPacket( byte_array, nachrichten_laenge, internet_addresse, port);
Die Angabe byte_array ist ein byte-Array, das die versendete Nachricht beinhaltet. Die Angabe nachrichten_laenge ist ein Integerwert, der die Länge der Nachricht angibt. Die Angabe internet_addresse beinhaltet die IP-Adresse, wo die Nachricht hin gesandt werden soll. Die Angabe port ist wieder ein Integerwert, der die Port-Nummer spezifiziert. Anschließend erstellen Sie eine Instanz von DatagramSocket: DatagramSocket meinSocket = new DatagramSocket();
Mit der send()-Methode können Sie nun das gerade erstellte Paket versenden: meinSocket.send(meinPacket);
Das Socket sollte wieder geschlossen werden, wenn alle Arbeiten erledigt sind. Dazu dient wieder die close()-Methode: meinSocket.close(); Java 2 Kompendium
879
Kapitel 16
Weiterführende Themen Empfangen eines Datagram-Pakets Das Datagram-Paket ist nun unterwegs zum Ziel und soll dort empfangen werden. Um ein Datagram-Paket zu empfangen, gehen Sie ziemlich ähnlich zum Senden vor. Sie erstellen zuerst eine Instanz von der Klasse DatagramPacket, allerdings mit einem etwas veränderten Konstruktor. Dies geschieht nun beispielsweise mit der folgenden Syntax: DatagramPacket empfangPacket = new DatagramPacket(buffer, buffer.length );
Die Angabe buffer ist wieder ein byte-Array, das die Nachricht nach dem Empfang beinhalten soll, danach folgt die Länge des Arrays. Anschließend erstellen Sie eine Instanz von DatagramSocket: DatagramSocket empfangSocket = new DatagramSocket(port);
Die Angabe port ist ein Integerwert, der durch den Port zu ersetzen ist, den der Sender verwendet. Mit der receive()-Methode können Sie nun das spezifizierte Paket empfangen: empfangSocket.receive(empfangPacket); Das Socket sollte über die close()-Methode wieder geschlossen werden, wenn alle Arbeiten erledigt sind.
16.5
Datenbanken und JDBC
Die netzwerkorientierte Struktur von Java macht die Sprache zu einem idealen Kandidaten für Client-Server-Einsätze. Das 3-Tier-Schichtmodell und Servlets haben dies ja schon angedeutet. Client-Server-Datenbanken sind ein sehr wichtiges Beispiel in der Praxis. Java wird als plattformunabhängiger Client für Datenbanken eingesetzt, auf die über das Netzwerk zugegriffen werden kann. Wegen der Plattformunabhängigkeit muss man sich keine großen Gedanken über plattformspezifische Fragestellungen machen. Für den Zugang zu Datenbanken von außen bietet Java eine einfache Möglichkeit – die Java DataBase Connectivity (JDBC). Diese Schnittstelle erlaubt es Entwicklern von Datenbankanwendungen, datenbankunabhängige Java-Clients zu schreiben, die auf zahlreiche verbreitete relationale Datenbanken zugreifen können. Auf Grund des modularen Aufbaus der JDBC-Spezifikation können aufgabenbezogene Erweiterungen hinzugefügt und für die Datenverarbeitung notwendige Tools jederzeit integriert werden. Diese können über den JDBCLayer mit den erforderlichen Datenbanken kommunizieren. Die JDBC-Trei880
Java 2 Kompendium
Datenbanken und JDBC
Kapitel 16
ber übernehmen dabei die gesamte Datenbankanbindung. Sofern sich die Datenbankentwickler an die normale Standard SQL-Syntax (SQL = Structured Query Language) halten, sollte jedes Datenbankprodukt mit einem JDBC-kompatiblen Treiber verwendet werden können. JDBC ist nicht als Produkt zu verstehen, sondern es handelt sich um die abstrakte Spezifikation einer Schnittstelle zwischen einer Client-Anwendung und einer SQL-Schnittstelle. Das Interface ist als Low-Level-API zum grundlegenden SQL-Zugriff entworfen worden. Es liegt an den verschiedenen Herstellern von Datenbanken und Software, ob JDBC-kompatible Treiber eingebaut werden, damit Java-Anwendungen mit den Datenbanksystemen verbunden werden können.
16.5.1
Was sind relationale Datenbanken?
Die Grundlagen von Datenbanken dürften nicht jedem Leser ein Begriff sein. Aber auch einige Leser mit Vorkenntnissen in Programmierung werden bisher noch keine Erfahrung mit der Erstellung und dem Zugriff auf Datenbanken aus einer eigenen Applikation heraus gemacht haben. Das Thema Datenbankprogrammierung ist eher im Bereich der professionellen Software-Entwicklung angesiedelt. JDBC gibt Ihnen die Möglichkeit, aus Java relativ einfach auf relationale Datenbanken zuzugreifen. Wir wollen deshalb in einem kleinen Exkurs erst einmal klären, was sich hinter dem Konzept einer relationalen Datenbank verbirgt. Im Allgemeinen enthalten Datenbanken Informationen, die in einer bestimmten Weise angeordnet sind und die auf Grund von bestimmten Abfragen aufbereitet und ausgegeben werden können. Eine Datenbank kann in tabellarischer Form vorliegen, aber ebenso komplexer geordnet sein. Man unterscheidet vom Konzept her drei Haupttypen von Datenbanken: Hierarchisch strukturierte Datenbanken Relational aufgebaute Datenbanken Netzwerkdatenbanken Historisch das älteste System ist die hierarchisch strukturierte Datenbank. In der Computersteinzeit (70er- bis 80er-Jahre) war das System sehr populär. Dabei werden Daten als ein Baumsystem mit Datensammlungen behandelt, die als Äste dargestellt werden. In einem hierarchischen Schema müssen Zugriffe auf die Daten entlang der Baumstruktur verlaufen. Die üblichste Beziehung in einer hierarchischen Struktur ist eine »Eins zu Vielen-Beziehung« zwischen den Datensätzen. Eine »Viele-zu-Viele-Beziehung« ist ohne erhebliche Redundanz (Überschneidungen von Daten ohne zusätzlichen Informationsgehalt) nicht zu bewerkstelligen.
Java 2 Kompendium
881
Kapitel 16
Weiterführende Themen Aber klären wir erst einmal, was das mit »Eins zu Vielen-Beziehung« bzw. »Viele-zu-Viele-Beziehung« auf sich hat. Es gibt drei Arten von Beziehungen zwischen Datensätzen: Eins zu Eins: Ein Datensatz in einer Tabelle ist mit einem Datensatz in einer anderen Tabelle verbunden. Eins zu Vielen: Ein Datensatz in einer Tabelle kann mit vielen Datensätzen in einer anderen Tabelle verknüpft sein. Viele zu Vielen: Ein Datensatz in einer Tabelle kann genau wie bei einer »Eins-zu-Vielen-Beziehung« mit vielen Datensätzen in einer anderen Tabelle verknüpft sein. Daneben können aber auch weitere Datensätze in dem Beziehungsgeflecht solche »Eins-zu-Vielen-Beziehung« mit vielen Datensätzen in einer anderen Tabelle haben. Auf das hierarchische Schema folgten irgendwann die Netzwerk-Datenbanken. Das Netzwerk-Datenmodell entspricht einer »Viele-zu-Vielen-Beziehung« zwischen den Datenelementen. Man versucht sich den Unterschied zu dem hierarchischen Schema so zu verdeutlichen, indem man das hierarchische Schema mit einer Eltern-Kind-Beziehung vergleicht, während das Netzwerkschema eine Gleichgestellten-Beziehung repräsentiert. In den 90ern entstand das relationale Datenzugriffskonzept. Das relationale Schema betrachtet die Daten als eine Tabelle mit Zeilen und Spalten. Die Zeilen (auch Records genannt) stellen die Datensätze der Tabelle dar. Jede Zeile unterteilt sich entsprechend der Spalten in der Tabelle in Felder. Die Felder enthalten die eigentlichen Daten. Das Hauptkonzept beim relationalen Schema ist, dass die Daten einheitlich sind. Jede Zeile einer Tabelle enthält die gleiche Anzahl an Spalten. Viele solcher Tabellen (die sich in ihrer Struktur unterscheiden können) bilden eine Datenbank. Die Relationen zwischen verschiedenen Tabellen einer Datenbank sind der Namensgeber für das Konzept. Um zwei Tabellen miteinander zu verbinden, müssen die zwei Tabellen mindestens eine gemeinsame Spalte haben. Diese gemeinsame Spalte enthält die Information, die für einen Datensatz der einen Tabelle einen Zugriff auf die zugehörigen Informationen aus der anderen Tabelle erlaubt. Auf diesem Weg entsteht eine Eins zu Vielen-Beziehung. Die gemeinsamen Felder nennt man Schlüssel. Wenn man diesen Schlüssel mit Zuordnungsinformationen in einer separaten Tabelle verwaltet, spricht man von einer Index-sequenziellen Datenbank. Ein anderer Weg führt über eine dritte Tabelle mit zwei Spalten, eine für ein Schlüsselfeld der ersten Tabelle und die zweite entsprechend für die zweite Tabelle. Über diese beiden Spalten werden die Datensätze der beiden Tabelle einander zugeordnet, wodurch eine Relation entsteht. Dies ist dann eine Viele zu Vielen-Beziehung.
882
Java 2 Kompendium
Datenbanken und JDBC
16.5.2
Kapitel 16
Was ist SQL?
SQL (Structured Query Language) ist eine universelle Datenbanksprache, die Aktionen auf relationalen Datenbanken ermöglicht. Unter solche Aktionen fallen das Erzeugen (create), Aktualisieren (update), Einfügen (insert) und Löschen (delete) von Daten oder Datendefinitionen für die Erzeugung von Tabellen und Spalten. Des Weiteren gibt es Möglichkeiten, den Zugriff auf Datenelemente zu beschränken und Anwender und Gruppen zu erzeugen. Weitere Bestandteile der Sprache betreffen das allgemeine Datenmanagement, Backup-Verfahren, das Kopieren und Aktualisieren von umfangreichen Datensätzen und Transaktionsverarbeitung (SQL-Statements, die Datenreihen und -felder in eine Datenbank löschen, aktualisieren oder hinzufügen). Nahezu jeder Datenbankhersteller stellt über eine eigene Implementation von SQL sicher, dass man mit SQL auf seine Datenbank zugreifen kann.
16.5.3
JDBC versus ODBC
Einer der ersten JDBC-kompatiblen Treiber ist der JDBC-Treiber für ODBC-kompatible Datenbanken, mit dem Java-Programmierer leicht auf eine beliebige ODBC-kompatible Datenbank zugreifen können. Microsofts ODBC (Open Database Connectivity) basiert auf dem gleichen Konzept wie JDBC – dem X/Open SQL CLI (Call Level Interface). Die JDBC-Spezifikation ist der ODBC-Spezifikation von Microsoft zwar sehr ähnlich, ist aber – als von Sun entwickelte Schnittstelle – natürlich besser auf die Zusammenarbeit mit Java ausgelegt. Zusätzlich können viele der Mängel von ODBC – wie zu viele Zeichenketten, Verarbeitung von sehr großen binary-Objekten und falsch verweisende Pointer – mit Java leichter gehandhabt werden oder treten auf Grund der Art, wie Java unbekannte Datentypen behandelt, gar nicht erst auf. Die Hauptunterschiede zwischen JDBC und ODBC liegen darin, wie Daten zwischen dem Aufrufer und dem Treiber hin- und hergeschickt werden. ODBC ist ein C-basiertes API. Daher verwendet es das »(void*)«-Casting, um Spaltenergebnisse an die Aufrufprozedur zurückzugeben. Java verwendet dagegen Methoden, die die erwarteten Typen direkt an den Aufrufer zurückgeben. Da Java ebenso nicht auf eine statische Größe von Arrays beschränkt ist, können Probleme auf Grund zu großer Zeichenketten und verschiedener Zeichengrößen leicht innerhalb von Java gehandhabt werden. Darüber hinaus besitzt JDBC Sicherheitsstufen, die es bei ODBC nicht gibt.
Java 2 Kompendium
883
Kapitel 16
Weiterführende Themen
16.5.4
Grundaufbau von JDBC und des JDBC-Managers
JDBC arbeitet auf zwei Stufen. Die erste Stufe ist der Verbindungsaufbau zwischen der Java-Anwendung und dem JDBC-Treibermanager mittels der JDBC-API. Über diesen JDBC-Treibermanager kann ein Java-Programm dann mehrere JDBC-Treiber verwalten und mit ihnen Informationen und Daten austauschen. Jeder Treiber wiederum kann aus Java direkt auf lokale Daten zugreifen, ODBC als Zwischenebene dazwischen schalten oder einen Netzwerkzugriff auf eine Datenbank auslösen. Die Treiber registrieren sich bei dem JDBC-Manager während der Initialisierung, sodass der Manager einen Überblick über alle verfügbaren Treiber hat. Der JDBC-Manager hat noch weitergehende Aufgaben. So untersucht er beispielsweise den Zustand eines Treibers, damit ggf. ein Applet oder eine Applikation einen geeigneten Treiber herunterladen kann, wenn noch keiner auf dem System vorhanden ist. Während des Versuchs, sich mit einer Datenbank zu verbinden, gibt das Java-Programm eine Datenbank-URL an den JDBC-Manager weiter. Der JDBC-Manager ruft dann jeden geladenen JDBC-Treiber, bis man die angefragte URL öffnen kann. Jeder Treiber ignoriert solche URLs, die Datenbanken erfordern, zu denen er sich nicht verbinden kann. Java Client-Programme können diesen Vorgang des Treibersuchens übergehen und explizit angeben, welcher Treiber verwendet werden soll, wenn der Java-Client bereits vorher weiß, welcher Treiber geeignet ist. Die URLs von JDBC haben immer die folgende Form: jdbc:subprotocol:subname Das Subprotokoll ist der Name des Verbindungsprotokolls, und der Subname ist der Name der jeweiligen Datenbank innerhalb der Domäne des Protokolls. Sofern über den Subnamen Informationen über Host und Port verschlüsselt sind, sollte dieser den Host und den Port in der URL-StandardNotation angeben: //hostname:port/subname Beispielsweise kann eine ODBC-Datenbank mit Namen Bankkonten über den URL jdbc:odbc:Bankkonten spezifiziert werden. Die gleiche Datenbank auf dem Rechner bundesbank zusammen mit dem Verbindungsprotokoll ixnet würde folgende URL haben: jdbc:ixnet://bundesbank/Bankkonten
Jeder Client kann mehrere Datenbankverbindungen geöffnet haben, wobei jede von diesen Verbindungen die Instanz einer Klasse ist, die aus java.sql.connection abgeleitet ist. Die Mehrfachverbindung kann über den gleichen JDBC-Treiber oder über mehrere unterschiedliche Treiber laufen.
884
Java 2 Kompendium
Datenbanken und JDBC
16.5.5
Kapitel 16
Woraus besteht das JDBC-API?
JDBC besteht aus mehreren portablen Java-Klassen/-Schnittstellen und liegt derzeit als JDBC 2 vor, das im SDK 2 von Java integriert ist. JDBC wurde vor dem SDK 2 so gut wie ausschließlich über Klassen realisiert, die allesamt zum Paket java.sql gehören. Dieses Paket beinhaltet u.a. die nachfolgend beschriebenen Schnittstellen, Klassen und Ausnahmen. Wichtigste Schnittstellen: Interface
Beschreibung
CallableStatement
Ein Interface für die Ausführung von SQL-Stored-Procedures.
Connection
Eine Connection (Session) mit einer angegebenen Datenbank. Die Schnittstelle enthält eine Menge Funktionalität, von der Transaktionsverarbeitung bis zum Erzeugen von Statements bildet sie die Grundlage.
DatabaseMetaData
Allgemeine Metainformationen über die Datenbank. Um den JDBC-Einsatz möglichst einfach zu halten, unterstützen JDBC-konforme Programme die JDBC-Schnittstelle mit zusätzlichen Informationen (so genannte Metadaten) über die Datenbank und die Ergebnisse. Dies erfolgt mit Methoden der Schnittstellen java.sql.DatabaseMetaData und java.sql.ResultSetMetaData. Das bedeutet, es gibt über die eigentlichen Datenbankinhalte hinausgehende Informationen. Dies können beispielsweise der Tabellenname, die Breite einer Spalte, die Typen in einer Spalte usw. sein.
Tabelle 16.4: Schnittstellen für JDBC
Die Schnittstelle DatabaseMetaData stellt Katalogfunktionen bereit, die denen in ODBC ähneln. Eine Anwendung kann die zugrunde liegenden DBMS-Systemtabellen abfragen. ODBC gibt die Informationen als ResultSet zurück. JDBC gibt die Ergebnisse als ein ResultSet-Objekt mit wohldefinierten Spalten zurück. Ein DatabaseMetaData-Objekt stellt über 100 Methoden zur Verfügung. Die meisten davon werden jedoch wahrscheinlich nur selten Verwendung finden. Driver
Eine ganz wichtige Schnittstelle. Jede Treiberklasse muss sie implementieren. Die Schnittstelle stellt gewöhnlicherweise Informationen wie PropertyInfo, Versionsnummer usw. bereit.
ResultSet
Eine Tabelle mit Daten, die ein Datenbank-ResultSet repräsentieren, das gerade durch die Ausführung von einen Abfragestatement der Datenbank generiert wurde.
Java 2 Kompendium
885
Kapitel 16 Tabelle 16.4: Schnittstellen für JDBC (Forts.)
Weiterführende Themen
Interface
Beschreibung
ResultSetMetaData
Metainformationen über die Typen und Eigenschaften der Spalten in einem ResultSet-Objekt. Die Schnittstelle dient also zum Auswerten von Ergebnissen einer Abfrage. Verglichen mit dem DatabaseMetaData-Objekt ist das ResultSetMetaData-Objekt leichter und hat weniger Methoden. Über das ResultSetMetaData-Objekt kann man mehr über die Typen und Eigenschaften von Spalten in einem ResultSet herauszufinden. Die Methoden des ResultSetMetaDataObjekts wie getColumnLabel() und getColumnDisplaySize() kann man deshalb in normalen Anwendungsprogrammen verwenden.
SQLData
Mapping von anwenderdefinierten SQL-Typen.
SQLInput
Ein Eingabestrom, der einen Strom von Daten beinhaltet, die als Instanz von einem SQL-struktierten oder -getrennten Typ zu verstehen sind.
SQLOutput
Ein Ausgabestrom zum Schreiben der Attribute von anwenderdefinierten Typen in die Datenbank.
Statement
Ausführung eines statischen SQL-Statements und wieder Entgegennehmen der produzierten Resultate.
Struct
Standard-Mapping zwischen der Java-Programmiersprache für einen SQL-strukturierten Typ.
Klassen: Tabelle 16.5: Klassen für JDBC
886
Klasse
Beschreibung
Date
Wrapper für JDBC um java.util.Date zur Identifikation als ein SQL-Datum.
DriverManager
Die Basisklasse zum Managen eines Satzes von JDBCTreibern unter JDBC vor dem JDBC 2.0 API (dort gibt es alternative Möglichkeiten). Die Klasse enthält die Treiberinformationen, Statusinformationen und mehr. Wenn ein Treiber geladen ist, registriert er sich beim DriverManager. Wenn eine Verbindung geöffnet wird, wählt der DriverManager den Treiber in Abhängigkeit vom JDBC URL aus. Der DriverManager gibt ein Connection-Objekt zurück, wenn Sie die getConnection()-Methode verwenden.
DriverPropertyInfo
Treibereigenschaften für den Aufbau einer Connection.
Java 2 Kompendium
Datenbanken und JDBC
Kapitel 16
Klasse
Beschreibung
SQLPermission
Die Erlaubnis, die der Securitymanager checken wird, wenn Appletcode eine der setLogWriter-Methoden aufruft. Die Klasse ist neu im Java 2 SDK hinzugefügt worden.
Time
Wrapper für JDBC um java.util.Date zur Identifikation als ein SQL-Zeitwert.
Timestamp
Wrapper für JDBC um java.util.Date zur Identifikation als ein SQL-TIMESTAMP.
Types
Definition von Konstanten, die zur Identifikation von generierten SQL-Typen verwendet werden (JDBC-Typen).
Tabelle 16.5: Klassen für JDBC (Forts.)
Wichtigste Exceptions: Exception
Beschreibung
SQLException
Fehler beim Zugriff auf eine Datenbank.
SQLWarning
Warnungen beim Zugriff auf eine Datenbank.
Tabelle 16.6: Exceptions für JDBC
Wenn irgend möglich verwendet JDBC statische Typenfestlegungen zur Kompilierungszeit. Laufzeitfehler beim Datenbankzugriff erzeugen eine Ausnahme vom Typ java.sql.SQLException, die – wie alle Ausnahmen – eine Ableitung von java.lang.Exception ist. Aus diesem Grund sollten sämtliche Datenzugriffsmethoden throws SQLException zum Abfangen bereitstellen und diese in einem try-catch-Block bearbeiten. So etwas könnte folgendermaßen aussehen (eine einfache Ausgabe von Ausnahmen auf das Standardausgabegerät): try { // JDBC-Aufruf } catch (SQLException e) { System.out.println( "In folgendem SQL-Aufruf ist eine Ausnahme aufgetreten: " + e.getSQLState()); System.out.println("Die Meldung der Ausnahme lautet: " + e.getMessage()); System.out.println("Der zugehoerige Errorcode: " + e.getErrorCode()); }
Da ein JDBC-Aufruf zu Folgefehlern durch verkette Ausnahmen führen kann, wird oft die Ausnahmebehandlung in eine Schleifenstruktur verpackt: try { // JDBC-Aufruf
Java 2 Kompendium
887
Kapitel 16
Weiterführende Themen } catch (SQLException e) { while (e != null) { // ... Behandlung einer Ausnahme e.getNextException(); } }
Anders als eine SQLException, die das Programm wegen der ausgeworfenen Ausnahme bemerkt, verursacht eine SQLWarning in einem Java-Programm erst einmal keine Aufmerksamkeit oder gar Probleme. Eine SQLWarning wird an das Objekt, dessen Methode die Warnung verursacht hat, angehängt. Sie sollten deshalb mit der getWarning()-Methode, die für alle Objekte verfügbar ist, auf Warnungen hin überprüfen.
16.5.6
Die JDBC-Treiber
Die JDBC-Treiber existieren in verschiedenen internen Ausprägungen: Der Typ JDBC-ODBC ist für den Zugriff auf alle vorhandenen ODBCTreiber und ihre Datenquellen zuständig. Dieser Treiber wurde gemeinsam von Sun und Intersolv entwickelt und nennt sich JDBC-ODBCBridge. Die JDBC-ODBC-Bridge ist als jdbcOdbc.class in Java implementiert und eine native Bibliothek, um auf den ODBC-Treiber zuzugreifen (keine Standard-Klasse). Unter Windows ist die native Bibliothek eine DLL (JDBCODBC.DLL). Da JDBC sehr am Design von ODBC orientiert ist, ist die ODBC-Bridge eine dünne Schicht über JDBC. Intern mappt dieser Treiber JDBC-Methoden auf ODBC-Aufrufe und tritt so mit jedem verfügbaren ODBC-Treiber in Interaktion. Der Vorteil dieser Bridge ist, dass über JDBC fast alle Datenbanken angesprochen werden können, da es für die meisten Datenbanken ODBC-Treiber gibt. Wenn die ausführenden Binärdateien auf dem Clientrechner installiert sind, kann darüber dann der Zugriff auf Datenbestände erfolgen. Der wohl grö ß te Nachteil der JDBC-ODBCBridge ist die bei großen Datenbanken zu geringe Performance. Der zweite Typ von Treiber konvertiert JDBC-Aufrufe in Textkommandos einer darunter liegenden speziellen Datenbank-API, beispielsweise DB2, Informix, Oracle oder andere DBMS. Damit müssen auf dem Client wieder plattformabhängige Binärdateien vorhanden sein, die diese Kommandos sinnvoll auswerten und die eigentlichen Datenbankzugriffe erledigen. Vorteil dieser Technik gegenüber der JDBCODBC-Bridge ist bessere Performance. Die dritte Form von JDBC-Treibern spricht aus Java direkt Datenbanken an. Zumeist sind dies lokale Datenbanken. Dazu werden alle Zugriffs-, Lese-, Schreib- und Auswertungsaufgaben unmittelbar implementiert.
888
Java 2 Kompendium
Datenbanken und JDBC
Kapitel 16
Der vierte Typ von JDBC-Treibern ist für datenbankspezifische Netzwerkbefehle zuständig. Mittels dieses Treibers werden JDBC-Anweisungen in datenbankspezifische Netzwerkbefehle übersetzt, die die Datenbank-API auf dem Server dann ausführt. Diese Treiberform ist explizit nicht auf zusätzliche Binärdateien auf dem Client (witzigerweise ist hier mit Client der Server gemeint – ist halt eine andere Beziehung) angewiesen. Statt dessen wird direkt mittels den Java-NetzwerkKlassen mit der Datenbank kommuniziert. Diese verhalten sich dort wie jede andere Zugriffssoftware. Nahezu alle namhaften Hersteller von Datenbanken (und diverser Tools) bieten mittlerweile diese Form von Treibern an, weil sie einfach die effektivste, schnellste und sicherste Variante ist.
16.5.7
Schematischer Aufbau einer Datenbank-Applikation
Allgemein geht man bei Datenbankzugriffen so vor, dass man zuerst die notwendigen Packages einbindet. Das sind so gut wie immer java.net.URL bzw. java.net.* und java.sql.*. Oft brauchen Sie noch java.util.* und java.math.* (Letzteres, wenn Sie mit der Klasse BigDecimal arbeiten wollen). Im nächsten Schritt laden Sie die gewünschten JDBC-Treiber unter ihrem Java-Namen. Dies kann mit folgender Syntax geschehen: try { // Laden der gewünschten Treiber Class.forName(drivername); // ... weitere sinnvolle Aktionen } catch (ClassNotFoundException e) { // etwas Sinnvolles tun }
Die Methode forName() der Klasse Class erledigt das Laden der Treiberklasse (ein Vorgang, der auf der Fähigkeit der Reflection basiert). Dazu muss man allerdings den vollständigen Klassennamen kennen. Für die JDBC-ODBC-Bridge sieht das so aus: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Die Namen von anderen Treibern sind in der Dokumentation des jeweiligen Herstellers angegeben. Im nächsten Schritt können wir bereits eine Datenbankverbindung aufbauen. Als fiktives Beispiel soll unsere ODBC Datenbank mit Namen »dbtest« dienen. Über den URL jdbc:odbc:dbtest sprechen wir sie an:
Java 2 Kompendium
889
Kapitel 16
Weiterführende Themen String url="jdbc:odbc:dbtest"; Connection con = DriverManager.getConnection(url, "userid", "passwd");
Die Methode getConnection() liefert eine Connection zur Datenbank. Sie gibt es in verschiedenen Varianten. Insbesondere, wenn keine User-ID und kein Passwort notwendig sind, kann man auch einfach Folgendes notieren: Connection con = DriverManager.getConnection(url);
Der nächste Schritt dient dazu, ein Abfrageobjekt zu erstellen und darauf ein (im Grunde beliebiges) SQL-Kommando auszuführen. In unserem Beispiel wollen wir sämtliche Datensätze aus einer Tabelle namens Tabelle1 ausgeben. Statement abfrageobj = con.createStatement(); ResultSet ergebnis = abfrageobj.executeQuery("SELECT * from Tabelle1");
Wenn wir mittels einer SQL-Abfrage die Datensätze selektiert haben, sollten wir damit auch etwas Sinnvolles tun, z.B. auf dem Bildschirm nach gewissen Kriterien anzeigen, was folgende Methode tut: private static void zeigeResultate (ResultSet res) throws SQLException { // Zur Abfrage der Metadaten wird ein Metadatenobjekt // erstellt ResultSetMetaData resmeta = res.getMetaData(); // Abfrage der Anzahl von Spalten in der Tabelle über // das Metadatenobjekt int anzahlSpalten = resmeta.getColumnCount(); // Abfrage der Namen von den Spalten in der Tabelle // über das Metadatenobjekt und Ausgabe der vorhandenen // Spaltennamen (bis anzahlSpalten) for (int i=1; i 5 invokevirtual #8 <Method java.io.PrintStream.println(Ljava/lang/String;)V> 8 return Method HelloWorld() 0 aload_0 1 invokenonvirtual #6 <Method java.lang.Object.()V> 4 return } -classpath [Verzeichnis]
Diese Angabe korrespondiert wie bereits beim Compiler und Interpreter mit der gleichnamigen Umgebungsvariable und teilt in diesem Fall dem Disassembler mit, in welchen Verzeichnissen nach den einzelnen Klassen zu suchen ist. Die Verzeichnisse werden in der Unix-Syntax durch Doppelpunkte getrennt, Windows benutzt das Semikolon. Auch ist für Pfadangaben zu beachten, dass die Komponenten eines Pfades unter Unix mittels des Slash und unter Windows mittels des Backslash voneinander getrennt werden. Die angegebenen Pfade werden in der Reihenfolge ihres Auftretens durchsucht.
-bootclasspath path
Spezifiziert den Pfad, von wo die bootstrap classes zu laden sind (Default ist jre\lib\rt.jar und jre\lib\i18n.jar).
Java 2 Kompendium
907
Anhang A Tabelle A.1: Die Javap-Optionen (Forts.)
Option
Beschreibung
-extdirs dirs
Überschreibt den Pfad, wo Erweiterungen für das JDK gesucht werden (default jre\lib\ext).
-verbose
Diese Option veranlasst den Disassembler, diverse Statusinformationen (z.B. Stack, Variablen, Argumente usw.) über den Quellcode anzuzeigen, während er gerade disassembliert wird.
-l
Gibt zusätzlich noch Zeilennummern und lokale Variablen aus. Aus dem Beispiel oben wird Compiled from ErstesJavaProgramm.java class HelloJava extends java.lang.Object { public static void main(java.lang.String[]); HelloJava(); } Line numbers for method void main(java.lang.String[]) line 3: 0 line 2: 8 Line numbers for method HelloJava() line 1: 0
-b
Stellt die Rückwärtskompatibilität zu früheren Versionen sicher.
-public
Zeigt nur die öffentlichen Klassen und Bestandteile an.
-protected
Zeigt die geschützten und die öffentlichen Klassen und Methoden an.
-private
Zeigt alle Klassen und Methoden an.
-s
Zeigt interne Typ-Signaturen an.
-package
Zeigt die Pakete, die geschützten und die öffentlichen Klassen und Methoden an (Default).
-J Flag
Gibt ein Flag direkt an das Runtime-System weiter. Beispiele: javap -J-version javap -J-Djava.security.manager -J-Djava.security.policy=MeinePolicy MeinKlassenName
Javap gibt die Ausgabe der Dissamblierung standardmäßig auf den Bildschirm aus. Um den Source in eine neue Datei auszugeben (etwa zur späteren Weiterverwendung), können Sie unter der DOS/Windows-Eingabeaufforderung die Technik des Umleitens nutzen. Mit dem Umleitungszeichen > leiten Sie die Ausgabe des Befehls in eine beliebige Datei um. Die Datei mit dem rechtsseitig angegebenen Namen wird erstellt, die dann den zurückübersetz-
908
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
ten Quelltext enthält. Dieser kann dann beliebig weiter bearbeitet und unter Umständen sogar neu kompiliert werden (Achtung: Es fehlen je nach verwendeter Option Klassen oder einiger ihrer Bestandteile). javah – das Tool zur Erstellung von C-Header- und Stub-Dateien Der javah-Generator erstellt C-Header (Erweiterung .h) und C-Quelldateien (Erweiterung .c) für die angegebenen Klassen. Diese so generierten Dateien enthalten alle notwendigen Informationen zur Implementierung von nativen Methoden, beispielsweise #include- und #define-Anweisungen, typedefKonstrukte u.ä. Normalerweise generiert javah nur ein Headerfile für die angegebenen Klassen. Innerhalb dieses Headerfiles wird eine C-Struct deklariert, die alle notwendigen Felder enthält, die mit den Instanzfeldern der ursprünglichen Java-Klassen korrespondieren. Innerhalb dieser HeaderDatei wird ebenfalls bereits eine Funktion für jede native Methode definiert, die in der zugehörigen Quelldatei implementiert werden muss. Ein Aufruf von javah im klassischen HelloWorld-Programm in Java class HelloWorld { public static void main (String args[]) { System.out.println("Hello World!"); }}
wird die folgende Header-Datei erzeugen: /* DO NOT EDIT THIS FILE – it is machine generated */ #include /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld typedef struct ClassHelloWorld { char PAD;/* ANSI C requires structures to have a least one member */ } ClassHelloWorld; HandleTo(HelloWorld); #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif #endif
Auch so genannte Stub-Dateien, d.h. C-Dateien, die neben der HeaderDatei zusätzliche, notwendige Rumpffunktionen für die Einbindung von nativen Methoden in der Java-Umgebung enthalten, können von javah generiert werden. Bei Angabe der Option -stubs zur Erzeugung von StubDateien generiert bei unserem klassischen Java-HelloWorld-Programm eine .c-Datei, die wie folgt aussieht: Java 2 Kompendium
909
Anhang A /* DO NOT EDIT THIS FILE – it is machine generated */ #include <StubPreamble.h> /* Stubs for class HelloWorld */
Bei komplexeren Java-Programmen wird in demselben Maße das javahResultat entsprechend anspruchsvoller und nimmt Programmierern viel Arbeit ab. javah generiert standardmä ß ig eine C-Datei in dem aktuellen Verzeichnis,
deren Name identisch zu dem im Aufruf spezifizierten Klassenname ist. Wenn dieser Klassenname ein Paket enthält, so enthalten die C-Dateien sämtliche Komponenten des Paketnamens. Allerdings werden diese nicht durch Punkte, sondern durch Unterstriche getrennt. Die Syntax von javah: javah [Optionen] [Klassenname ]
Klassenname ist der Name der Java-Klassendatei ohne die Dateinamenserwei-
terung. Tabelle A.2: Die javah-Optionen
Option
Beschreibung
-help
Hilfe
-version
Die Version des JDK
-classpath [Verzeichnis]
Identisch mit den anderen Tools
-bootclasspath path Identisch mit den anderen Tools
910
-verbose
Identisch mit den anderen Tools
-d [Verzeichnis]
Mit dieser Option wird javah gezeigt, in welchem Verzeichnis sich die Header oder Stub-Dateien nach der Generierung befinden sollen. Normalerweise wird das aktuelle Verzeichnis verwendet. Diese Option und die Angabe der Option -o schließen sich aus.
-stubs
Diese Option veranlasst javah, Stub-Dateien statt der Standard-Header-Dateien zu erzeugen.
-o [Dateiname]
Mit dieser Option wird javah veranlasst, die Stubs- oder Header-Dateien in die mit Dateiname spezifizierte Datei (eine Datei, in der alle .h- oder .c-Dateien kombiniert werden) einzufügen. Bei der Datei kann es sich um eine normale Textdatei, um eine Header-Datei ([Dateiname].h) oder eine Stub-Datei ( [Dateiname].c) handeln.
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Option
Beschreibung
-jni
javah wird angewiesen, im erzeugten Header-File JNI-
Anhang A Tabelle A.2: Die javah-Optionen (Forts.)
style native method function prototypes zu generieren. -old
Gibt an, dass Header-Dateien nach dem alten JDK1.0Konzept erstellt werden sollen.
-force
Erzwingt die Erstellung einer Ausgabedatei.
Das Dokumentations-Tool javadoc Eines der am meisten unterschätzten Tools im JDK ist javadoc. Das JDK verfügt damit über ein feines, eigenes Dokumentations-Tool, das auf der Basis von speziellen Kommentar-Tags innerhalb einer Java-Quelldatei (es gibt drei Formen von Kommentaren in Java, hierfür wird die folgende Form benötigt: /** Kommentartext */ ) eine HTML-Datei als API-Dokumentation der angegebenen Datei oder des Paketes erzeugt. Vereinfacht gesagt, schreibt javadoc die innerhalb der Datei in den javadocKommentaren eingeschlossenen Texte kurzerhand in eine HTML-Datei. Darin können sich beliebige Informationen befinden. Es bleibt im Prinzip dem Programmierer überlassen, was er mit diesen Kommentaren über seinen Quelltext dokumentieren möchte. Außerdem kann man die Kommentare mit Steueranweisungen zur Erzeugung von Hyperlinks und speziellen Tags erweitern. Allerdings benötigt man dafür kein eigenes Tool, auch mit einem Editor ist dies halbwegs machbar. Es werden zusätzlich noch automatische Informationen über die Klassen, Interfaces, Vererbungshierarchien, Methoden, Variablen und Hyperlinks, die mit dem Java-Programm in Verbindung stehen können, aufgeführt. Die erzeugte Dokumentation enthält sämtliche als public und protected deklarierte Elemente. Javadoc wurde ursprünglich von den SUN-Entwicklern erstellt, um die Java-API-Dokumentation zu erzeugen. Die Leistungsfähigkeit dieses Tools wird besonders deutlich, wenn man Anspruch und Wirklichkeit bezüglich der Dokumentation in SoftwareProjekten gegenüberstellt. In der professionellen Software-Entwicklung sollte Planung bzw. Konzeption eines Projekts mit ca. 30 % oder mehr einkalkuliert werden (es kommt stark auf die Rahmenbedingungen an, aber die Grö ß enordnungen stimmen ungefähr). Die Realisierierung schlägt dann vielleicht mit 50 % zu Buche und der Rest (also ca. 20 %) sollte für die Dokumentation zur Verfügung stehen. Die Praxis sieht dann meist so aus, dass nach 30 % der Zeit mit der Realisierung zwar begonnen wird, die Planung und Konzeption aber noch nicht abgeschlossen ist und ständig Veränderungen in der Realisierungsphase bewirkt. Diese Phase benötigt dann
Java 2 Kompendium
911
Anhang A 90 % der Zeit1 und wo bleibt dann noch Kapazität für die Dokumentation? Oft wird sie als nicht so wichtig betrachtet. Je mehr Schitte der Dokumentation dann mit einem Tool erfolgen können, das automatisch die wichtigsten Details herausarbeitet, desto besser. In dieser Hinsicht ist javadoc vielleicht sogar das einzige Tool des JDK, das man in der Praxis nicht durch ergänzende oder alternative Tools ersetzt. Die zu dokumentierende Datei muss mindestens eine public oder protected deklarierte Klasse enthalten. Die Syntax von Javadoc: javadoc [Optionen] [Dateiname] [Paketname] [@files] Dateiname ist die .java-Datei bzw. der Paketname. Die Datei kann sowohl
ohne die Dateinamenserweiterung, als auch mit Erweiterung angegeben werden kann (leider wieder keine konsistente Syntaxlogik bzgl. der anderen JDK-Programme). Wenn ein Paketname angegeben worden ist, dann dokumentiert javadoc alle Java-Quelldateien innerhalb des aktuellen Verzeichnisses und anschließend das dazugehörige Paketverzeichnis (als Paketname zu verstehen und nicht etwa als ein physikalisches Verzeichnis). Für jede Klasse wird ein eigenes HTML-Dokument erzeugt und für die Klassen innerhalb des Paketes wird ein HTML-Index generiert. Standardmä ß ig werden also minimal vier HTML-Dateien (eine Index-Datei, [Name der Datei].html, packages.html und tree.html) generiert. Abbildung A.1: Aus einer JavaDatei werden per javadoc alle anderen Dateien generiert.
1
912
;-)
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A Abbildung A.2: Die Dokumentation erfolgt im Stil der Java-Online-Dokumentation.
In der ersten Version von javadoc gab es noch die unangenehme Eigenart, bei Aufruf ohne Parameter einfach anzufangen zu dokumentieren. Was? Das wußte javadoc ebenfalls nicht und so folgte zwangsläufig irgendwann eine Fehlermeldung. Durchaus vergleichbar mit einem Taxifahrer, der einfach losfährt, nachdem der Gast eingestiegen ist. Aber ohne nach dem Weg zu fragen. Erst ein paar Straßen weiter kommt dann die Rückfrage, wo es eigentlich hin gehen soll. Seit dem JDK 1.1.x ist das glücklicherweise vorbei und es wird eine Kurzbeschreibung mit allen Parametern auf dem Bildschirm ausgegeben. Die javadoc-Optionen Mittlerweile sind die Optionen des Dokumentations-Tools so umfangreich geworden, dass wir hier nur eine Zusammenfassung der wichtigsten Optionen angeben wollen. Diejenigen Optionen, die mit den bisher beschriebenen Optionen der anderen Tools übereinstimmern, haben auch die dort beschriebene Funktion. Das Dokumentations-Tool des JDK versteht u.a. folgende Optionen, die teilweise selbsterklärend sind und oft auch weggelassen werden können (für Details sei auf die Online-Dokumentation verwiesen): -1.1, -author, -bootclasspath, -bottom, -classpath, -d, -docencoding, -doclet, -docletpath, -doctitle, -encoding, -extdirs, -footer, -group, -header, -help, -helpfile, -J, -link, -linkoffline, -locale, -nodeprecated, -nodeprecatedlist, -nohelp, -noindex, -nonavbar, -notree, -overview, -package, -private, -protected, -public, -sourcepath, -splitindex, -stylesheetfile, -title, -use, -verbose, -version, -windowtitle
Java 2 Kompendium
913
Anhang A Das Dokumentations-Tool des JDK wurde für die Version 1.2 erheblich überarbeitet. Hier folgt eine Liste mit den wichtigsten Veränderungen: -use – Hinzufügen einer Cross-Referenzdokumentation (Beschreibung, dass das API andere APIs verwendet) -link und -linkoffline – Generierung von Links auf existierende Dokumentationen, die mit javadoc-generiert wurden -windowtitle – Angabe des Titels, der in das HTML -Tag geschrieben wird -doctitle – Titel der Seite (bisher die Option -title) -group – Unterteilung von Paketen in Gruppen.
Die Funktion eines Dokumentations-Tools muss sich naturgemäß von den übrigen Tools ein wenig unterscheiden. Insbesondere werden Querverweise (»siehe auch ...«) eine wichtige Rolle bei der Dokumentation spielen. Diese können jedoch nicht als Aufrufparameter übergeben werden, sondern müssen wie oben beschrieben Bestandteile des Quelltextes sein. Sie werden dort innerhalb der Kommentar-Tags mit einem speziellen Zeichen eingeleitet (die so genannten javadoc-Tags). Die Tags beginnen nach dem eigentlichen Kommentarbeginn alle mit dem Zeichen @. Die javadoc-Tags Tabelle A.3: Die javadoc-Tags
914
Tag
Beschreibung
@link
Setzt einen in-line-Link an diesem Punkt.
@version
Mit diesem Tag kann die Version des Programms spezifiziert werden.
@throws
Wie @exception.
@since
Spezifiziert, wann das Release erstellt wurde.
@serialField
Dokumentiert eine ObjectStreamField-Komponente eines serialPersistentFields-Mitglieds einer Serializable-Klasse.
@serialData
Beschreibt die Daten, die von der writeObject()- und der Externalizable.writeExternal()-Methode geschrieben werden.
@serial
Dokumentation eines serialisierbaren Defaultfeldes.
@see
Dieses Tag erzeugt einen Verweis in der HTML-Datei.
@return
Mit diesem Tag kann der Wert beschrieben werden, der von einer Methode zurückgegeben wird.
@param
Dieses Tag dient zu Dokumentation der Parameter.
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Tag
Beschreibung
@exception
Dieses Tag erzeugt ein Link auf Ausnahmen, die von der Klasse erzeugt werden.
@deprecated
Der Tag markiert ein Klasse, ein Interface, ein Feld oder eine Methode als nicht zu verwenden in weiteren Anwendungen. So gekennzeichneter Code wird dennoch weiter kompiliert und laufen, aber der Compiler – natürlich nur der einer neueren Generation – wird eine Warnung generieren, dass Sie Ihren Code bzgl. dieses Ausdrucks updaten sollten.
@author
Dieses Tag fügt den Namen des Autors in die HTML-Datei ein.
Anhang A Tabelle A.3: Die javadoc-Tags (Forts.)
Beispiel für einen Quelltext mit javadoc-Kommentar und javadoc-Tags: /** * Um was es geht. * @version3.42 * @authorRalph Steyer */ class HelloWorld { /* Kommentarform 2 – wird von javadoc nicht brücksichtigt*/ public static void main (String args[]) { System.out.println("Hello World!"); }}
Beachten Sie, dass der javadoc-Kommentar außerhalb der Klassendefinition steht. Dies ist wichtig, denn der Generator ignoriert den Kommentar bei einer Verschachtelung mit einer Klassendefinition. jdb - der Java-Debugger Als Nächstes soll der Java-Debugger jdb, das Debugging-Werkzeug des JDK, behandelt werden. Es handelt sich nicht um einen integrierten Debugger, wie er mittlerweile in den meisten Entwicklungsumgebungen üblich ist. Den Debugger können Sie nur über Befehlszeileneingaben steuern. Er verfügt nur über eine ähnliche Syntax wie die bekannten Unix-Debugger dbx oder gdb. Allerdings ist er in der Lage, neben den lokalen Dateien auch Dateien auf entfernten Systemen (Anwendungen und Applets) auf Fehler zu überprüfen. In diesem Fall müssen Sie die notwendigen -host und die -password-Optionen verwenden. Mit dem jdb können Sie beliebig Haltepunkte setzen und die Werte der Variablen ausgeben lassen. Steppen durch den Source – sprich das Programm in Einzelschritten auszuführen – wird ebenfalls unterstützt. Der Code in der Umgebung eines Haltepunktes kann jederzeit aufgelistet werden. Sie können jedes Mal, wenn das Programm angehalten oder unterbro-
Java 2 Kompendium
915
Anhang A chen wird, den Stack mit den Aufrufen untersuchen. Weiter unterstützt jdb die Bewegung durch die Threads in Ihrem Code. Exceptions sind ein weiterer Problemfall, wo Sie jdb unterstützt, indem er die Ausnahmen (auf Wunsch) auffängt, selbst wenn sie im Programm nicht aufgefangen werden. Erst einmal abgefangen, können Sie dann die Variablen und den Stack untersuchen. Im JDK 1.3 wurde der Debugger erheblich überarbeitet, sodass er in vielen Details nicht mehr mit seinem Vorgänger des JDK 1.2 übereinstimmt. Dafür kam im JDK 1.3 das Debugging-Tool oldjdb hinzu, was im Wesentliche dem Vorgänger des aktuellen jdb entspricht2. Dieses ist – wie alle mit old beginnenden Tools – für die Arbeit mit Quellcode vorhanden, der bestimmte Kriterien älterer Java-Versionen nutzt, die mit dem neuen Standard nicht vereinbar sind. Der neue Debugger jdb wurde gegenüber seinem Vorgänger bezüglich seiner erlaubten Optionen erheblich erweitert. Man muss trotz der unbestrittenen Leistungsfähigkeit von jdb festhalten, dass seine Bedienung wohl die meisten Wünsche im JDK offen lässt. Sie ist relativ umständlich. Außerdem setzt die Verwendung von jdb recht viel Hintergrundwissen voraus. Auch wer sich mit dem Debuggen schon auskennt, wird mit einem integrierten Debugger leichter zum Erfolg kommen. Vorbereitung einer Debugger-Sitzung Bevor Sie den Debugger verwenden, müssen Sie Ihre Klassen erst einmal entsprechend kompilieren, damit für den Debugger genügend Informationen zur Verfügung stehen. Dazu müssen Sie den Java-Compiler mit der Option -g ausführen. Die Syntax für die vorbereitende Kompilierung: javac -g [Name der Datei].java
Das Ergebnis dieser Kompilierung sollte ein nicht optimierter Bytecode sein, den jdb für den Zugriff auf die Symboltabellen für lokale Variablen benötigt. jdb hängt sich auf Grund dieser Information quasi in den Bytecode hinein. Eine jdb-Debugging-Sitzung lässt sich auf zwei (drei, wenn man Interpreter- und Appletviewer-Sitzung unterscheidet) verschiedene Arten starten. Sie können jdb veranlassen den Java-Interpreter mit den zu bearbeitenden Klassen im Debugging-Modus zu starten oder Sie können jdb starten und dazu auffordern, sich an einen laufenden Java-Interpreter (bzw. einen laufenden Appletviewer) anzuhängen. jdb versteht dieselben Optionen wie der Java-Interpreter. Sie können den Debugger also einfach anstelle des Interpreters aufrufen und sämtliche Optionen des Interpreters verwenden. 2
916
Sun gibt allerdings an, dass es kaum Gründe für die Verwendung dieser explizit abwärtskompatiblen Version gibt.
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
Natürlich besitzt er aber auf Grund seiner weitergehenden Funktionen zusätzliche eigene Optionen. Auch hier gilt wieder, dass der Compiler zwingend die Erweiterung .java voraussetzt. jdb jedoch benötigt in der Folge die Erweiterung .class nicht zwingend. Es ist jedoch in diesem Fall auch kein Fehler, was wieder eine der vielen Inkosistenzen im JDK ist. Direkter Aufruf des Debuggers Eine Debugger-Sitzung kann man auf vielfältige Weise durchführen. Die üblichste Methode ist der direkte Aufruf des Debuggers mit der zu untersuchenden Klasse, die eine main()-Methode enthalten muss. Die eigentliche Syntax für den direkten Aufruf des Debugger ist nicht sonderlich umfangreich: jdb [Optionen] [KlassenName] oldjdb [Optionen] [KlassenName]
Die Optionen des Debuggers sind im JDK 1.3 gegenüber den Vorgängerversionen erheblich verändert und erweitert worden. Option
Beschreibung
-host [Hostname]
Diese Option informiert jdb bzw. oldjdb, auf welchem Rechner sich das entfernte Java-Programm befindet. Hostname steht dabei für den DNS-Namen des Remote-Computer.
-password [password]
Diese Option gibt das Passwort für die Java-Datei auf einem entfernten System, das vom Java-Interpreter mit der -Xdebug Option angegeben wurde, an jdb bzw. oldjdb weiter. Bei einer Arbeit auf einem entfernten Rechner ist ein solches Passwort oft zwingend. Außerdem muss das Passwort verwendet werden, wenn man den Debugger als Zweitprozess nach Start des Interpreters verwenden möchte.
-help
Hilfe (jdb bzw. oldjdb)
-version
Debuggerversion (jdb bzw. oldjdb)
-dbgtrace
Ausgabe von Informationen über jdb bzw. oldjdb
-sourcepath
Verzeichnisse, die durchsucht werden sollen (nur jdb)
Java 2 Kompendium
Tabelle A.4: Die Optionen von jdb und oldjdb im JDK 1.3
917
Anhang A Tabelle A.4: Die Optionen von jdb und oldjdb im JDK 1.3 (Forts.)
Option
Beschreibung
-attach
Anhängen an eine laufende VM an der spezifizierten Adresse mit dem Standard-Connector (nur jdb)
-listen
Warten auf eine laufende VM an der spezifizierten Adresse mit dem Standard-Connector (nur jdb)
-listenany
Warten auf eine laufende VM an einer beliebigen Adresse mit dem Standard-Connector (nur jdb)
-launch
Direkter Start statt auf das run-Kommando zu warten (nur jdb)
-connect :=, Connector mit dem aufgelisteten Argumenten auf... bauen (nur jdb). -thotspot
Die Applikation mit der im JDK 1.3 neu eingeführten Hotspot(tm) Performance Engine laufen lassen (nur jdb).
-tclassic
Die Applikation mit der klassischen VM laufen lassen (nur jdb).
Wenn Sie jdb direkt im Befehlszeilenmodus unter DOS (oder Xterm) mit der Angabe einer Klasse gestartet haben, wird die Ausgabe im entsprechenden Fenster etwa so aussehen: Initializing jdb...
Bis jetzt wurde der Code noch nicht ausgeführt. Deshalb sehen Sie im Ausgabefenster nicht viel mehr als diese Zeile. Wenn Sie jdb auf diese Weise benutzen, startet er den Java-Interpreter mit den jeweils in der Befehlszeile festgelegten Parametern, lädt die spezifizierte Klasse und hält an, bevor die erste ausführbare Anweisung der Klasse ausgeführt wird. Wie es weiter geht, werden wir gleich sehen. Vorher aber besprechen wir noch die weiteren Aufrufmöglichkeiten für den Debugger. Start des Debuggers als Folgeprozess des Interpreters Neben dem direkten Aufruf des jdb können Sie das Programm gleichermaßen mit dem Java-Interpreter starten und anschließend jdb als getrennten Prozess aufrufen, der Ihrem laufenden Programm dann hinzugefügt wird. Dieser Weg ist zwar nicht so üblich, wir wollen ihn dennoch skizzieren. Dazu müssen Sie den Interpreter mit der Option -Xdebug und Angabe der entsprechenden Klasse starten. Vor der Ausführung der angegebenen Klasse gibt java ein Passwort aus. Dieses Passwort muss dann als BefehlszeilenParameter für jdb benutzt werden und jdb wird sich dann mit diesem Pass-
918
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
wort in den Prozess einklinken. Wenn Sie jdb und das Java-Programm auf zwei verschiedenen Rechnern laufen lassen wollen, müssen Sie zusätzlich beim Start von jdb die Option -host angeben. Die Syntax zum Aufruf des jdb nach Start des Java-Interpreters (in zwei Schritten): java -Xdebug [KlassenName] jdb -host [Hostname] -password [password]
Diese zweite Methode müssen Sie zum Debuggen des Programms verwenden, sofern Sie ein Betriebssystem haben, das die Eingabe nur über den Standard-Input bezieht. In diesem Fall besteht das Problem, dass jede Eingabe, die Sie eintippen, als Eingabe für jdb behandelt wird, wenn Sie jdb bereits gestartet haben. Bei der Benutzung der zweiten Methode können Sie zwei separate Eingabeströme verwenden: einen für Ihr Programm, einen für jdb. jdb zum Debuggen eines Applets starten Wenn Sie ein Applet mit jdb debuggen wollen, gehen Sie analog wie bei der zweiten Methode mit dem Interpreter vor. Sie starten nur in diesem Fall den Appletviewer aus der Befehlszeile mit der Option -debug3. Das Resultat ist jedoch sehr unterschiedlich gegenüber Methode 2. Es wird jdb gestartet, der wiederum den Appletviewer ohne weitere Aufrufe startet, jedoch anhält, bevor eine ausführbare Zeile im Appletviewer ausgeführt wird. Um die Ausführung im Appletviewer zu starten, müssen Sie run eingeben. Jedes Applet der HTML-Datei wird in einem einzelnen Fenster gestartet: Die Syntax zum Debuggen eines Applets: appletviewer -debug [Html-DateiName]
Wenn Sie den Appletviewer erst einmal in der Debug-Einstellung gestartet haben, antwortet jdb mit einigen Zeilen, die in etwa wie bei Methode 1 aussehen. Bis jetzt wurde der Code noch nicht ausgeführt. Deshalb sehen Sie im Ausgabefenster nicht viel mehr als diese Zeilen. Die jdb-Befehlszeile Egal wie Sie eine Debugger-Sitzung starten, in jedem Fall sollten Sie sich jetzt auf der Befehlszeilenebene des Debuggers befinden. Sie erkennen diess an dem jdb-Prompt, das auf Ihre Eingaben wartet – egal ob Sie eine Klasse geladen haben oder nicht. Sie können nur die diversen Kommandos an den Debugger geben, wobei diese zum einen erst einmal erkannt, aber auch in 3
Beachten Sie die Inkonsistenz zwischen -Xdebug beim Interpreter und -debug beim Appletviewer.
Java 2 Kompendium
919
Anhang A der richtigen Reihenfolge angewandt werden müssen. Wie schon angedeutet – der Debugger ist leistungsfähig, aber sehr unkomfortabel. jdb unterstützt folgende Kommandos für das Debuggen (Auflistung in alphabetischer Reihenfolge): Tabelle A.5: Die Kommandos an den Debugger
920
Kommando
Beschreibung
!!
Der zuletzt eingegebene Befehl wird nochmals wiederholt.
?
Erzeugt eine Liste aller gültigen Kommandos für den Debugger.
catch [exception]
Das Kommando bewirkt eine Unterbrechung des Programmablaufs, sobald die angegebene Exception ausgelöst wird. Wenn kein Parameter angegeben wird, erhält man eine Liste der Ausnahmen, die aufgefangen werden.
classes
Gibt die Namen und IDs der Klassen aus, die bereits geladen worden sind.
clear[class:line]
Entfernt Haltepunkte, die bei der angegebenen Klasse an der angegebenen Zeile gesetzt worden sind. Der Aufruf ohne Parameter generiert eine Angabe aller gesetzten Haltepunkte.
cont
Der aktuelle, unterbrochene Thread wird fortgesetzt (continue).
down[n]
Durch das Kommando wird der aktuelle Stack-Bereich eines Threads um n Frames nach unten gesetzt. Ohne Parameter wird der Frame um eine Einheit nach unten bewegt. Dazu gehört das umgekehrte Kommando up.
dump id(s)
Mit dump werden alle Felder (Werte der Variablen) einer Klasse oder der Instanz einer Klasse des angegebenen Objekts bzw. der Objekte angegeben, wenn Sie als id den Namen einer Klasse oder der Instanz einer Klasse angeben. dump gibt die Werte der Variablen der statischen Klasse aus, und dump this oder dump die Werte der Mitgliedsvariablen. Objekte und Klassen können sowohl durch Ihren Namen als auch durch eine achtstellige Hexadezimalzahl (ihrer Identifikator-ID) angegeben werden. Ebenso können Threads durch die Angabe der Kurzbezeichnung t@thread-number angegeben werden.
exit (oder quit)
Beenden des Debuggers
gc
Erzwingt die direkte Ausführung des Garbage Collectors.
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Kommando
Beschreibung
help
Identisch mit dem Kommando ?
ignore <exception>
Unterbindet die Ausführung einer Unterbrechung der angegebenen Ausnahme. Das bedeutet, sie wird aus der Ausnahmenliste des jeweiligen catch-Kommandos entfernt. Beachten Sie, dass der ignore-Befehl die spezifizierte Ausnahme nur im Fall des Debuggers ignoriert; der Java-Interpreter wird Sie weiterhin auffangen. ignore ohne Parameter listet die Ausnahmen in der catch-Liste auf.
list [Zeilennummer]
Zeigt den Quellcode an der angegebenen Zeilenummer an. Wenn keine Zeilennummer angegeben wird, wird die Zeile angegeben, die im aktuellen Frame des des aktuellen Threads steht. Um Quellcode-Zeilen aufzulisten, muss das Programm zunächst an einem Haltepunkt angehalten werden oder Sie müssen bereits einen Thread spezifiziert haben und diesen Thread dann unterbrechen. Andernfalls antwortet jdb mit einer Fehlermeldung (No thread specified or Current thread isn't suspended.)
Anhang A Tabelle A.5: Die Kommandos an den Debugger (Forts.)
Wenn ein Thread unterbrochen wurde, anstatt an einem Haltepunkt angehalten worden zu sein, müssen Sie den Zusammenhang mit dem Thread über den Thread-Befehl spezifisch festlegen. Sie müssen sich dann eventuell im Stack mit dem up-Befehl nach oben bewegen, um den Stack-Kontext in dem Code Ihres Programms festzulegen. Wenn sich die Quelle zu den Klassen, die Sie bearbeiten wollen, nicht im eingestellten Klassenpfad befindet (oder in dem Klassenpfad, der durch den Befehlszeilen-Parameter -classpath festgelegt wurde), kann jdb die Quelle nicht auflisten. Allerdings gibt es für diesen Fall den Befehl use, um einen Dateipfad zur Quelle festzulegen. load [Klassenname]
Die mit Klassenname angegebene Klasse wird in den Debugger geladen.
locals
locals gibt die lokalen Variablen des aktuellen Stack-
Bereichs aus. Dafür muss allerdings zwingend der Bytecode mit der Compileroption -g erzeugt worden sein. memory
memory zeigt den Speicherbedarf des aktuellen Pro-
gramms bis zum derzeitigen Zeitpunkt an. Sowohl der freie als auch der gesamte verfügbare Speicher wird angezeigt.
Java 2 Kompendium
921
Anhang A Tabelle A.5: Die Kommandos an den Debugger (Forts.)
Kommando
Beschreibung
methods
Durch diesen Befehl werden alle Methoden der angegebenen Klasse angezeigt.
print id(s)
Der Debugger zeigt mit diesem Befehl die Werte für eine angegebene Klasse, ein Objekt, ein Feld oder eine lokale Variable an. id kann sowohl ein Name als auch ein Identifikator – die Objekt-ID – sein. Die Objekt-ID einer Klasse wird beim Laden derselben angezeigt oder kann mit dem Kommando classes nachträglich abgefragt werden. Durch die Angabe der speziellen Syntax t@thread-number ist es möglich, sich auf spezielle Threads zu beziehen. Das Kommando print verwendet zur Ausgabe die Methode toString().
resume [thread1 ...threadN]
Veranlasst den Debugger, die angehaltenen Threads wieder fortzuführen. Wenn keine Parameter angegeben worden sind, werden alle mit dem Kommando suspend angehaltenen Threads wieder fortgeführt.
run [Klasse] [arg1...argN]
Dieses Kommando startet die Ausführung der angegebenen Klasse, d.h., es führt die main()-Methode der angegebenen Klasse aus. Die optionalen Parameter arg1 bis argN werden gegebenenfalls übergeben. Falls keine Argumente angegeben worden sind, wird die Klasse ausgeführt, die beim Start von dem Debugger angegeben worden ist.
step
Führt die aktuelle Zeile des aktuellen Threads aus und stoppt im Anschluss daran.
stop [at Klasse:Zeile] Setzt einen Haltepunkt in der angegebenen Zeile der
Klasse. Ohne Angabe der Argumente werden alle gesetzten Haltepunkte ausgegeben. stop [in Klasse:Zeile] Setzt einen Haltepunkt am Anfang der angegebenen
Methode der Klasse. Ohne Angabe der Argumente werden alle gesetzten Haltepunkte ausgegeben.
922
suspend [thread1...threadN]
Die angegebenen Threads werden unterbrochen. Falls kein Argument angegeben worden ist, werden alle aktiven Threads unterbrochen. Mit resume können die Zustände von Threads wieder geändert und die Threads wieder gestartet werden.
thread [thread]
Nach Aufruf des angegebenen Threads in diesem Kommando wird dieser zum aktuellen Thread.
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Kommando
Beschreibung
threadgroup [Name der threadgroup]
Wenn Sie sich einen Thread außerhalb der voreingestellten Thread-Gruppe ansehen wollen, müssen Sie zuerst die entsprechende Thread-Gruppe über den threadgroup-Befehl spezifizieren. Nach Aufruf dieses Kommandos ist die angegebene Thread-Gruppe die aktuelle Thread-Gruppe, und Sie können sich einen einzelnen Thread herauspicken.
threadgroups
Zeigt alle gerade aktiven Threadgruppen innerhalb eines Programms an. Sie werden mit aufsteigenden Nummern davor aufgelistet, gefolgt vom Klassennamen, wiederum gefolgt vom Handle der ThreadGruppe und dem Namen der Thread-Gruppe. Nur die Thread-Gruppen von Threads, die gestartet wurden, werden angezeigt.
threads [threadgroup1... threadgroupN]
Listet alle Threads in der angegebenen Gruppe auf. Wenn keine Gruppe angegeben worden ist, werden die Threads der aktuellen Gruppe angegeben. Threads werden mit vorangestellten Indexnummern aufgelistet. Der letzte Bestandteil einer Threadzeile ist der Zustand des Threads. Nur Threads, die bereits gestartet wurden, werden angezeigt.
up[n]
Durch das Kommando wird der aktuelle Stack-Bereich eines Threads um n Frames nach oben gesetzt. Ohne Parameter wird der Frame um eine Einheit nach oben bewegt. Dazu gehört das umgekehrte Kommando down.
use [Sourcefile Pfad]
Setzt den Pfad, den jdb verwenden soll, um nach eventuell benötigten Quellcodes zu suchen. Der Befehl use, ohne irgendwelche Parameter, veranlasst jdb dazu, den Pfad aufzulisten, den er gerade zum Finden des Quellcodes verwendet. use, gefolgt von einem Datei-Pfad, ändert den Pfad der Quelldatei auf den neu angegebenen Pfad. Die bei den anderen Tools verwendete Option -classpath hat eine ähnliche Bedeutung. jdb folgt dem spezifizierten Pfad, um den Quellcode zu finden.
where [thread] [all]
Bewirkt die Ausgabe des Stacks für den angegebenen Thread. Falls kein Thread angegeben worden ist, wird der Stack des aktuellen Threads angezeigt. Durch Angabe des Arguments all können alle Stacks angezeigt werden.
Java 2 Kompendium
Anhang A Tabelle A.5: Die Kommandos an den Debugger (Forts.)
923
Anhang A Ab der Version 1.2 unterstützt die Java Virtual Machine Low-Level-Services für das Debuggen. Die API für diese Low-Level-Services ist das Java Virtual Machine Debugger Interface (JVMDI). Deren detaillierte Behandlung sprengt jedoch den Rahmen des Buchs. In der JDK-Dokumentation finden Sie mehr dazu. jdb reagierte in der Version 1.2 (oldjdb tut es immer noch) ganz witzig auf einen Fehler bei der Befehlseingabe, wenn er einen Befehl nicht kennt: Auf > xit (Buchstabe vergessen) kommt folgende Antwort von jdb: huh? Try help... > Das Java Archive Tool (jar) Bereits ab der JDK-Version 1.1.1 können Java-Programme JAR-Dateien (Java-Archive mit der Erweiterung .jar) nutzen. Statt vieler einzelner und unkomprimierter Dateien kann man ein gepacktes Archiv verwenden und auch über Netze übertragen. Der Vorteil dieses Konzepts liegt bei Netzwerkaktionen darin. dass die Applikation in einer einzigen Transaktion übertragen wird und nicht in vielen einzelnen Übertragungsschritten. Außerdem wird die Datenmenge ziemlich komprimiert. JAR-Archive basieren auf der ZIP-Technologie und dem ZIP-Format. Zu der Theorie der Datenkomprimierung finden Sie einen kleinen Exkurs im Anhang C. Zum Erstellen der Java-Archive wird das Java Archive Tool jar genutzt. Man kann beliebig viele Java-Klassen und andere Ressourcen zu einer einzelnen JAR-Datei damit zusammenfassen. Die Syntax für jar: jar [Optionen] [manifest] [JAR-Datei] [Eingabedatei(en)]
Die Syntax besteht aus vier Bestandteilen nach dem Programmaufruf: Den Optionen. Der mit manifest bezeichneten Teil der Syntax gibt eine Datei an, die sämtliche Meta-Informationen über das Archiv enthält. Eine ManifestDatei wird immer automatisch vom jar-Tool generiert und ist immer der erste Eintrag in der .jar-Datei. Sie müssen diese Angabe nur dann machen, wenn Sie eine vom Defaultwert abweichende Datei als MetaInformationsdatei des Archives verwenden wollen. Andernfalls wird diese Meta-Informationsdatei mit Namen META-INF/MANIFEST.MF erstellt.
924
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
JAR-Datei ist der Name des zu erstellenden oder zu dekomprimierenden Java-Archivs. Eingabedatei(en) bezeichnet die Datei(en), die komprimiert werden sollen. Dabei kann mit Wildcards gearbeitet werden (z.B. *.class für die Komprimierung alle Klassendateien im Verzeichnis in der angegebenen JAR-Datei). Die Dateien müssen beim Entkomprimieren nicht unbedingt angegeben werden.
Das jar-Tool ist in der Syntax den weit verbreiteten DOS-Komprimierungsprogrammen lha oder arj sehr ähnlich. Es gibt aber einen wichtigen Unterschied, denn die nachfolgenden Optionen sind immer gekoppelt. Dies bedeutet Folgendes: Eine der Optionen -{ctx} muss angegeben werden und wird dann meistens mit der entsprechenden weiteren Option aus [vfm0M] kombiniert. Dabei können zwar die Optionen aus den beiden Bereichen in der Reihenfolge vertauscht werden; sie dürfen aber nicht alleine verwendet werden, sondern nur in Verbindung mit zwei Optionen aus dem Trippel -{ctx}. Beispiele: jar -fc test.jar *.class jar -xf test.jar *.class
Dies ist etwas gewöhnungsbedürftig, jedoch wenn Sie sich nicht daran halten, kann es sogar passieren, dass eine Fehlermeldung (im günstigsten Fall) das Resultat ist oder sich das Tool sogar aufhängt (scheinbar). Wenn das Tool auf Befehlszeilenebene wartet, probieren Sie einmal die Tastenkombination STRG+Pause aus. Auf dem Standard-Ausgabegerät werden die Aktionen seitenweise ausgegeben. Optionen
Beschreibung
-c
Diese Option generiert ein neues oder leeres Archiv auf dem Standard-Ausgabegerät. Dies bedeutet, wenn Sie die Option alleine verwenden, füllt sich in der Regel der Bildschirm mit Sonderzeichen. Diese Option macht nur Sinn in Kombination mit einer anderen Option. Das folgende Kommando jar -fc test.jar *.class erstellt aus sämtlichen in dem Verzeichnis vorhandenen Dateien mit der Erweiterung .class ein JARArchiv test.jar.
-t
Listet eine Tabelle des Inhalts einer Datei auf dem StandardAusgabegerät auf. Allerdings macht diese Option nur Sinn in Kombination mit einer anderen Option, etwa jar -tf test.jar
Tabelle A.6: Die jar-Optionen
*.class
Java 2 Kompendium
925
Anhang A Tabelle A.6: Die jar-Optionen (Forts.)
Optionen
Beschreibung
-x [Datei]
Extrahiert alle Files oder die namentlich angegeben Dateien. Auch hier gilt, dass in Verbindung mit der weiteren Option -f die Hauptanwendung zu sehen ist.
-f
Nur als zweites Argument für die Aktionen Erstellen, Extrahieren oder Inhaltsangabe zu verwenden. Die Option spezifiziert die zu bearbeitende JAR-Datei.
-v
Generiert eine Statusausgabe auf das Standardausgabegerät. Die Option macht nur Sinn in Verbindung mit laufenden Aktionen, die mit anderen Optionen ausgelöst werden.
-m
Integriert Manifest-Informationen in die angegebene ManifestDatei.
-0
Nur Zusammenfassung von Dateien. Es wird keine ZIP-Kompression verwendet. Ein solches JAR-Archiv kann nicht im Suchpfad von Tools spezifiziert werden.
-M
Generiert keine Manifest-Datei.
-u
Update einer existierenden JAR-Datei, indem Dateien hinzugefügt werden. Beispiel: jar -uf mein.jar meineKlasse.class
-C
Wechselt Verzeichnisse während der Ausführung eines jarKommandos.
Wenn in der Angabe der Dateien ein Verzeichnis auftaucht, wird dieses Verzeichnis rekursiv verarbeitet.
Dieses Tool unterscheidet bei den Optionen zwischen Groß- und Kleinschreibung. Das Utility für jar-Konflikte – extcheck Zu den Basis-Tools zählt auch das Programm extcheck, ein Diagnose-Tool für JAR-File-Versionskonflikte. Damit können solche Probleme zwischen jeder JAR-Datei und den JAR-Dateien aufgedeckt werden, die als Erweiterung der JDK-Software installiert sind. Die Syntax für extcheck: extcheck [ -verbose ] targetfile.jar
Die Option -verbose listet alle JAR-Dateien auf, die überprüft wurden.
926
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
A.1.2
Anhang A
Internationalization Tools
Diese Art von Programmen umfasst nur das Programm native2ascii, das Text in Unicode nach der Norm Latin-1 konvertiert. Der Java-Compiler und andere Java-Tools können nur mit in Latin-1 und/oder Unicode-verschlüsselten (\udddd-Notation) Dateien arbeiten. Der Native-To-ASCII Converter konvertiert eine native-kodiertes Datei (nicht-Latin-1 und nicht-Unicode) in eine reine ASCII-Datei, das die \udddd-Unicode-Notation beinhaltet. Die umgekehrte Richtung funktioniert genauso. Syntax: native2ascii [Optionen] [inputfile [outputfile]]
Wenn die Output-Datei weggelassen wird, wird die Standard-Ausgabe verwendet. Wenn die Input-Datei weggelassen wird, wird die Standard-Eingabe verwendet. Option
Beschreibung
-reverse
Diese Option veranlassst native2ascii, Unicodeoder Latin-1-kodierten Text in native-kodierten Text zu übersetzen.
-encoding [Verschlüssel_name]
Spezifiziert den Verschlüsselungsnamen, der bei der Konvertierung verwendet wird. Dieser Verschlüssel_name-String muss als korrektes Argument der Klasse CharacterEncoding definiert sein.
Tabelle A.7: Die native2ascii Optionen
Hier ist eine kleine Liste mit möglichen Verschlüsselungsnamen: 8859_1 ISO Latin-1 8859_2 ISO Latin-2 8859_3 ISO Latin-3 8859_5 ISO Latin/Cyrillic 8859_6 ISO Latin/Arabic 8859_7 ISO Latin/Greek 8859_8 ISO Latin/Hebrew 8859_9 ISO Latin-5 Cp1250 Windows Eastern Europe / Latin-2 Cp1251 Windows Cyrillic Cp1252 Windows Western Europe / Latin-1 Cp1253 Windows Greek Cp1254 Windows Turkish Cp1255 Windows Hebrew Cp1256 Windows Arabic Cp1257 Windows Baltic Cp1258 Windows Vietnamese Cp437 PC Original
Java 2 Kompendium
927
Anhang A Cp737 PC Greek Cp775 PC Baltic Cp850 PC Latin-1 Cp852 PC Latin-2 Cp855 PC Cyrillic Cp857 PC Turkish Cp860 PC Portuguese Cp861 PC Icelandic Cp862 PC Hebrew Cp863 PC Canadian French Cp864 PC Arabic Cp865 PC Nordic Cp866 PC Russian Cp869 PC Modern Greek Cp874 Windows Thai EUCJIS Japanese EUC JIS JIS MacArabic Macintosh Arabic MacCentralEurope Macintosh Latin-2 MacCroatian Macintosh Croation MacCyrillic Macintosh Cyrillic MacDingbat Macintosh Dingbat MacGreek Macintosh Greek MacHebrew Macintosh Hebrew MacIceland Macintosh Iceland MacRoman Macintosh Roman MacRomania Macintosh Romania MacSymbol Macintosh Symbol MacThai Macintosh Thai MacTurkish Macintosh Turkish MacUkraine Macintosh Ukraine SJIS PC and Windows Japanese UTF8 Standard UTF-8
A.1.3
Security Tools
Das JDK beinhaltet diverse Sicherheitsprogramme. Diese Programme sind zum Setzen und Verwalten von Sicherheitspolicen auf Ihrem System gedacht. Sie können damit Applikationen entwickeln, die mit anderen Sicherheitspolicen zusammenarbeiten. keytool dient zum Schlüssel- und Zertifikat-Management. Es wird eine Datenbank mit privaten Schlüsseln und ihren zugehörigen X.509-Zertifikaten sowie den Zertifikaten von vertrauenswürdigen Entities verwaltet. Dieses Tool basiert auf dem DSA-Algorithmus mit der SHA-1 Signatur.
928
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
jarsigner generiert oder verifiziert eine digitale Signatur für eine JAR-
Datei. policytool ist ein GUI-Tool (d.h. mit grafischer Oberfläche) für das Management von Policy-Dateien.
Das digitale Signierungs-Tool javakey verwaltet Datenbankentitäten, inklusive ihrer Schlüssel, Zertifikate und ihren Vertrauensebenen. Allerdings nach dem alten Java-Sicherheitsmodell. Dieses Tool ist als eine der bedeutendsten Neuerungen in der Version 1.2 durch die Programme keytool und jarsigner sowie policytool ersetzt worden. Mit dem Thema Verschlüsselung und Datensicherheit müssen wir ein Thema ansprechen, in dem Sun bei der Version 1.1 einen kleinen Flop landeten. Zwar ist Java auch hier mittlerweile erwachsen geworden und in der Version 1.1 kam mit javakey ein wichtiges Tool zum JDK. Dieses Programm hat sich allerdings als teilweise nicht voll befriedigend herausgestellt und ist als eine der bedeutendsten Neuerungen in der Version 1.2 durch die Programme keytool und jarsigner sowie policytool ersetzt worden. Wir wollen für die Besprechung der Hintergründe der Java-SicherheitsTools dennoch hauptsächlich javakey verwenden. Zum einen können wesentliche Hintergrundinformationen über Verschlüsselung und Datensicherheit daran recht gut erklärt werden und die Anwendung der neuen Programme ist weigehend analog. Zum anderen werden wohl noch einige Leser weiter mit javakey arbeiten wollen! Besonders diejenigen Anwender, die bereits mit javakey eine Datenbank an Schlüsseln aufgebaut haben, stehen sonst vor einem gewissen Problem. Die beiden Programme keytool und jarsigner ersetzen javakey zwar vollständig und bieten eine Fülle neuer Features (etwa Schutz der Datenbank und der privaten Schlüssel mit Passwörtern). Die beiden Programme sind jedoch ausdrücklich nicht abwärtskompatibel zu dem Keystore- und Datenbankformat, das von javakey in dem JDK 1.1 verwendet wurde. javakey javakey ist ein kommandozeilenorientiertes Sun-Sicherheits-Tool, dessen primäre Anwendung das Generieren von digitalen Signaturen für Archive ist. Eine Signatur verifiziert, dass eine Datei von einer bekannten Quelle kommt. Um eine Signatur für eine Datei zu generieren, muss zuerst ein öffentlicher Schlüssel und dann ein privater Schlüssel generiert werden, mit dem der öffentliche Schlüssel dann wieder dekodiert werden kann. javakey erstellt solche Schlüssel und eine Datenbank zur Verwaltung der Schlüssel und der zugeordneten Zertifikate, die den Status der Vertrauenswürdigkeit dokumentieren.
Java 2 Kompendium
929
Anhang A Die Syntax für javakey: javakey [Optionen]
Zu den Hintergründen und der Theorie der Datenverschlüsselung finden Sie einen Exkurs im Anhang. Sowohl javakey als auch die neueren Tools verwenden defaultmäß ig eine Verschlüsselung nach dem DSA-Standard (Digital Signature Algorithm) bzw. darauf aufbauenden Verfahren. Es gibt zwei Arten von Einträgen in der Datenbank, die von javakey verwaltet werden: Identities Signers Unter Identities (Identitäten) kann man sich jede Form juristischer Personen aus der realen Welt (Personen, Firmen, Organisationen) vorstellen. Diese haben von Ihnen einen öffentlichen Schlüssel bekommen. Weiter kann eine Verbindung zwischen dem öffentlichen Schlüssel einer Identity und einem oder mehreren Zertifikaten bestehen. Ein Zertifikat ist eine digitale Unterschrift dieser verwalteten juristischen Personen. Sie überprüft, von wem das mit dem öffentlichen Schlüssel kodierte Datenpaket stammt. Wenn also mehrere juristische Personen denselben öffentlichen Schlüssel zum Kodieren verwenden, können Sie durch die digitale Unterschrift eine eindeutige Zuordnung vornehmen. Signers sind juristische Personen, die zu einem öffentlichen Schlüssel auch einen passenden privaten Schlüssel haben. Um ein Datenpaket eindeutig zu signieren, müssen ein öffentlicher Schlüssel und ein passender privater Schlüssel vorhanden sein sowie ein Zertifikat zur Sicherstellung der Authentizität des öffentlichen Schlüssels. Wenn Ihnen jemand also ein Datenpaket zuschicken will, und Sie sollen es als vertrauenswürdig einstufen, dann läuft der Vorgang bei der Verwendung von einem Programm wie javakey normalerweise folgendermaßen ab.
930
1.
Mit dem Sicherheitsprogramm erstellen Sie einen öffentlichen Schlüssel und einen dazu passenden privaten Schlüssel. Beide werden vom Sicherheitsprogramm in einer Datenbank verwaltet.
2.
Das Objekt Ihrer Wahl aus der realen Welt (Personen, Firmen, Organisationen) bekommt den öffentlichen Schlüssel.
3.
Ein Zertifikat mit der speziellen digitalen Unterschrift für die jeweilige juristische Person wird ausgetauscht. Diese digitale Unterschrift kann von Ihnen mit dem Sicherheitsprogramm erstellt und dem Partner zugeschickt werden, sie kann aber auch vom Partner erstellt und Ihnen
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
zugeschickt werden. In beiden Fällen tragen Sie mit dem Sicherheitsprogramm diese digitale Unterschrift in der Datenbank bei dem passenden Schlüsselpaar ein. 4.
Wenn Sie nun ein Datenpaket erhalten, können Sie den Absender auf Grund der digitalen Unterschrift identifizieren und nur Sie sind durch Ihren privaten Schlüssel in der Lage, das Datenpaket zu dekodieren.
Sie können in javakey wie in den meisten so arbeitenden Sicherheitsprogrammen sowohl Schlüssel und Zertifikate neu erstellen als auch bestehende Schlüssel importieren. Jede Datenbank benötigt zur Verwaltung einen internen Zugriffsschlüssel für die darin enthaltenen Datensätze. Alle Objekte (Identities und Signers) haben in der lokalen Datenbank einen von javakey verwalteten Username. Dieser Username ist der interne und eindeutige Schlüssel zum Verwalten der Datenbank. Das Hinzufügen eines Eintrags in die Datenbank mit der Option -c (create identity) oder -cs (create signer) ist eine Verwaltungsaktion, wo ein solcher Username vergeben wird. Alle javakey-Kommandos müssen anschließend diesen eindeutigen Username zur Referenz auf ein Objekt verwenden. Lassen Sie uns ein Beispiel – wieder unter der Verwendung von javakey – durchsprechen: Der Befehl javakey -cs safetyfirst true generiert einen als vertrauenswürdig eingestuften Signer und weist ihm den Username safetyfirst zu (Ausgabe: Created identity [Signer]safetyfirst[identitydb.obj][trusted]). Anschließend werden mit javakey ein öffentlicher und ein privater Schlüssel generiert. Für unser Beispiel soll ein Schlüssel mit 512 Bit nach DSA für diesen Signer generiert werden: javakey -gk safetyfirst DSA 512 javakey erlaubt es, bestimmte juristische Personen als vertrauenswürdig einzustufen. Der Appletviewer gestattete in dem ehemaligen Sicherheitskonzept jedem aus dem Netz geladenen Applet in JAR-Dateien, die als vertrauenswürdig eingestuft und mit diesem Tool entsprechend signiert wurden, mit denselben Rechten auf dem lokalen Rechner zu laufen wie eine lokale Applikation. Dies hatte extrem weitreichende Konsequenzen, denn ein solches Applet ist nicht mehr Bestandteil des »Laufstalls«, in den das Java Sicherheitsmodell Applets normalerweise zwingt. Wenn Sie also eine Organisation als prinzipiell vertrauenswürdig einstufen wollten, mussten Sie sich schon sehr sicher sein. Es gab übrigens bis zu den 1.1.x-Versionen nur die Möglichkeit »vertrauenswürdig« oder »nicht vertrauenswürdig«. Eine dif-
Java 2 Kompendium
931
Anhang A ferenziertere Abstufung war nicht möglich. Mittlerweile wurde eine solche weitergehende Differenzierung realisiert. Defaultwert ist »nicht vertrauenswürdig«. Wenn Sie also Einträge in der Datenbank vornehmen, können Sie folgende Vertrauensstufen setzen: javakey -cs safetyfirst true javakey -cs microsoft false javakey -cs cia
Fall eins steht für »vertrauenswürdig«, die anderen beiden für »nicht vertrauenswürdig«. Die Einträge können später natürlich wieder verändert werden. Klären wir nun, was Zertifikate sind. Mit den meisten Sicherheitsprogrammen sind Sie in der Lage, Zertifikate zu importieren, zu generieren, anzeigen und zu speichern. Ein Zertifikat ist eine digitale Unterschrift einer juristischen Person. Vereinfacht gesagt drückt ein Zertifikat nur aus, dass der öffentliche Schlüssel von einer anderen juristischen Person einen abweichenden Wert hat. javakey verwendet X.509-Zertifikate. Wenn Sie mit javakey ein Zertifikat generieren wollen, müssen Sie als Erstes eine Datei generieren, in die folgende Informationen gehören: Informationen über den Unterzeichner Informationen über die juristische Person selbst Informationen über das Zertifikat selbst Optional der Name des verwendeten Verschlüsselungsalgorithmus (falls Sie nicht DSA verwenden) Der Name der Datei, die eine Kopie des Zertifikats enthält Um ein Zertifikat zu generieren und eine Datei zu spezifizieren, verwenden Sie die Option -gc. Beispiel: javakey -gc bembelmaniaCertDirFile javakey wird ein Zertifikat generieren, indem es die Informationen verwendet, die in der angegebenen Datei abgelegt sind. Zusätzlich werden Informationen verwendet, die in der Datenbank vorhanden sind (öffentlicher und privater Schlüssel usw.).
Zum Anzeigen von Zertifikatinformationen verwenden Sie die Option -dc. Beispiel: javakey -dc certfile.cer
932
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
Dies zeigt die Informationen über das Zertifikat an, die in der Datei certfile.cer abgelegt sind.
Zum Importieren von Zertifikaten verwenden Sie die Option -ic. Beispiel: javakey -ic joe jcertfile.cer Der Befehl importiert das Zertifikat in die Datei jcertfile.cer und ordnet es dem Username joe zu. Zum Exportieren von Zertifikaten verwenden Sie die Option -ec. Beispiel: javakey -ec jane 2 janecertfile.cer Der Befehl exportiert das zweite Zertifikat der mit dem Username jane bezeichneten juristischen Person in die Datei janecertfile.cer. Die Nummer des Zertifikats muss dieselbe Nummer sein, die bei der Generierung oder dem Import zugewiesen wurde. javakey kann JAR-Dateien auf jeden Fall mit DSA (Digital Signature Algorithm) signieren und verifizieren. In einigen Fällen funktioniert genauso der MD5/RSA-Algorithmus, was vom Typ der verwendeten Schlüssel des Signers und der Unterstützung durch den Provider abhängt.
Signieren einer JAR-Datei generiert für den angegebenen Signer eine digitale Unterschrift und schließt diese in die angegebene JAR-Datei ein. Dazu muss der Signer in der von javakey verwalteten Datenbank mit seinem Schlüsselpaar und einen X.509-Zertifikat vorhanden sein. Wie die Generierung eines Zertifikates basiert die Generierung einer digitalen Unterschrift auf den Anweisungen aus einer Datei, die das Profil eines Signers enthält. Wenn die JAR-Datei und die Anweisungsdatei generiert wurden, kann der javakeyBefehl zum signieren der JAR-Datei angewendet werden: javakey -gs directivefile jarfile directivefile ist der Name (und Pfad) der Anweisungsdatei, und jarfile ist der Name (und Pfad) der JAR-Datei.
Die Ausgabe dieses Befehls ist eine signierte JAR-Datei, deren Name von dem Wert in der Eigenschaft out.file spezifiziert wird, sofern dort ein Wert steht. Andernfalls wird der Name der signierten JAR-Datei identisch sein mit der Orginaldatei, aber mit der Erweiterung .sig. Auf die konkrete Auflistung aller Optionen von javakey wollen wir verzichten – immerhin ist das Tool nur noch für abwärtskompatible Arbeit sinnvoll. In der Dokumentation von Sun finden Sie aber mehr dazu. Beachten
Java 2 Kompendium
933
Anhang A Sie jedoch, dass Sie unter Umständen die Dokumentation eines 1.1.x-JDK laden müssen. keytool und jarsigner Wie bereits angedeutet, hat sich javakey nicht sonderlich bewährt und wurde deshalb durch einen Satz von Tools ausgetauscht. javakey dient indes immer noch als Basis für diese Tools. Viele Funktionalitäten und die Bedienung sind daran angelehnt oder gar identisch. Andere dagegen sind komplett neu. Zum Schlüssel- und Zertifikat-Management dient nun keytool. Wie bei javakey wird eine Datenbank (keystore) mit privaten Schlüsseln und ihren zugehörigen X.509-Zertifikaten sowie den Zertifikaten von vertrauenswürdigen Entities verwaltet. Auch dieses Tool basiert auf dem DSA-Algorithmus mit der SHA-1-Signatur. Die Schlüsselgrö ß e muss im Bereich zwischen 512 und 1024 Bits liegen, und muss ein Vielfaches von 64 sein. Die Defaultschlüsselgrö ß e ist 1024 Bits. Das jarsigner-Tool benutzt dieses Informationen, um eine digitale Signatur für eine JAR-datei zu generieren oder verifizieren. jarsigner verifiziert die digitale Signatur von einer JAR-Datei, indem das mitgeschickte Zertifikat dahingehend überprüft wird, ob der öffentliche Schlüssel vertrauenswürdig ist oder nicht (beispielsweise eine Übereinstimmung mit einem Eintrag im keystore). Das jarsigner-Tool unterstützt den DSA-Algorithmus und das RSA-Verfahren mit dem MD5-Algorithmus. Um es noch einmal zu betonen: Die beiden Programme keytool und jarsigner ersetzen javakey zwar vollständig und bieten eine Fülle neuer Features. Die beiden Programme sind jedoch ausdrücklich nicht abwärtskompatibel zu dem Keystore- und Datenbankformat, das von javakey in dem JDK 1.1 verwendet wurde. Wir werden Befehle und Optionen von keytool nur skizzieren. Mehr Informationen dazu finden Sie u.a. in der Dokumentation des JDK. Allen Befehlen und Optionen geht ein Minuszeichen voran. Die Optionen für die Befehle werden in jedem Befehl unterstützt. Klammern werden unterstützt. Klammern um eine Option bedeuten, dass der Defaultwert genutzt wird, wenn die Option in der Kommandozeile nicht spezifiziert wird. Klammern um eine Option bedeuten ebenfalls, dass der Anwender Werte eingeben kann, wenn die Option in der Kommandozeile nicht spezifiziert wird.
934
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
Angaben in geschweiften Klammer bedeuten, dass der dort stehende Wert durch einen erlaubten Wert zu ersetzen ist. Beispiel: keytool -printcert {-file cert_file} {-v} Um ein Kommando einzugeben, muss cert_file mit dem aktuellen
Dateinamen ersetzt werden, etwa so: keytool -printcert -file VScert.cer
Optionswerte müssen mit einem Leerzeichen getrennt werden. Das Kommando -list ist die Defaulteinstellung und äquivalent zu dem Aufruf keytool. Wenn Sie keytool -list eingeben, erhalten Sie eine Auflistung der keytool-Befehle, der Optionen und der Syntax, auf die auch hier weiter verwiesen werden soll. Die Befehle und Optionen von jarsigner skizzieren wir ebenfalls nur grob. Mehr Informationen dazu finden Sie u.a. in der Dokumentation des JDK. Sie müssen mit dem Befehlsaufruf die Datei angeben, die Sie signieren oder verifizieren wollen. Wenn Sie jarsigner benutzen, um eine JARDatei zu signieren, wird die signierte JAR-Datei exakt identisch zu der Input-JAR-Datei sein, es sei denn, in dem META-INF-Directory sind zwei einander zugeordnete Dateien angegeben. Auch dazu finden Sie Informationen in der Dokumentation. Auch für die jarsigner-Optionen gilt, dass alle Optionen mit einem Minuszeichen beginnen. Die Optionen werden in den meisten Befehlen unterstützt. Angaben in geschweiften Klammer bedeuten, dass der dort stehende Wert durch einen erlaubten Wert zu ersetzen ist. Ein Beispiel soll das Signieren einer JAR-Datei demonstrieren. Die JARDatei heißt im Beispiel bundle.jar. Wir verwenden einen privaten Schlüssel mit dem Keystore-Aliasnamen (siehe dazu die Dokumentation) safety in dem Keystore mykeystore im daten-Directory. Das Keystore-Password soll mykeypass sein und das Passwort für den privaten Schlüssel abc. Mit diesen Voraussetzungen können Sie eine JAR-DAtei signieren und die signierte JAR-Datei sbundle.jar nennen: jarsigner -keystore "\daten\mykeystore" -storepass mykeypass -keypass abc signedjar sbundle.jar bundle.jar safety
Das Policytool Das Policytool ist eine grafische Benutzerschnittstelle (neben dem Appletviewer das einzige Programm des JDK mit GUI), die den Anwender beim Spezifizieren, Generieren, Editieren, Exportieren oder Importieren von einer Sicherheitspolice unterstützt. Damit kann unter Java auf fremde Hosts zugegriffen werden, ohne das Java-Sicherheitsmodell zu verlassen. Das Tool Java 2 Kompendium
935
Anhang A selbst ist weitgehend selbsterklärend und wird von der Kommandozeile mit policytool aufgerufen.
A.1.4
Java IDL- und RMI-Tools
Diese Programme dienen zum Generieren von Applikationen, die über das Web oder andere Netzwerken interagieren. Das bedeutet, es geht um die Unterstützung von Remote-Prozessen. Dabei kann entweder auf IDL und CORBA oder das RMI-Konzept zurückgegriffen werden. Im Wesentlichen geht es dabei um die Angabe einer gemeinsamen Schnittstelle für den Server und die Clients. Diese Schnittstelle wird vom Server implementiert, der sich bei einem Nameserver anmeldet. Von diesem können die Clients eine Referenz auf den Server erfragen, um ihn anschließend zu benutzen. Ziemlich einfach ist die Implementierung eines Clients: Der einzige Unterschied zu einem Client, der keine verteilten Objekte nutzt, ist das Holen einer Referenz auf den Server vom Nameserver. Das unter dem JDK 1.2 neu eingeführte Programm tnameserv unterstützt den Zugriff auf die benannten Services4. Neu in der Java-2-Plattform ist mit dem JDK 1.2 das Tool idltojava eingeführt worden. Dieses Tool generiert .java-Dateien, die ein OMG IDL-Interface mappen. Damit können in Java geschriebene Applikationen CORBA-Funktionalität nutzen. Dieses Tool war ursprünglich nicht direkt Bestandteil des JDK, sondern konnte von der Java IDLWebseite geladen werden. Im JDK ist ein solches Tool nun enthalten. Es heißt zwar idlj, hat jedoch die gleiche Funktionalität – es generiert aus der IDL-Metasprache Java-Schablonen für CORBA. Der Java RMI Stub Converter (rmic) generiert Stub-Dateien und Gerüststrukturen für so genannte Remote-Objekte (Remote Objects). Syntax: rmic [ Optionen ] package-qualified-class-name(s)
Das generierte Remote-Objekt ist ein Objekt, das die Schnittstelle java.rmi.Remote enthält. Die Stub-Dateien und Gerüststrukturen werden von den Namen der kompilierten Klassen, die Remote-Object-Implementationen enthalten, abgeleitet. Die im rmic-Kommando angegebenen Klassen müssen Klassen sein, die erfolgreich mit dem Java-Compiler javac kompiliert wurden und sie müssen vollständig qualifizierte Angabe bzgl. der Packages enthalten.
4
936
Die meisten der hier erklären Tools werden im Kapitel über die erweiterten Java-Techniken bei der Behandlung von CORBA verwendet.
Java 2 Kompendium
Ergänzungen zu den JDK-Tools
Anhang A
Beispiel: Das Kommando rmic hello.HelloImpl
generiert die Dateien HelloImpl_Skel.class und HelloImpl_Stub.class. Das Tool rmiregistry (Java Remote Object Registry) ist dafür da, auf dem angegebenen Port eines Hosts eine so genannte Remote Object Registry zu generieren und dann zu starten. Wie auch rmic – der Java RMI Stub Compiler – dient rmiregistry zur programmiertechnischen Umsetzung des RMI-Konzepts für die verteilte Programmierung. Das Tool rmid (Java RMI Activation System Daemon) ist in das RMIKonzept integriert und startet den so genannten Activation System Daemon, mit dessen Hilfe Objekte in einer JVM registriert und aktiviert werden können. Das dahinter liegende Konzept wird ActivationFramework genannt und erlaubt es beispielsweise, eine GIF-Datei als solche zu erkennen und ein passendes Objekt zu deren Bearbeitung zur Verfügung zu stellen. Syntax: rmid [-port port] [-log dir]
Für den Bereich der verteilten Programmierung (RMI) benötigt Java das Konzept der so genannten Object Serialization, auf dem das Tool serialver (Serial Version Command) aufbaut. Es ermöglicht das Abspeichern der Inhalte eines Objekts in einen Stream. Hauptanwendung hierfür ist das Versenden von Objekten über das Netzwerk im Zusammenhang mit dem RMI. Das Serialization-API wird benutzt, um die Daten eines Objekts in einen Datenstrom zu packen und anschließend, an anderer Stelle, wieder auszupacken. Dies kann aber auch im Prinzip eine beliebige Datei sein. Ein Objekt kann in einem Stream zwischengespeichert und zu einem späteren Zeitpunkt daraus wieder aufgebaut werden. Die Lebensdauer eines Objekts kann also über die eigentliche Laufzeit eines Programms hinaus verlängert werden. Dazu muss ein Java-Objekt normalerweise nur die Schnittstelle Serializable implementieren. In der einfachsten Form hat die Schnittstelle nur die Aufgabe einer Kennzeichnung. Die Serialisierung selbst wird in diesem Fall vom Laufzeitsystem vorgenommen. Sollte dies dem Programmierer nicht ausreichen, besteht die Möglichkeit, die gesamte Serialisierung des Objekts manuell durchzuführen. Das Tool serialver gibt u.a. die serialVersionUID für eine oder mehrere Klassen so zurück, dass man sie in eine konkrete Klasse kopieren kann.
Java 2 Kompendium
937
Anhang A
A.2
IDEs für Java
Grundsätzlich ist die Arbeit mit dem JDK ziemlich mühsam und unkomfortabel. Zwar wird das JDK kostenlos zur Verfügung gestellt und ein einfacher Texteditor genügt als Ergänzung (wir beschränken uns in dem Buch auch auf diese Konfiguration). In der Praxis wird man sich jedoch kaum damit zufrieden geben. Die Arbeit dauert einfach zu lange, ist zu fehleranfällig und vor allem muss man bei Standardvorgängen zu viele Dinge von Hand erledigen, die eine Entwicklungsumgebung mit wenigen Klicks auch kann. Es gibt mittlerweile zahlreiche kommerzielle IDEs für Java, die von wenigen Euro bis hin zu vierstelligen Beträgen kosten. Das ist vom Produkt und dem Hersteller, vor allem aber der Version des jeweiligen Tools abhängig. Die meisten IDEs gibt es in einer Grundversion sowie darauf aufbauenden umfangreicheren Versionen. Die Grundversionen unterstützen meist keine weitergehenden Techniken wie Datenbankanbindungen, JavaBeans, Servlets oder Netzwerktechniken. Sie sind aber für die einfachere Erstellung von Oberflächen meist ausreichend. Insbesondere gibt es von vielen Profi-Tools oft eine kostenlose Light-Version, die als Basis für die Arbeit mit Java bedeutend komfortabler ist als die Arbeit mit dem JDK direkt und einem einfachen Texteditor. Wir wollen hier keine kommerziellen Tools vorstellen, sondern einige kostenlose – oder zumindest über einen gewissen Zeitraum frei einsetzbare.
A.2.1
JCreator für Windows
Ein sehr brauchbarer, kompakter, in C++ geschriebener, Freeware-Editor für Java mit einem recht intuitiv bedienbaren User-Interface ist der JCreator von Xinox Software (http://www.jcreator.com). Der Editor ist insbesondere bei schwachbrüstigen Rechnern eine sehr gute Wahl, denn er benötigt keinen sonderlich leistungsfähigen Computer. Die keine zwei MByte große Installationsdatei wird als ZIP-File bereitgestellt. Die Installation vom JCreator ist unkompliziert. Das ZIP-Archive muss nur extrahiert werden. Danach steht Ihnen ein Windows-Standard-Setup zur Verfügung, in dem Sie wie üblich Verzeichnisse und ähnliche Details auswählen können. Der JCreator liefert kein JDK oder eigene Java-Tools mit und auch keine virtuelle Maschine. Deshalb muss der JCreator wissen, wo sich die virtuelle Maschine und die JDK-Tools befinden. Die Installationsroutine sucht danach.
938
Java 2 Kompendium
IDEs für Java
Anhang A Abbildung A.3: Hier gibt es den JCreator
Abbildung A.4: Der Download
Java 2 Kompendium
939
Anhang A Abbildung A.5: Gefundenes JDKVerzeichnis
Sie können auch individuell ein JDK-Verzeichnis auswählen. Abbildung A.6: Auswahl eines JDKVerzeichnisses
Das Programm kann dann nach der Installation ohne Neustart direkt aufgerufen werden. JCreator bietet ein Projektmanagement mit Projekt-Templates, Klassenbrowser, Syntax-Highlighting, Wizards und einem frei konfigurierbarem User-Interface. Mit dem JCreator kann direkt Java-Quelltext kompiliert
940
Java 2 Kompendium
IDEs für Java
Anhang A
und ausgeführt werden. Generell kann der Zugriff auf sämtliche Tools eines zugrunde liegenden JDK in die IDE integriert werden. Auch die Verwendung von verschiedenen Compiler-Tools ist möglich. Ansonsten bietet der Editor u.a. Zeilennummerierung, praktisch unbegrenztes Undo/Redo, Drag&Drop, gleichzeitige Arbeit mit verschiedenen Dokumenten, Autoeinrückung bei neuen Zeilen, Wortkomplettierung, automatische Kontrolle von externen Dokumentveränderungen und Lesezeichen. Abbildung A.7: Die Arbeitsoberfläche des JCreators
Ein kleiner Nachteil des JCreators bezüglich des Komforts ist, dass es sich nicht um ein visuelles Tool handelt, also eine IDE, wo Programme in gewissen Teilen per Maus erstellt werden können. Im Wesentlichen sind das zwar nur Komponenten der Oberfläche (bei einfachen Ausführungen), aber den Komfort einer IDE à la Visual Basic ist bei der Erstellung einer Applikation oder eines Applets auch nicht zu verachten. Auch solche Tools gibt es kostenlos, sogar bei Sun selbst. Der Preis für deren Verwendung ist jedoch der immense Bedarf an Ressourcen und die meist recht große Installationsdatei.
A.2.2
Forte 2.0 for Java
Eine visuelle IDE für das JDK, die in einer Grundversion von Sun frei zur Verfügung gestellt wird, ist Forte 2.0 for Java. Es gibt Versionen für Linux, Solaris und Windows sowie eine universelle Version für alle Plattformen, wo eine passende virtuelle Maschine vorhanden ist. Das Programm ist in Java geschrieben und funktioniert mit dem JDK ab der Version 1.3, das zusätzlich auf dem Rechner vorhanden sein muss. Sie können die ca.
Java 2 Kompendium
941
Anhang A 9 MByte große Installationsdatei (nur die IDE – ohne Java-Tools) in verschiedenen Versionen von den Sun-Servern unter der Adresse http:// www.sun.com/forte laden. Abbildung A.8: Hier gibt es Forte
Die IDE gibt es in verschiedenen Versionen, wobei die so genannte Community Edition kostenlos ist, was sich natürlich dann auch im Leistungsumfang zeigt. Grundsätzlich müssen Sie sich aber vor einem Download registrieren lassen, auch für die kostenlose Community-Version. Wenn Sie sich registriert haben, können Sie eine Download-Quelle und die gewünschte Version auswählen. Wenn Sie die Version für alle Plattformen laden, wird eine Java-class-Datei übertragen. Die Installation der Windows-Version des Programms ist unkompliziert, aber dennoch ein paar Erwähungen wert. Der Installationsvorgang ist Javabasierend, was sich auch optisch äußert.
942
Java 2 Kompendium
IDEs für Java
Anhang A Abbildung A.9: Auswahl der Version – die Community Editon ist kostenlos
Abbildung A.10: Die Registrierung ist unumgänglich.
Java 2 Kompendium
943
Anhang A Abbildung A.11: Download-Quelle und Plattformversion
Abbildung A.12: Ein Java-Installationsdialog
944
Java 2 Kompendium
IDEs für Java
Anhang A
Wie schon angedeutet, muss für die Arbeit mit der Forte-IDE mindestens ein JDK 1.3 (genau genommen eine passende virtuelle Maschine, aber auch die entsprechenden JDK-Tools wie der Compiler, wenn man aus der IDE heraus kompilieren möchte) zur Verfügung stehen. Der Installationsvorgang sucht selbstständig nach einem solchen JDK. Abbildung A.13: Gefundene JDKs ab einer JVM 1.3
Man kann aber auch – wenn mehrere JDKs ab der Version 1.3 installiert sind – selbst eine Version auswählen. Abschließend können alle Dateien mit der Endung .java mit dem Programm verknüpft werden. Das selbst in Java geschriebene Programm bietet eine visuelle Entwicklungsumgebung für Java mit diversen frei auf dem Bildschirm platzierbaren Fenstern. Von besonderer Bedeutung ist die Leiste mit Komponenten, mit der Sie per Mausklick AWT- und Swing-Elemente in einem grafischen Modus in ein Programm integrieren und mit passendem Eventhandling versehen können. Das wirkt sich natürlich auch in dem textbasierenden Modus aus, der synchron verwaltet wird und entsprechende Programmierung auf Quelltextebene erlaubt. Darüber hinaus finden Sie Debug-Unterstützung, Projektmanagement, einen Komponenteninspektor, Klassen- und Objektbrowser und zahlreiche weitere Möglichkeiten.
Java 2 Kompendium
945
Anhang A Abbildung A.14: Auswahl eines JDKs
Abbildung A.15: Verknüpfen der Dateierweiterung mit Forte
Zusammen mit dem Java-Editor wird auch ein JavaScript-Editor bereitgestellt.
946
Java 2 Kompendium
IDEs für Java
Anhang A Abbildung A.16: Der Arbeitsbereich von Forte
Abbildung A.17: Der JavaScriptEditor von Forte
Leider gilt für dieses Tool (wie für viele visuelle Entwicklungstools -besonders, wenn sie selbst in Java geschrieben sind), dass der Rechner nicht zu schwach sein sollte – vorsichtig ausgedrückt. Selbst bei einem Athlon 600 mit 256 Megabyte werden ungeduldige Naturen bei einigen Vorgängen nervös. Oder Kaffee holen. Da beißt die Maus keinen Faden ab. Das Tool ist kein Spielzeug und wer nicht ausreichend mit der Hardware ausgestattet ist, wird damit wenig Freude haben. Das gilt auch für das nachfolgend behandelte Tool JBuilder. Java 2 Kompendium
947
Anhang A
A.2.3
JBuilder
Von dem Hersteller des legendären Turbo Pascals Inprise (früher Borland) gibt es ein kommerzielles Java-Entwicklungstool namens JBuilder. Eine Lightversion (die Version JBuilder Foundation – die Installationsdatei im ZIP-Format ist für die Version 3.5 ca. 28 MByte groß) wird kostenlos zur Verfügung gestellt, wenn man sich bei Inprise registrieren lässt (http:// www.borland.com). Abbildung A.18: Ein auf Java basierender Installationsassistent installiert den JBuilder.
Diese Registrierung ist notwendig, denn beim ersten Start des installierten Programms muss man den von Inprise zugesandten Schlüssel zur Freischaltung eingeben. Abbildung A.19: Ohne Registrierung startet der JBuilder nicht.
948
Java 2 Kompendium
IDEs für Java
Anhang A
Dazu betätig man den ADD...-Button und erhält ein passendes Eingabefenster. Abbildung A.20: Beim ersten Start werden diese Angaben notwendig.
Der JBuilder bietet in der Foundation-Version einen weitgehend mit Forte 2.0 vergleichbaren Leistungsumfang. Besonderes Highlight ist die Verknüpfung von grafischem und textbasierendem Programmiermodus. Änderungen im Textmodus wirken sich sofort – sofern davon berührt – im grafischen Modus und umgekehrt aus. Auch diverse Schablonen und Wizards machen das Leben leichter. Abbildung A.21: Die Arbeitsoberfläche des JBuilders.
Insbesondere gilt für beide visuellen Tools, dass die Programmierung des Eventhandlings damit zum Kinderspiel wird. Der Doppelklick auf eine Komponente generiert bereits eine vollständige Event-Schablone zum Standardereignis der Komponente und auch die Auswahl anderer Ereignisse lässt sich mithilfe eines Komponenten-Inspektors mühelos realisieren. Marketing-Trick von Inprise ist die deselektierte Anzeige all der Leistungen, die in der Foundation-Version des JBuilders nicht funktionieren.
Java 2 Kompendium
949
Anhang A Abbildung A.22: Einfachste Generierung von Eventmethoden per Mausklick – auch Forte bietet einen solchen Inspektor
Abbildung A.23: Appetitthappen auf die kommerziellen Versionen des JBuilders
950
Java 2 Kompendium
IDEs für Java
A.2.4
Anhang A
Kawa
Abschließend soll noch das Entwicklungstool Kawa erwähnt werden. Eine längere Zeit war das Tool unter http://www.tek-tools.com zu laden. Es ist jedoch mittlerweile an die Firma Allaire übergegangen, von deren Seiten es nun zu laden ist (http://www.allaire.com/products/kawa). Abbildung A.24: Hier gibt es Kawa.
Vor einem Download muss man sich registrieren lassen (siehe Abbildung A.25). Danach können Sie zwischen verschieden Versionen für den Download auswählen. Die Benutzerführung dahin ist ziemlich unglücklich, denn es wird nur indirekt deutlich, wie man die kostenlose Evaluation laden kann. Diese darf zudem nur 30 Tage verwendet werden. Sie müssen mindestens in der einfachsten Version eine 15 MByte große Installationsdatei laden, die dann nach der Installation mindestens 46 MByte Platz auf der Festplatte verbraten wird (die Enterprise-Version multipliziert die Eckdaten nochmals um einige Faktoren). Die Installation von Kawa erfolgt inklusive der Extrahierung vollautomatisch. Beim ersten Start von Kawa müssen Sie unbedingt den Pfad zum JDK – insbesondere zum Compiler – setzen. Sie werden von Kawa darauf automatisch hingewiesen (siehe Abbildung A.26).
Java 2 Kompendium
951
Anhang A Abbildung A.25: Registrierung
Abbildung A.26: Hinweis, dass der Compiler spezifiziert werden muss
Wenn dann das Programm installiert ist, steht Ihnen – auch schon in der Evaluation-Variante – eine übersichtliche und intuitiv zu bedienende IDE zur Verfügung. Dennoch – die gigantischen Installationsdateien und der immense Platzbedarf auf der Festplatte (im Vergleich zu der Leistung der Evaluation-Version und anderen, kostenlosen Java-Tools) sowie die zeitliche Einschränkung lässt einen Download von Kawa nur dann empfehlenswert erscheinen, wenn man danach die kommerzielle Variante wählt.
952
Java 2 Kompendium
IDEs für Java
Anhang A Abbildung A.27: Der wichtigste Konfigurationsdialog von Kawa
Abbildung A.28: Der Compiler wird angegeben.
Java 2 Kompendium
953
Anhang A Abbildung A.29: Die KawaOberfläche
954
Java 2 Kompendium
B
Anhang B
Sie finden in diesem Anhang einen allgemeinen Überblick über das Standard-API des JDK 1.3. Dies bedeutet, die darin enthaltenen Klassen sind auf jeden Fall in jeder Java-Implementierung vorhanden. Dieser Abschnitt ist insbesondere deshalb interessant, weil sich nur so die ganzen 1.1- und 1.2Erweiterungen/Veränderungen von Java nachvollziehen lassen. Das JavaAPI ist mittlerweile jedoch so umfangreich geworden, dass wir einfach eine Auswahl treffen müssen. Wir werden uns also auf eine allgemeine Übersicht beschränken, was bedeuten soll, dass für eine vollständige Information über die einzelnen Klassen, Schnittstellen, die enthaltenen Felder, Konstruktoren und Methoden sowie die Ausnahmen auf weiterführende Literatur und vor allem die 1.3-APIDokumentation der Java-Webseite von Sun (http://java.sun.com) verwiesen sei. Auch einige Unterpakete der einzelnen Java-Hauptpakete werden nur knapp angerissen. Was tun wir dann aber überhaupt hier in diesem Kapitel? Nun, Sie werden sehen, dass die Übersicht auch ohne diese Angaben der Abschnitt ziemlich umfangreich ist. Sie finden hier: Die Paket-Hierarchie des Java-API 1.3 Die Veränderungen der Paket-Struktur zwischen den APIs vor dem JDK 1.2 (inklusive Beta 3) und den Nachfolgern Eine Beschreibung der Standardpakete des Java-API 1.3 Bei den meisten Paketen eine Beschreibung wichtiger Klassenbestandteile. Dabei werden wir die Schnittstellen und Klassen teils vollständig aufführen, teils eine Auswahl. Ausnahmen und Errors werden nur in wichtigen Spezialfällen aufgeführt. Die veralteten Elemente des Java-API 1.3. Dazu soll dieser Anhang einige wichtige Tabellen rund um Java enthalten. Insbesondere zu HTML, aber auch zu JavaScript.
Java 2 Kompendium
955
Anhang B
B.1
Das Java-1.3-API
Das SDK 2-API wurde erheblich gegenüber dem 1.1-API erweitert. Es hat sich aber nicht nur zwischen der Version 1.1 mit den diversen Zwischenversionen und der Version 1.2 verändert. Gravierende Modifikationen fanden über die einzelnen Betaversionen der 1.2-API statt. Das API wurde in der Struktur teilweise vollkommen umsortiert. Wir stellen daher zuerst das 1.2API der Beta 2/3 dem Final direkt gegenüber. Die nachfolgende Tabelle stellt die einzelnen Pakete des SDK 2-StandardAPI dar. Dabei wird die bisherige Paketstruktur der neuen Struktur gegenübergestellt. Die Zuordnungsnummer in der ersten Spalte soll die Orientierung erleichtern, wenn Sie ein Paket der einen Version in der jeweils anderen Struktur suchen. »*« steht dafür, dass eine eindeutige Zuordnung zu einem Paket in der anderen Struktur nicht eindeutig möglich ist. Entweder ist die Funktionalität dort nicht vorhanden oder es ist auf andere Pakete aufgeteilt. Tabelle B.1: Die Pakete des SDK 2 gegenüber Vorgängerversionen
956
Nr.
1.2-API Beta
1.2-API Final
1
java.applet
java.applet
2
java.awt
java.awt
3
java.awt.accessibility
52
4
java.awt.color
java.awt.color
5
java.awt.datatransfer
java.awt.datatransfer
6
java.awt.dnd
java.awt.dnd
7
java.awt.event
java.awt.event
8
java.awt.font
java.awt.font
9
java.awt.geom
java.awt.geom
10
java.awt.im
java.awt.im
11
java.awt.image
java.awt.image
12
*
java.awt.image.renderable
13
java.awt.print
java.awt.print
14
java.awt.swing
53
15
java.awt.swing.basic
59
16
java.awt.swing.beaninfo
*
Java 2 Kompendium
Das Java-1.3-API
Anhang B
Nr.
1.2-API Beta
1.2-API Final
17
java.awt.swing.border
54
18
java.awt.swing.event
56
19
java.awt.swing.jlf
*
20
java.awt.swing.motif
*
21
java.awt.swing.multi
61
22
java.awt.swing.plaf
58
23
java.awt.swing.table
62
24
java.awt.swing.target
*
25
java.awt.swing.text
63
26
java.awt.swing.tree
67
27
java.awt.swing.undo
68
28
java.beans
java.beans
29
java.beans.beancontext
java.beans.beancontext
30
java.io
java.io
31
java.lang
java.lang
32
java.lang.ref
java.lang.ref
33
java.lang.reflect
java.lang.reflect
34
java.math
java.math
35
java.net
java.net
36
java.rmi
java.rmi
37
java.rmi.activation
java.rmi.activation
38
java.rmi.dgc
java.rmi.dgc
39
java.rmi.registry
java.rmi.registry
40
java.rmi.server
java.rmi.server
41
java.security
java.security
42
java.security.acl
java.security.acl
43
java.security.cert
java.security.cert
44
java.security.interface
java.security.interfaces
Java 2 Kompendium
Tabelle B.1: Die Pakete des SDK 2 gegenüber Vorgängerversionen (Forts.)
957
Anhang B Tabelle B.1: Die Pakete des SDK 2 gegenüber Vorgängerversionen (Forts.)
958
Nr.
1.2-API Beta
1.2-API Final
45
java.security.spec
java.security.spec
46
java.sql
java.sql
47
java.text
java.text
48
java.util
java.util
49
java.util.jar
java.util.jar
50
java.util.mime
*
51
java.util.zip
java.util.zip
52
3
javax.accessibility
53
14
javax.swing
54
17
javax.swing.border
55
*
javax.swing.colorchooser
56
18
javax.swing.event
57
*
javax.swing.filechooser
58
22
javax.swing.plaf
59
*
javax.swing.plaf.basic
60
*
javax.swing.plaf.metal
61
21
javax.swing.plaf.multi
62
23
javax.swing.table
63
25
javax.swing.text
64
*
javax.swing.text.html
65
*
javax.swing.text.html.parser
66
*
javax.swing.text.rtf
67
26
javax.swing.tree
68
27
javax.swing.undo
69
org.omg.CORBA
org.omg.CORBA
70
*
org.omg.CORBA.DynAnyPackage
71
org.omg.CORBA.ContainedPackage
*
72
org.omg.CORBA.ContainerPackage
*
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Nr.
1.2-API Beta
1.2-API Final
73
org.omg.CORBA.InterfaceDefPackage
*
74
org.omg.CORBA.ORBPackage
org.omg.CORBA.ORBPackage
75
org.omg.CORBA.portable
org.omg.CORBA.portable
76
org.omg.CORBA.TypeCodePackage
org.omg.CORBA.TypeCodePackage
77
org.omg.CosNaming
org.omg.CosNaming
78
org.omg.CosNaming.NamingContextPackage
org.omg.CosNaming.NamingContextPackage
Tabelle B.1: Die Pakete des SDK 2 gegenüber Vorgängerversionen (Forts.)
Die große Umstrukturierung bei der Einführung der Java-2.0-Plattform sollte nach Aussage von Sun im Funktionsumfang der Kernplattform weitgehend komplett sein. Das kann man zwar bestätigen, wenn man die Betonung auf Kernplattform legt. Wenn man sich aber das API des JDK 1.3 betrachtet, wird man eine Vielzahl an neuen Paketen entdecken. Glücklicherweise sind diese aber Erweiterungen und beinhalten keine Umstrukturierungen, wie bei dem unglücklichen Wechsel vom JDK 1.2 Beta auf das JDK 1.2. Neu in dem API des JDK 1.3 sind folgende Pakete: java.awt.im.spi javax.naming javax.naming.directory javax.naming.event javax.naming.ldap javax.naming.spi javax.rmi javax.rmi.CORBA javax.sound.midi javax.sound.midi.spi javax.sound.sampled javax.sound.sampled.spi javax.transaction org.omg.CORBA_2_3 org.omg.CORBA_2_3.portable org.omg.SendingContext org.omg.stub.java.rmi
B.2
Beschreibung der Pakete
Hier folgt nun eine Beschreibung der Pakete, die zum offiziellen Umfang von SDK 2 mit dem JDK 1.3 zählen. Beachten Sie bitte, dass wir bei den Klassen und Schnittstellen oft nur eine Auswahl angeben, wenn die jeweiligen Überschriften dies aussagen.
Java 2 Kompendium
959
Anhang B
B.2.1
java.applet
Dieses Package beinhaltet die appletspezifischen Elemente, die ein Applet braucht, um mit seiner Umwelt zu kommunizieren. Schnittstellen Tabelle B.2: Schnittstellen
AppletContext
Methoden zum Zeigen auf den Applet-Kontext
AppletStub
Methoden zum Implementieren eines Appletviewers
AudioClip
Methoden zum Abspielen von Audiodateien
Klassen Tabelle B.3: Klassen
Applet-Basisklasse
Applet
B.2.2
java.awt
Dieses Paket enthält die Klassen und Schnittstellen des Abstract Window Toolkit. Seit der Version 1.0 haben sich gerade hier massive Erweiterungen und Veränderungen ergeben. Schnittstellen Tabelle B.4: Schnittstellen
960
ActiveEvent
Methoden für Ereignisse, die sich selbst ausführen können (SDK 2)
Adjustable
Methoden für Objekte mit einstellbaren numerischen Werten, um einen Bereich von akzeptablen Werten festzulegen (Java 1.1)
Composite
Methoden zum Erstellen von einem neuen, indivdiuell zusammengestellten 2D-Image (SDK 2)
CompositeContext
Methoden, um die Umgebung von einem indivdiuell zusammengestellten 2D-Image zu definieren (SDK 2)
EventSource
Methoden für Objekte, die Ereignisse generieren (Java1.1-Beta-Interface – schon im Finalrelease und erst recht nicht mehr im SDK 2 oder gar 1.3 vorhanden)
ItemSelectable
Methoden für Objekte, die einen Satz von Einträgen enthalten, wo kein, einer oder mehrere Einträge ausgewählt werden können (Java 1.1)
LayoutManager
Methoden, um Komponenten in einem Container zu platzieren
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
LayoutManager2
Minimale Repräsentation von Methoden in einem Bereich von Komponenten (basierend auf constraints), die exakt festlegen, wo eine Komponente in einem Container platziert werden soll (Java 1.1)
MenuContainer
Methoden für Menü-bezogene Container (die Methode postEvent() gilt seit SDK 2 als verworfen)
Paint
Methoden zum Definieren von gefüllten Bereichen für 2DZeichen-Operationen (SDK 2)
PaintContext
Methoden zum Definieren von der Umgebung von einer individuellen 2D-Zeichen-Operation (SDK 2)
PrintGraphics
Methoden für die Bereitstellung eines grafischen Kontexts zum Drucken (Java 1.1)
Shape
Methoden für Objekte, die geometrische Formen darstellen (neu eingeführt in Java 1.1 und als Teil von SDK 2-2DImage-Funktionalität überarbeitet)
Stroke
Methoden, um die Fläche von einem gezeichneten Strich in grafischen 2D-Operationen darzustellen (SDK 2)
Transparency
Methoden zum Definieren von verschiedenen Transparenz-Zuständen (SDK 2)
Tabelle B.4: Schnittstellen (Forts.)
Klassen AlphaComposite
Basisregeln für Alpha-Komposition
AWTEvent
Ursprung aller AWT-Ereignisse (Java 1.1)
AWTEventMulticaster
Ein Multicast-Ereignis-Absender (Java 1.1)
AWTPermission
Ein Mittel zum Erstellen von Zugriffsregeln, die den Zugriff auf AWT-Ressourcen kontrollieren (SDK 2)
BasicStroke
Ein gezeichneter Strich (Basisformat) (SDK 2)
BorderLayout
Ein Layoutmanager für die Anordnung von Komponenten in die vier Kompass-Richtungen (die Methode addLayoutComponent() gilt seit Java 1.1 als verworfen).
Button
Eine Schaltfläche
Canvas
Ein Zeichenbereich.
CardLayout
Ein Layoutmanager für die Anordnung von Komponenten in einem Kartenlayout (die Methode addLayoutComponent() gilt seit Java 1.1 als verworfen)
Checkbox
Ein Kontrollfeld.
Java 2 Kompendium
Tabelle B.5: Klassen
961
Anhang B Tabelle B.5: Klassen (Forts.)
CheckboxGroup
Eine Gruppe von sich gegenseitig ausschließenden Kontrollfeldern (Optionsfelder) (die Methoden getCurrent() und setCurrent() sind seit Java 1.1 verworfen)
CheckboxMenuItem
Umschaltbare Menüoption
Choice
Auswahlmenü (die countItems()-Methode gilt seit Java 1.1 als verworfen)
Color
Abstrakte Darstellung einer Farbe in einem standardisieten RGB-Farbarrangement oder einem alternativen ColorSpaceobject
Component
Der Ursprung aller Benutzerschnittstellen-Komponenten, die nicht Teil eines Pulldown-Menüs sind (zahlreiche Methoden gelten seit Java 1.1 als verworfen: action(), bounds(), deliverEvent(), disable(), enable(), getPeer(), gotFocus(), handleEvent(), hide(), inside(), keyDown(), keyUp(), layout(), locate(), location(), lostFocus(), minimumSize(), mousedown(), mousedrag(), mouseEnter(), mouseExit(), mouseMove(), mouseUp(), move(), nextFocus(), postEvent(), preferredSize(), reshape(), resize(), show() und size())
ComponentOrientation
Ausrichtung von Text in Komponenten (neu im JDK 1.2)
Container
Eine Benutzerschnittstellen-Komponenten, die andere Komponenten und Container enthalten kann (einige Methoden gelten seit Java 1.1 als verworfen: countComponents(), deliverEvent(), insets(), layout(), locate(), minimumSize() und preferredSize())
962
Cursor
Ein bitmapped Mauscursor (Java 1.1)
Dialog
Ein Dialogfeld für eine einfache Benutzerinteraktion
Dimension
Eine Repräsentation von der Höhe und Breite einer Komponente oder eines anderen Objekts
Event
Ein Objekt, das die Ereignisse in dem Java 1.0.2-Eventhandling-Modell repräsentiert (ersetzt in 1.1 und 1.2, aber aus Gründen der Abwärtskompatibilität weiter vorhanden)
EventQueue
Eine Liste von Ereignissen, die darauf warten, abgearbeitet zu werden (Java 1.1)
FileDialog
Ein Dialogfenster für Dateioperationen
FlowLayout
Ein Layoutmanager zum Anordnen von Objekten in Spalten von links nach rechts
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Font
Eine Repräsentation einer Schriftart
FontMetrics
Abstrakte Klasse mit Informationen über eine bestimmte Schriftart (Form, Höhe, usw.) (die getMaxDecent()Methode ist seit Java 1.1 verworfen und ersetzt durch getMaxDescent())
Frame
Ein top-level-Fenster mit Titel und Rand (die Methoden getCursorType() und setCursor() sind seit Java 1.1
Tabelle B.5: Klassen (Forts.)
verworfen; zahlreiche Variablen sind seit SDK 2 verworfen: CROSSHAIR_CURSOR, DEFAULT_CURSOR, E_RESIZE_CURSOR, HAND_CURSOR, MOVE_CURSOR, N_RESIZE_CURSOR, NE_RESIZE_CURSOR, NW_RESIZE_CURSOR, S_RESIZE_CURSOR, SE_RESIZE_CURSOR, SW_RESIZE_CURSOR, TEXT_CURSOR, W_RESIZE_CURSOR und WAIT_CURSOR) GradientPaint
Eigenschaften für das Zeichnen eines Gradientenpatterns innerhalb einer Form (SDK 2)
Graphics
Eigenschaften zur Darstellung von Grafiken und zum Erstellen von Zeichnungen und Formen (die Methode getClipRect() gilt seit Java 1.1 als verworfen)
Graphics2D
Eine Erweiterung von Graphics, die speziell die 2DGestaltung ermöglicht (SDK 2)
GraphicsConfigTemplate
Überprüfung einer gültigen GraphicsConfiguration
GraphicsConfiguration
Die physikalischen Charakteristiken eines grafischen Ausgabegeräts (SDK 2)
GraphicsDevice
Ein grafisches Ausgabegerät – beispielsweise ein Drucker oder ein Monitor (SDK 2)
GraphicsEnvironment
Eine Repräsentation von allen grafischen Ausgabegerät und font-Objekten, die in der aktuellen Umgebung vorhanden sind (SDK 2)
GridBagConstraints
Arrangement einer individuellen Zelle in einem GridBagLayout-Arrangement
GridBagLayout
Ein Layoutmanager, der Komponenten in einem Rasterlayout arrangiert (auf Grundlage der Werte in GridBagConstraints)
GridLayout
Ein Layoutmanager, der Komponenten in einem Rasterlayout arrangiert – die Elemente werden in die Zellen des Gitters eingefügt.
Image
Eine Repräsentation eines Bitmap-Bildes
Java 2 Kompendium
963
Anhang B Tabelle B.5: Klassen (Forts.)
Insets
Abstrakte Darstellung von Einsätzen, d.h. dem äußeren Rand eines Containers
JobAttributes
Attribute zur Kontrolle eines Druckjobs (JDK 1.3)
JobAttributes.DefaultSelectionType
Eine typensichere Enumeration von möglichen Defaultaufwahlzuständen (JDK 1.3)
JobAttributes. DestinationType
Eine typensichere Enumeration von möglichen Jobzielen (JDK 1.3)
JobAttributes. DialogType
Eine typensichere Enumeration von möglichen Dialogen für einen User (JDK 1.3)
JobAttributes. MultipleDocumentHandlingType
Eine typensichere Enumeration von möglichen Verhaltensweisen bei mehreren Dokumenten (JDK 1.3)
JobAttributes. SidesType
Eine typensichere Enumeration von möglichen Verhaltensweise bei mehreren Seiten (JDK 1.3)
Label
Beschriftung für Elemente einer Benutzeroberfläche
List
Ein scrollbares Listenfeld einer Benutzeroberfläche (Einige Methoden sind seit Java 1.1 verworfen: allowsMultipleSelections(), clear(), countItems(), delItems(), isSelected(), minimumSize(), preferredSize() und setMultipleSelections(); daneben sind die Methoden addItem() und delItem()seit SDK 2 als verwor-
fen gekennzeichnet)
964
MediaTracker
Ein Weg, um den Status von Medienobjekten zu verfolgen, die über das Netz geladen wurden
Menu
Ein Set von Pulldown-Menüs, die mit einer MenuBar verbunden werden (die Methode countItems() gilt seit Java 1.1 als verworfen)
MenuBar
Ein Container für Menüs (die countMenus()-Methode gilt seit Java 1.1 als verworfen)
MenuComponent
Der Ursprung von allen Menüelementen (die Methoden getPeer() und postEvent() sind seit Java 1.1 verworfen)
MenuItem
Einzelne Einträge in einem Pulldown-Menü (die Methoden disable() und enable() sind seit Java 1.1 verworfen)
MenuShortcut
Ein Tastatur-Shortcut für die Selektion von einem Pulldown-Menüeintrag (Java 1.1)
PageAttributes
Ein Satz von Attributen zur Kontrolle der Ausgabe einer gedruckten Seite (JDK 1.3).
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
PageAttributes.ColorType
Eine typensichere Enumeration von möglichen Farbzuständen (JDK 1.3)
PageAttributes.MediaType
Eine typensichere Enumeration von möglichen Papiergrö ß en (JDK 1.3).
PageAttributes. OrientationRequestedType
Eine typensichere Enumeration von möglichen Ausrichtungen (JDK 1.3).
PageAttributes.OriginType
Eine typensichere Enumeration von möglichen Quellen (JDK 1.3)
PageAttributes.PrintQualityType
Eine typensichere Enumeration von möglichen Druckqualitäten (JDK 1.3)
Panel
Ein anzeigbarer Container
Point
Eine Repräsentation von einem Punkt in (x, y)-Koordinaten
Polygon
Vieleck (die Methoden getBoundingBox() und inside() sind seit Java 1.1 verworfen)
PopupMenu
Ein Popup-Menü an einer spezifizierten Stelle (Java 1.1)
PrintJob
Eigenschaften zum Beginnen und Durchführen einer Druckoperation (Java 1.1).
Rectangle
Ein Rechteck, das durch die obere Ecke mit der (x, y)Koordinate plus Breite und Höhe repräsentiert wird (die Methoden inside(), move(), reshape() und resize() sind seit Java 1.1 verworfen).
RenderingHints
Neu in 1.2: Rendering-Hints, die u.a. von Graphics2D genutzt werden können
RenderingHints.Keys
Neu in 1.2: Schlüssel zur Kontrolle von Rendering- und Bildprozessen
Robot
Eine Klasse zum Generieren von nativen Systemen für Eingabe-Events. Dies kann zum Testen von automatischen Vorgängen, Demos usw. verwendet werden (JDK 1.3).
Scrollbar
Eine Bildlaufleiste in einer Benutzerschnittstelle (einige Methoden sind seit Java 1.1 verworfen:,
Tabelle B.5: Klassen (Forts.)
getLineIncrement(), getPageIncrement(), getVisible() setLineIncrement() und setPageIncrement())
Java 2 Kompendium
965
Anhang B Tabelle B.5: Klassen (Forts.)
ScrollPane
Ein Container, der sich um das horizontale und vertikale Scrollen für eine einzelne Child-Komponente kümmert, sofern es notwendig ist (Java 1.1; die layout()-Methode gilt seit Java 1.1 als verworfen)
SystemColor
Die Farben, die auf dem Betriebssystem des Anwenders zur Verfügung stehen (Java 1.1)
TextArea
Ein rechteckiger, mehrzeiliger Textbereich – editierbar und scrollbar (einige Methoden sind seit Java 1.1 verworfen : appendText(), insertText(), minimumSize(), preferredSize() und replaceText())
TextComponent
Der Ursprung von allen editierbaren Textkomponenten
TextField
Ein rechteckiger, einzeiliger Textbereich – editierbar (die Methoden minimumSize(), preferredSize(), und setEchoCharacter() sind seit Java 1.1 verworfen).
TexturePaint
Eigenschaften zum Zeichen von Text in einer Form (SDK 2)
Toolkit
Abstrakte Eigenschaften zum Binden der abstrakten AWT-Klassen an eine plattformspezifische Implementation
Window
Ein Fenster auf der obersten Ebene in einer Benutzerschnittstelle (die postEvent()-Methode gilt seit Java 1.1 als verworfen)
B.2.3
java.awt.color
Dieses Paket (neu eingeführt im SDK 2) beschreibt verschiedene Systeme um Farben zu identifizieren und die Konvertierung zwischen den Systemen zu ermöglichen. Klassen Tabelle B.6: Klassen
966
ColorSpace
Das spezifische Farbsystem eines Color-Objekts, eines Bilds oder eines Graphics-Objekts
ICC_ColorSpace
Ein Farbsystem – basierend auf der International Color Consortium (ICC) Profile Format Specification
ICC_Profile
Eine Repräsentation von Farbprofildaten von der ICCSpecification
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
ICC_ProfileGray
Eine Teilmenge von Profilen, beispielsweise für monochrome Eingabe- und Ausgabegeräte
ICC_ProfileRGB
Eine Teilmenge von Profilen, beispielsweise für Eingabeund Ausgabegeräte, die auf dem 3-Komponenten-RGBKonzept basieren
B.2.4
Tabelle B.6: Klassen (Forts.)
java.awt.datatransfer
Dieses Paket (vorhanden seit Java 1.1) erlaubt den Datenaustausch von Informationen innerhalb eines oder verschiedener Programme mittles Cut, Copy und Paste. Dazu wird ein Speicherbereich genutzt, der Clipboard oder Zwischenablage genannt wird. Nahezu jeder Anwender von Windowsprogrammen kennt diese Technik. Schnittstellen ClipboardOwner
Methoden für Objekte, die Daten in einem Clipboard speichern
FlavorMap
Mappen von nativen Stringtypen in MIME-Stringtypen
Transferable
Methoden für Objekte, die die Daten in einem Clipboard nutzen können
Tabelle B.7: Schnittstellen
Klassen Clipboard
Eigenschaften, um Informationen über ein Clipboard zu übertragen
DataFlavor
Eine Repräsentation von einem Datenformat, das den Datenaustausch über ein Clipboard verwenden kann
StringSelection
Eigenschaften, um Java-Strings als einfachen Text über ein Clipboard zu übertragen
SystemFlavorMap
Mappen von nativen Stringtypen in MIME-Stringtypen und zugehörigen DataFlavors
B.2.5
Tabelle B.8: Klassen
java.awt.dnd
Dieses Paket (neu eingeführt im SDK 2) behandelt beide Seiten einer Drag&Drop-Operation.
Java 2 Kompendium
967
Anhang B Ausgewählte Schnittstellen Tabelle B.9: Schnittstellen
DragSourceListener
Methoden für den Urheber von Drag&Drop-Operationen, um die zugehörigen Ereignisse zu behandeln
DropTargetListener
Methoden für den Empfänger von Drag&Drop-Operationen, um die zugehörigen Ereignisse zu behandeln
Ausgewählte Klassen Tabelle B.10: Schnittstellen
DnDConstants
Konstanten zur Behandlung einer Drag&Drop-Operation
DragSource
Urheber einer Drag&Drop-Operation
DragSourceContext
Umgebung des Urhebers, um die Drag&Drop-Aktion zu dokumentieren und unterstützen
DragSourceDragEvent
Ereignisse, auf die der Urheber bei einer Drag-Operation reagieren kann
DragSourceDropEvent
Ereignisse, auf die der Urheber bei einer Drop-Operation reagieren kann
DragSourceEvent
Parent von Dragsource-Ereignissen
DropTarget
Empfänger einer Drag&Drop-Operation
DropTargetContext
Umgebung des Empfängers, um die Drag&Drop-Aktion zu dokumentieren und unterstützen
DropTargetDragEvent
Ereignisse, auf die der Empfänger bei einer Drag-Operation reagieren kann
DropTargetDropEvent
Ereignisse, auf die der Empfänger bei einer Drop-Operation reagieren kann
DropTargetEvent
Parent von Droptarget-Ereignissen
B.2.6
java.awt.event
Dieses Paket (vorhanden seit Java 1.1) stellt ein vollständig überarbeitetes Ereignisbehandlungssystem dar.
968
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Schnittstellen ActionListener
Methoden, um auf action-Ereignisse zu reagieren
AdjustmentListener
Methoden, um auf adjustment-Ereignisse zu reagieren
AWTEventListener
Reaktion auf Ereignisse von Component oder MenuComponent (inkl. Subklassen)
ComponentListener
Methoden, um auf component-Ereignisse zu reagieren
ContainerListener
Methoden, um auf container-Ereignisse zu reagieren
FocusListener
Methoden, um auf Ereignisse zu reagieren, die vom Focus einer Tastatur herrühren
HierarchyBoundsListener
Empfang von Bewegungs- und Grö ß enveränderungsereignissen, die von Vorgängerobjekten ausgelöst werden (JDK 1.3)
HierarchyListener
Empfang von Veränderungsereignissen, die von Vorgängerobjekten ausgelöst werden (JDK 1.3).
InputMethodListener
Methoden, um auf Ereignisse einer Eingabemethode zu reagieren (SDK 2)
ItemListener
Methoden, um auf Ereignisse von Menüeinträgen zu reagieren
KeyListener
Methoden, um auf Tastatur-Ereignisse zu reagieren
MouseListener
Methoden, um auf Maus-Ereignisse zu reagieren
MouseMotionListener
Methoden, um auf Ereignisse einer Mausbewegung zu reagieren
TextListener
Methoden, um auf Text-Ereignisse zu reagieren
WindowListener
Methoden, um auf Fenster-Ereignisse zu reagieren
Tabelle B.11: Schnittstellen
Ausgewählte Klassen ActionEvent
Ein Komponenten-definiertes action-Ereignis
AdjustmentEvent
Ein adjustment-Ereignis, generiert von einem regulierbaren Objekt
ComponentAdapter
Abstrakte Klasse für die Erstellung von neuen Komponentenreaktions-Klassen
ComponentEvent
Ein component-Ereignis
Java 2 Kompendium
Tabelle B.12: Klassen
969
Anhang B Tabelle B.12: Klassen (Forts.)
ContainerAdapter
Abstrakte Klasse für die Erstellung von neuen Containerreaktions-Klassen
ContainerEvent
Ein Container-Ereignis
FocusAdapter
Abstrakte Klasse für die Erstellung von neuen Klassen, die auf Tastaturfokus regieren
FocusEvent
Ein Tastaturfokus-Ereignis
HierarchyBoundsAdapter
Abstrakte Adapterklasse für das zugehörige Hierarchieereignis (JDK 1.3)
HierarchyEvent
Abstrakte Adapterklasse für das zugehörige Hierarchieereignis (JDK 1.3)
InputEvent
Ein Komponentenzustand-Eingabeereignis
ItemEvent
Ein Item-Ereignis, das von einem selektierbaren Objekt generiert wurde
KeyAdapter
Abstrakte Klasse für die Erstellung von neuen Tastaturreaktions-Klassen
KeyEvent
Ein Tastatur-Ereignis
MouseAdapter
Abstrakte Klasse für die Erstellung von neuen Mausreaktions-Klassen
MouseEvent
Ein Maus-Ereignis
MouseMotionAdapter
Abstrakte Klasse für die Erstellung von neuen Klassen, die auf Mausbewegung reagieren
PaintEvent
Ein Komponentenzustand-Zeichnen-Ereignis
TextEvent
Ein Text-Ereignis-Objekt, das von einem passenden Objekt – beispielsweise TextComponent – generiert wurde
WindowAdapter
Abstrakte Klasse für die Erstellung von neuen Fensterreaktions-Klassen
WindowEvent
Ein Fenster-Ereignis
B.2.7
java.awt.font
Dieses Paket (neu eingeführt im JDK 1.2) unterstützt die Zusammenstellung, Anzeige und individuelle Gestaltung von Schriftarten.
970
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Dieses Paket wurde gegenüber seinen Vorgängern in den Betaversionen erheblich verändert (was leider unzureichend dokumentiert wurde). So finden Sie dort beispielsweise die folgenden Klassen nicht mehr: GlyphSet, StyledString, StyledStringIterator Schnittstellen MultipleMaster
Methoden zur Unterstützung von Type-1-Multiple-Master-Schriftarten
OpenType
Methoden zur Unterstützung von TrueType- und OpenType-Schriftarten
Tabelle B.13: Schnittstellen
Ausgewählte Klassen GlyphJustificationInfo
Einstellbare Eigenschaften eines Gestaltungstyps
GlyphMetrics
Abmessungen des Gestaltungstyps
TextAttribute
Attribute, die für das Textlayout benötigt werden
TextHitInfo
Informationen über Abstand und exakte Einfügeposition von Zeichen in Text
TextLayout
Ein grafische Repräsentation von gestalteten Strings
B.2.8
Tabelle B.14: Klassen
java.awt.geom
Hierbei handelt es sich um ein Paket (neu eingeführt im SDK 2) zur Unterstützung von 2D-Geometrie. Schnittstellen PathIterator
Methoden für Pfadwiederholungen
Tabelle B.15: Schnittstellen
Ausgewählte Klassen AffineTransform
Affine 2D-Transformation (die Methoden prepend() und append() sind seit SDK 2 verworfen)
Arc2D
Ein Bogen, definiert von einem begrenzenden Rechteck, Startwinkel, Winkelgrad, und Abschlusstyp
Arc2D.Float
Ein Bogen, definiert mit Gleitkommagenauigkeit (float)
Area
Eine Flächengeometrie
Java 2 Kompendium
Tabelle B.16: Klassen
971
Anhang B Tabelle B.16: Klassen (Forts.)
CubicCurve2D
Kubisch parametrisiertes Kurvensegment im (x, y)-Koordinatenraum
CubicCurve2D.Float
Kubisch parametrisiertes Kurvensegment mit float-(x, y)Koordinaten
Dimension2D
Eine Repräsentation einer Dimension in Höhe und Breite
Ellipse2D
Ellipse, definiert von begrenzendem Rechteck
Ellipse2D.Float
Ellipse, spezifiziert mit float-Genauigkeit
FlatteningPathIterator
Abgeflachter Blick eines anderen PathIterator-Objekts
GeneralPath
Geometrischer Pfad, konstruiert von geraden Linen und quadratischen, sowie kubischen Kurven
Line2D
Liniensegment im (x,y)-Koordinatenraum.
Line2D.Float
Liniensegment mit float-(x,y)-Koordinaten
Point2D
Punkte im (x,y)-Koordinatenraum
Point2D.Double
Punkte mit double-(x,y)-Koordinaten
Point2D.Float
Punkte mit float-(x,y)-Koordinaten
QuadCurve2D
Quadratische Kurvensegmente im (x,y)-Koordinatenraum
QuadCurve2D.Float
Quadratische Kurvensegmente mit float-(x,y)-Koordinaten
Rectangle2D
Rechtecke, definiert von (x,y)-Position und Dimension
Rectangle2D.Double
Rechtecke mit double-Koordinaten
Rectangle2D.Float
Rechtecke mit float-Koordinaten
Rectangular.Shape
Formen, die einen rechteckigen Satz von Außenbedingungen registrieren
RoundRectangle2D
2D-Rechtecke mit bogenförmigen Ecken
RoundRectangle2D. Float
2D-Rechtecke mit bogenförmigen Ecken mit float-Koordinaten
B.2.9
java.awt.im
Hierbei handelt es sich um ein Paket (neu eingeführt im SDK 2), das ganz wesentlich die neue Internationalisierung von Java unterstützt. Unterstützt werden Eingabemethoden, die tausende von verschiedenen Zeichen interpretieren können.
972
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Schnittstellen InputMethodRequests
Methoden, die Text-editierenden Komponenten erlauben, mit Eingabemethoden zu arbeiten
Tabelle B.17: Schnittstellen
Klassen InputContext
Eigenschaften zum Verwalten der Kommunikation zwischen Eingabemethoden und Text-editierenden Komponenten
InputMethodHighlight
Eingabemethode, die Text in highlight-Style darstellt
InputSubset
Zusätzliche Unicode-Definitionen
B.2.10
Tabelle B.18: Klassen
java.awt.im.spi
Neu im JDK 1.3 eingeführt wurde dieses Paket. Es stellt Interfaces für die Entwicklung von neutralen Eingabemethoden bereit (in jedem Java-Runtime-Environment zu verwenden). InputMethod
Unterstützung für komplexe Texteingaben
InputMethodContext
Unterstützung für Eingabemethoden, die mit ihren Clientkomponenten oder anderen Diensten kommunizieren wollen
InputMethodDescriptor
Unterstützung von diversen Zusatzinformationen für die Eingabemethoden
B.2.11
Tabelle B.19: Schnittstellen
java.awt.image
Hierbei handelt es sich um ein Paket zur Handhabung von Bitmap-Bildern. Dieses Paket wurde gegenüber den Vorgängern vom JDK 1.2 (inklusive der Betaversionen) erheblich umstrukturiert. So fehlen zahlreiche Schnittstellen und Klassen, die dort noch vorhanden waren.
Java 2 Kompendium
973
Anhang B Schnittstellen Tabelle B.20: Schnittstellen
BufferedImageOp
Methoden, um Operationen auf BufferedImage-Objekten zu beschreiben (SDK 2)
ImageConsumer
Methoden zum Empfangen von Bilddaten, die von einem Bilderzeuger (ImageProducer) erstellt wurden
ImageObserver
Methoden zum Verfolgen des Ladens und Aufbauens von einem Bild
ImageProducer
Methoden zum Aufbauen und Filtern von Imagedaten, die von einem ImageConsumer-Objekt empfangen werden
RasterOp
Methoden zum Beschreiben von Operationen auf RasterObjekten (SDK 2)
RenderImage
Methoden für Objekte, die Raster produzieren oder enthalten können (SDK 2)
TileObserver
Methoden, um zu beobachten, wenn Kacheln von einem WritableRenderedImage-Objekt modifiziert werden können (SDK 2)
WriteableRenderedImage
Methoden für Objekte, die Bilder produzieren oder enthalten, die modifiziert oder überschrieben werden können (SDK 2)
Klassen Tabelle B.21: Klassen
974
AffineTransformOp
Affine Transformation zur Unterstützung von linearem Mapping von einem Bild oder Raster in ein anderes (SDK 2)
AreaAveragingScaleFilter
Filter zum Skalieren von Bildern (SDK 2)
BandCombineOp
Willkürliche lineare Kombinationen von Rasterbändern, wobei zum Spezifizieren Matrizen genutzt werden (SDK 2)
BandedSampleModel
Eigenschaften zum Sampeln von Bildern (SDK 2)
BufferedImage
Images mit einem zugänglichen Puffer von Daten (SDK 2; die Methode getGraphics() gilt seit SDK 2 als verworfen)
BufferedImageFilter
Filter, die gepufferte Bilddaten von ImageProducer-Objekten nehmen und eine modifizierte Version an ImageConsumer-Objekte weitergeben (SDK 2)
ByteLookupTable
Nachschlagetabellen für Tilechannels oder Bildkomponentenstrukturen, beispielsweise RGB (SDK 2)
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
ColorConvertOp
Pixel-by-Pixel-Farbkonvertierung von Bildern (SDK 2)
ColorModel
Eigenschaften zum Verwalten von Farbinformationen für Bilder
ComponentColorModel
Eigenschaften zum Verwalten von Farbinformationen für Bilder (willkürliche ColorSpace Objekte, SDK 2)
ComponentSampleModel
Eigenschaften zum Sampeln von Bildern (SDK 2)
ConvolveOp
Verbiegung eines Images in ein anderes (SDK 2)
CropImageFilter
Filter zum Zuschneiden (crop) von Bildern
DataBuffer
Einkapselung von einem oder mehr Datenarrays in Reihen (SDK 2)
DataBufferByte
Datenpuffer gespeichert als Bytes (SDK 2)
DataBufferInt
Datenpuffer gespeichert als int-Werte (SDK 2)
DataBufferShort
Datenpuffer gespeichert als short-Werte (SDK 2)
DataBufferUShort
Datenpuffer gespeichert als short-Werte (SDK 2)
DirectColorModel
Farbmodell zum Verwalten von Pixelfarbwerten
FilteredImageSource
Ein Bilderzeuger (ImageProducer), der aus einem Bild und dem ImageFilter-Objekt ein Bild für ein ImageConsumerObjekt erzeugt
ImageFilter
Filter, der Bilddaten aus dem ImageProducer-Objekt nimmt, sie modifiziert und an das ImageConsumer-Objekt weitergibt
IndexColorModel
Farbmodell, wo Pixelwerte in feststehende Farbmaps in einem ColorSpace-Objekt übersetzt werden
Kernel
Matrizen, die beschreiben, wie ein Pixel und die umgebenden Pixels die Werte in einer Filteroperation beeinflussen (SDK 2)
LookupOp
Diese Klasse führt eine Nachschlageoperation von der Quelle (ein Bild) zu dem Bestimmungsort (ein anderes Bild) durch (SDK 2)
LookupTable
Diese abstrakte Klasse definiert ein LookupTable-Objekt (Daten für ein oder mehr Tilechannels oder Bildkomponenten-Strukturen, SDK 2)
MemoryImageSource
Ein ImageProducer-Objekt, das Bilder aus dem Speicher erhält
Java 2 Kompendium
Tabelle B.21: Klassen (Forts.)
975
Anhang B
MultibandPackedSampleModel
Eigenschaften zum Sampeln von Bilder (SDK 2)
PackedColorModel
Ein Farbmodell von Pixelwerten (SDK 2)
PixelGrabber
Die PixelGrabber-Klasse nimmt eine Teilmenge der Pixel in einem Bild
PixelInterleavedSampleModel
Bilddaten
Raster
Raster-Repräsentation von Bilddaten (SDK 2)
ReplicateScaleFilter
Filter zum Skalieren von Bildern (Java 1.1)
RescaleOp
Pixel-by-Pixel-Skalierung von Bildern oder Rastern (SDK 2)
RGBImageFilter
Filter, die Bilddaten von dem ImageProducer-Objekt nehmen und in RGB-ImageConsumer-Objekte umwandeln.
SampleModel
Klasse zum Extrahieren von Pixel aus einem Bild.
ShortLookupTable
Nachschlagetabellen mit einer knappen Auswahl von Daten für Tilechannels oder Bildkomponentenstrukturen (SDK 2)
SingleBandPackedSampleModel
Eigenschaften zum Sampeln von Bildern (SDK 2)
WritableRaster
Beschreibbare Rasterrepräsentation von Bilddaten (SDK 2)
B.2.12
java.awt.image.renderable
Dies ist ein Paket mit unterstützenden Klassen und Schnittstellen für die Produktion von Rendering-unabhängigen Bildern. Neu im Final 1.2 eingeführt.
B.2.13
java.awt.print
Hierbei handelt es sich um ein Druck-Package, das neu im SDK 2 eingeführt wurde. Ausgewählte Schnittstellen Tabelle B.22: Schnittstellen
976
Printable
Methoden zum Drucken in Verbindung mit PageFormatObjekten
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Klassen Book
Liste von Seiten für das Drucken (mit Informationen über eine Seite – etwa den druckbaren Bereich)
PageFormat
Die Grö ß e und Ausrichtung von Seiten für das Drucken
Paper
Physikalische Charakteristierung von dem Druckpapier
PrinterJob
Kontrolle des Druckauftrags
B.2.14
Tabelle B.23: Klassen
java.beans
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1), das wiederverwendbare Softwarekomponenten – die so genannten Beans – generiert und Programme zur Manipulation zur Verfügung stellt. Schnittstellen AppletInitializer
Methoden, um Beans zu korrekt zu initialisieren, die ebenso als Applets dienen (SDK 2).
BeanInfo
Methoden für ein Bean, um Informationenn über sich selbst zu liefern.
Customizer
Methoden, die den Aufwand für die Definition eines grafischen Konfigurationeditors für ein Bean beschreiben.
DesignMode
Methoden, die die Bean-Eigenschaft festlegen, wenn sie in einer Entwicklungsumgebung verwendet werden (SDK 2).
PropertyChangeListener
Methoden um auf Veränderungen von Eigenschaften zu reagieren.
PropertyEditor
Methoden für die Unterstützung grafischer Anwenderschnittstellen zur Editierung von Eigenschaftswerten eines gegebenen Typs.
VetoableChangeListener
Methoden um auf erzwungene Veränderungen von Eigenschaften zu reagieren.
Visibility
Methoden um festzulegen, ob ein Bean eine grafische Benutzerschnittstelle hat und sie verfügbar ist.
Java 2 Kompendium
Tabelle B.24: Schnittstellen
977
Anhang B Klassen Tabelle B.25: Klassen
BeanDescriptor
Globale Informationen über ein Bean.
Beans
Allgemeine Eigenschaften um ein Bean zu kontrollieren.
EventSetDescriptor
Gruppe von Ereignissen, auf die ein Bean in der Lage ist zu generieren.
FeatureDescriptor
Parent von allen Bean-Descriptor-Klassen.
IndexedPropertyDescriptor
Beschreibt eine Eigenschaft, die wie ein Array funktioniert und einen Index für Lese-/Schreibzugriffe zur Verfügung stellt.
Introspector
Eigenschaften um ein Bean zu anlysieren.
MethodDescriptor
Eigenschaften zum Beschreiben von Methoden, mit denen auf ein Bean von außen zugegriffen werden kann.
ParameterDescriptor
Eigenschaften um zusätzliche Information in Parameter zu beschreiben.
PropertyChangeEvent
Event, wenn sich Eigenschaften verändern.
PropertyChangeSupport
Hilfeklasse für das Managen von Eigenschaften.
PropertyDescriptor
Eigenschaften und Zugriffsmethoden.
PropertyEditorManager
Eigenschaften zum Lokaliseren von einem Eigenschaften-Editor.
PropertyEditorSupport
Hilfeklasse für die Erstellung von Eigenschaften-Editoren.
SimpleBeanInfo
Hilfe für das Bereitsstellen von BeanInfo-Klassen.
VetoableChangeSupport
Hilfeklasse für Beans bei erzwungenen Eigenschaften.
B.2.15
java.bean.beancontext
Hierbei handelt es sich um ein Paket (neu eingeführt im SDK 2) zur Unterstützung von allgemeinen Diensten für Beans.
978
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Ausgewählte Schnittstellen BeanContext
Methoden zur Bereitstellung von Informationen in einem Bean-Umgebungsstatus.
BeanContextChild
Methoden zur Festlegung einer Laufzeitumgebung für Beans.
BeanContextMembershipListener
Methoden, um auf Bean-Kontextereignisse zu reagieren.
Tabelle B.26: Schnittstellen
Ausgewählte Klassen BeanContextEvent
Ereignisse, die generiert werden, wenn sich der BeanContext-Status verändert.
BeanContextMembershipEvent
Ereignisse, die generiert werden, wenn sich der Status von einem oder allen Mitgliedern eines BeanContext verändert.
BeanContextSupport
Implementation des BeanContext-Interfaces.
B.2.16
Tabelle B.27: Klassen
java.io
Dieses Paket enthält Ein- und Ausgabeklassen und Schnittstellen für Ströme und Dateien. Beim IO-Paket werden wir ausnahmsweise die Exceptions angeben, da diese extrem wichtig sind. Schnittstellen DataInput
Methoden zum Lesen von maschinenunabhängigen Eingabeströmen.
DataOutput
Methoden zum Schreiben von maschinenunabhängigen Ausgabeströmen.
Externalizable
Methoden zum Schreiben und Lesen eines Objektinhalts in einen Stream (Java 1.1).
FileFilter
Filter für abstrakte Pfadnamen.
FilenameFilter
Methoden zum Filtern von Dateinamen.
ObjectInput
Methoden zum Lesen von Objekten (Java 1.1).
ObjectInputValidation
Methoden zum Validieren eines Objekts (Java 1.1).
Java 2 Kompendium
Tabelle B.28: Schnittstellen
979
Anhang B Tabelle B.28: Schnittstellen (Forts.)
ObjectOutput
Methoden zum Schreiben von Objekten (Java 1.1).
ObjectStreamConstants
Konstanten zum Schreiben in einen Object Serilization Stream.
Serializable
Feststellung, dass diese Klasse serialisiert sein kann (Java 1.1).
Klassen Tabelle B.29: Klassen
980
BufferedInputStream
Ein gepufferter Eingabestrom.
BufferedOutputStream
Ein gepufferter Ausgabestrom.
BufferedReader
Ein gepufferter Reader (Java 1.1).
BufferedWriter
Ein gepufferter Writer (Java 1.1).
ByteArrayInputStream
Ein Eingabestrom aus einem Byte-Array.
ByteArrayOutputStream
Ein Ausgabestrom in ein Byte-Array (die toString()Methode gilt seit Java 1.1 als verworfen).
CharArrayReader
Ein Reader von einem Array von Character (Java 1.1).
CharArrayWriter
Ein Writer in ein Array von Character (Java 1.1).
DataInputStream
Eigenschaften zum maschinenunabhängigen Lesen von primitiven Javatypen (beispielsweise int, char, und boolean) aus einem Stream (die readLine()-Methode gilt seit Java 1.1 als verworfen).
DataOutputStream
Eigenschaften zum maschinenunabhängigen Schreiben von primitiven Javatypen (beispielsweise int, char, und boolean) in einen Stream.
File
Repräsentiert eine Datei auf dem Host-Dateisystem.
FileDescriptor
Eigenschaften um einen plattformspezifischen Zugriff auf eine Datei oder Socket zu realisieren
FileInputStream
Ein Eingabestrom aus einer Datei; zusammengesetzt aus dem Dateinamen oder dem Bezeichner.
FileOutputStream
Ein Ausgabestrom an eine Datei; zusammengesetzt aus dem Dateinamen oder dem Bezeichner.
FilePermission
Zugriff auf eine Datei oder ein Verzeichnis.
FileReader
Ein Reader von einer Datei; zusammengesetzt aus dem Dateinamen oder dem Bezeichner (Java 1.1).
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
FileWriter
Ein Writer in eine Datei; zusammengesetzt aus dem Dateiname oder dem Bezeichner (Java 1.1).
FilterInputStream
Abstrakte Klasse zum Filtern oder Puffern von Eingabeströmen.
FilterOutputStream
Abstrakte Klasse zum Filtern oder Puffern von Ausgabeströmen.
FilterReader
Ein Klasse, die einen Filter für Reader enthält und zugehörige Funktionalität, beispielsweise buffering (Java 1.1).
FilterWriter
Ein Klasse, die einen Filter für Writer enthält und zugehörige Funktionalität, beispielsweise buffering (Java 1.1).
InputStream
Abstrakte Klasse, die einen Eingabestrom von Bytes darstellt; der Ursprung von allen Eingabeströmen in diesem Package.
InputStreamReader
Ein Reader zur Überführung von byte-Streams in character-Streams (Java 1.1).
LineNumberInputStream
Ein Eingabestrom zum Erzeugen von Zeilennummern (im SDK 2 verworfen).
LineNumberReader
Ein gepufferter Character-Eingabestrom-Reader zum Lesen von Zeilennummern (Java 1.1).
ObjectInputStream
Ein Klasse, die Daten und Objekte deserialisiert (Java 1.1; die readLine()-Methode gilt seit SDK 2 als verworfen).
ObjectInputStream. GetField
Unterstützung für den Zugriff auf ein persistentes Feld, das aus einem Eingabestrom gelesen wird.
ObjectOutputStream
Ein Klasse, die Daten und Objekte serialisiert (Java 1.1).
ObjectOutputStream. PutField
Unterstützung für die Ausgabe in ein persistentes Feld.
ObjectStreamClass
Ein Descriptor für Klassen, die serialisiert werden können (Java 1.1).
ObjectStreamField
Beschreibung eines Feldes in einer serialisierbaren Klasse.
OutputStream
Abstrakte Klasse, die einen Ausgabestrom von Bytes darstellt; der Ursprung von allen Ausgabeströmen in diesem Package.
OutputStreamWriter
Ein Brücke zwischen byte- und character-Streams (Java 1.1).
PipedInputStream
Ein Pipe-Eingabestrom, der mit einem Pipe-Ausgabestrom verbunden werden sollte.
Java 2 Kompendium
Tabelle B.29: Klassen (Forts.)
981
Anhang B Tabelle B.29: Klassen (Forts.)
982
PipedOutputStream
Ein Pipe-Ausgabestrom, der mit einem Pipe-Eingabestrom verbunden werden sollte, um eine sichere Kommunikation zwischen Threads zu gewährleisten.
PipedReader
Ein Pipe-Reader, der mit einem Pipe-Writer verbunden werden sollte, um eine sichere Kommunikation zwischen Threads zu gewährleisten (Java 1.1).
PipedWriter
Ein Pipe-Writer, der mit einem Pipe-Reader verbunden werden sollte, um eine sichere Kommunikation zwischen Threads zu gewährleisten (Java 1.1).
PrintStream
Ein Ausgabestrom zum Drucken (verwendet von System.out.println(); die PrintStream()-Konstruktoren sind seit Java 1.1 verworfen).
PrintWriter
Ein Writer zum Drucken (Java 1.1).
PushbackInputStream
Ein Eingabestrom mit einem Rückstellpuffer (1 Byte).
PushbackReader
Ein Reader mit einem Push-back-Puffer (Java 1.1).
RandomAccessFile
Eigenschaften für den Zufallszugriff auf eine Datei – besteht aus Dateiname, Bezeichner oder Objekten.
Reader
Abstrakte Klasse, die einen Zeicheneingabe-Strom repräsentiert; der Ursprung von allen Readers in diesem Package (Java 1.1).
SequenceInputStream
Eigenschaften um aus einer Sequenz von Eingabeströmen einen einzelnen Eingabestrom zu bilden.
SerializablePermission
Eigenschaften zum Behandeln von serialisierter Zugriffskontrolle (SDK 2).
StreamTokenizer
Eigenschaften zum Konvertieren eines Eingabestrom in eine Reihe von individuellen Token (der StreamTokenizer()-Konstruktor gilt seit Java 1.1 als verworfen).
StringBufferInputStream
Ein Eingabestrom von einem String-Objekt (verworfen seit SDK 2).
StringReader
Ein Reader von einem String-Objekt (Java 1.1).
StringWriter
Ein Writer in ein String-Objekt (Java 1.1).
Writer
Abstrakte Klasse, die einen Zeichenausgabestrom repräsentiert; der Ursprung aller Writer in diesem Package (Java 1.1).
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Die Ausnahmen Hier folgt ausnahmsweise (da Ein- und Ausgabe zu den gefährlichsten Aktionen eines Programms gehören) eine Liste der Standardausnahmen. Sie sind nicht näher erklärt und können in der Dokumentation nachgelesen werden. CharConversionException EOFException FileNotFoundException InterruptedIOException InvalidClassException InvalidObjectException IOException NotActiveException NotSerializableException ObjectStreamException OptionalDataException StreamCorruptedException SyncFailedException UnsupportedEncodingException UTFDataFormatException WriteAbortedException
B.2.17
java.lang
Das wohl wichtigste Paket von Java, denn dieses Paket beinhaltet den Kern der Java-Sprache. Wir werden es deshalb inklusive aller Klassen, Schnittstellen sowie Ausnahmen und Fehler besprechen. Schnittstellen Cloneable
Methoden, um anzuzeigen, dass ein Objekt kopiert oder geklont werden kann.
Comparable
Methoden zum Vergleichen von Objekten.
Runnable
Methoden, um Klassen als Threads zu verwenden.
Tabelle B.30: Schnittstellen
Klassen Boolean
Objekt-Wrapper für boolean-Werte.
Byte
Objekt-Wrapper für byte-Werte (Java 1.1).
Character
Objekt-Wrapper für char-Werte (die Methoden isJavaLetter(), isJavaLetterOrDigit()und isSpace() sind seit
Tabelle B.31: Klassen
Java 1.1 verworfen).
Java 2 Kompendium
983
Anhang B Tabelle B.31: Klassen (Forts.)
984
Character.Subset
Ein Subset des Unicode-Zeichensatzes.
Character.UnicodeBlock
Eine Familie von Zeichenuntergruppen des Unicode-Zeichensatzes (Unicode 2.0).
Class
Darstellung von Klassen zur Laufzeit.
ClassLoader
Abstrakte Eigenschaft zum Laden von Klassen (die Methode defineClass() gilt seit Java 1.1 als verworfen).
Compiler
Systemklasse, die Zugriff auf den Java-Compiler erlaubt.
Double
Objekt-Wrapper für double-Werte.
InheritableThreadLocal
Erweiterung von ThreadLocal zur Unterstützung der Weitergabe von Werten von dem Parent-Thread zum Kindprozess (JDK 1.2).
Float
Objekt-Wrapper für float-Werte.
Integer
Objekt-Wrapper für int-Werte.
Long
Objekt-Wrapper für long-Werte.
Math
Utility-Klasse für mathematische Operationen.
Number
Abstrakte Superklasse von allen Zahlenlassen (beispielsweise integer und float).
Object
Globale Objektklasse an der obersten Stelle der Vererbungshierarchie.
Package
Versioninformation über die Implementation und Spezifikation des Java-Packages (SDK 2).
Process
Abstrakte Eigenschaft für Prozesse der Systemklasse.
Runtime
Zugriff auf die Java-Runtime-Umgebung (die Methoden getLo.calizedInputStream() und getLocalizedOutputStream() sind seit Java 1.1 verworfen).
RuntimePermission
Eigenschaften zur Bereitstellung von Laufzeitzugriffskontrolle (SDK 2).
SecurityManager
Abstrakte Eigenschaft für die Implementation von Sicherheitsmaßnahmen (die inCheck-Variable und einige Methoden gelten seit SDK 2 als verworfen: getInCheck(), classDepth(), classLoaderDepth(), inClass() und inClassLoader()).
Short
Objekt-Wrapper für short-Werte (Java 1.1).
StrictMath
Numerische Basisoperationen (JDK 1.3).
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
String
Zeichenketten (2 String()-Konstruktoren und eine getBytes()-Methode sind seit Java 1.1 verworfen).
StringBuffer
Mutationsfähige Zeichenketten.
System
Zugriff (plattformunabhängig) auf Eigenschaften der Java-Systemebene (die Methode getEnv() gilt seit Java 1.1 als verworfen).
Thread
Methoden für die Verwaltung von Threads und Klassen, die in Threads laufen (die Methoden stop(), suspend() und resume() sind seit SDK 2 verworfen).
ThreadGroup
Eine Gruppe von Threads (die Methoden stop(), suspend() und resume() sind seit SDK 2 verworfen).
ThreadLocal
Eigenschaften zum Bereitstellen von unabhängig individualisierten Variablen für Threads (SDK 2).
Throwable
Globale Exception-Klasse.
Void
Objekt-Wrapper für void-Typen (Java 1.1).
Tabelle B.31: Klassen (Forts.)
Ausnahmen ArithmeticException
Ausgeworfen bei einer arithmetischen Regelverletzung.
ArrayIndexOutOfBoundsException
Ausgeworfen bei einem illegalen Array-Zugriff.
ArrayStoreException
Ausgeworfen bei einer Typverletzung während eines Zugriffs auf ein Objekt-Array.
ClassCastException
Ausgeworfen bei einem Casting eines Objekts in eine falsche Subklasse.
ClassNotFoundException
Ausgeworfen, wenn eine Applikation versucht, eine Klasse zu laden und es Konflikte bei dem angegebenen Namen gibt.
CloneNotSupportedException
Ausgeworfen, wenn es Probleme beim Klonen von Objekten gibt.
Exception
Mutterklasse von Ausnahmen.
IllegalAccessException
Ausgeworfen bei einem illegalen Zugriff auf eine Methode (falscher Name).
IllegalArgumentException
Ausgeworfen bei einem Zugriff mit illegalen Argumenten.
IllegalMonitorStateException
Ausgeworfen bei einem fehlgeschlagenen Zugriff eines Threads auf den Monitor eines Objekts.
Java 2 Kompendium
Tabelle B.32: Exceptions
985
Anhang B Tabelle B.32: Exceptions (Forts.)
986
IllegalStateException
Aufruf einer Methode zum falschen Zeitpunkt.
IllegalThreadStateException
Falscher Status des Threads für die betreffende Operation.
IndexOutOfBoundsException
Index außerhalb des gültigen Bereichs.
InstantiationException
Ausgeworfen, wenn eine Applikation eine Instanz einer Klasse erstellen will und die Klasse ist ein Interface oder eine abstrakte Klasse.
InterruptedException
Ausgeworfen, wenn ein Thread wartet, schläft oder sonst pausiert und ein anderer Thread diese Ruhephase über die interrupt()-Methode in der Klasse Thread unterbricht.
NegativeArraySizeException
Ausgeworfen, wenn ein Array mit negativer Grö ß e erstellt werden soll.
NoSuchFieldException
Es gibt kein Feld mit diesem Namen in einer Klasse.
NoSuchMethodException
Ausgeworfen, wenn keine Methode des angegebenen Namens gefunden werden kann.
NullPointerException
Ausgeworfen, wenn eine Applikation versucht null zu verwenden, obwohl ein Objekt zwingend ist.
NumberFormatException
Ausgeworfen bei einer Konvertierung eines Strings in einen numerischen Typ, wenn der String nicht das passende Format hat.
RuntimeException
Superklasse aller Laufzeitausnahmen der Java Virtual Machine.
SecurityException
Ausgeworfen durch den Securitymanager bei einer Sicherheitsverletzung.
StringIndexOutOfBoundsException
Ausgeworfen durch die charAt()-Methode in der Klasse String und anderer String-Methoden zur Anzeige, dass ein Index negativ ist oder grö ß er bzw. gleich der Grö ß e des Strings.
UnsupportedOperationException
Ausgeworfen, wenn eine Operation nicht unterstützt wird.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Fehler AbstractMethodError
Aufruf einer abstrakten Methode.
ClassCircularityError
Zirkelbezug beim Initialisieren einer Klasse entdeckt.
ClassFormatError
Ausgeworfen, wenn die Java Virtual Machine beim Lesen einer Klasse feststellt, dass die Datei kein gültiges Javaclass-File ist.
Error
Subklasse von Throwable. Anzeige eines Problems, das nicht von der Applikation aufgefangen werden sollte.
ExceptionInInitializerError
Unerwartete Ausnahme in einen static initializer.
IllegalAccessError
Ausgeworfen bei Zugriff auf ein Feld oder eine Methode ohne Berechtigung.
IncompatibleClassChangeError
Ausgeworfen bei einer inkompatiblen Klassenveränderung.
InstantiationError
Ausgeworfen bei einer illegalen Instanzierung.
InternalError
Ausgeworfen bei einem unerwarteten internen Fehler in der Java Virtual Machine.
LinkageError
Subklassen dieser Klasse zeigen an, dass eine Klasse Abhängigkeiten auf andere Klassen beinhaltet und dort Inkompatiblitäten vorhanden sind.
NoClassDefFoundError
Ausgeworfen, wenn die Java Virtual Machine oder ein Classloader versucht eine Klasse zu laden und sie nicht findet.
NoSuchFieldError
Ausgeworfen bei einem Zugriff auf ein Feld, das nicht im Objekt enthalten ist.
NoSuchMethodError
Ausgeworfen bei einem Zugriff auf eine Methode, die nicht in der Klasse enthalten ist.
OutOfMemoryError
Ausgeworfen, wenn die Java Virtual Machine ein Objekt aus Speichermangel nicht allokieren kann.
StackOverflowError
Ausgeworfen bei einem Überlauf des Stacks.
ThreadDeath
Ausgeworfen, wenn für einen Thread die stop()-Methode ohne Argumente aufgerufen wird.
UnknownError
Ausgeworfen bei einer unbekannten Exception in der Java Virtual Machine.
Java 2 Kompendium
Tabelle B.33: Fehler
987
Anhang B Tabelle B.33: Fehler (Forts.)
UnsatisfiedLinkError
Ausgeworfen, wenn die Java Virtual Machine eine passende Native-Language-Definition von einer native deklarierten Methode nicht finden kann.
UnsupportedClassVersionError
Ausgeworfen, wenn die Java Virtual Machine versucht, eine class-Datei zu lesen und feststellt, dass die Versionsnummer in der Datei nicht unterstützt wird.
VerifyError
Ausgeworfen, wenn der Verifier entdeckt, dass die classDatei innere Inkonsistenzen oder Sicherheitsprobleme beinhaltet.
VirtualMachineError
Ausgeworfen, wenn die Java Virtual Machine abgestürzt ist bzw. nicht mehr genug Ressourcen zur Verfügung hat.
B.2.18
java.lang.ref
Hierbei handelt es sich um ein Paket (neu eingeführt im SDK 2), das es ermöglicht, Objektreferenzen wie jedes anderes Objekt zu behandeln. Klassen Tabelle B.34: Klassen
PhantomReference
Phantom-Objektreferenz.
Reference
Kernabstraktion für Objektreferenzen.
ReferenceQueue
Zusammenarbeit der Objektreferenz mit dem Garbage Collector.
SoftReference
Softreferenz.
WeakReference
Schwache Objektreferenz.
B.2.19
java.lang.reflect
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) zur Unterstützung von Reflection, d.h., um Informationen über geladene Klassen zu bekommen (beispielsweise ihre Attribute). Schnittstellen Tabelle B.35: Schnittstellen
988
InvocationHandler
Unterstützung für im JDK 1.3 neu eingeführte ProxyInstanzen (JDK 1.3).
Member
Methoden, um Informationen über ein Mitglied herauszufinden.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Klassen AccessibleObject
Basisklasse für Felder, Methoden und KonstruktorObjekten (SDK 2).
Array
Methoden zum dynamischen Generieren von und Zugreifen auf Arrays.
Constructor
Methoden für Informationen über und Zugriff auf Konstruktoren.
Field
Methoden für Informationen über und Zugriff auf Variablen.
Method
Methoden für Informationen über und Zugriff auf Methoden.
Modifier
Decoder für statische Klassen und Zugriffsmodifier.
Proxy
Die Klasse stellt statische Methoden zur Verfügung, um dynamisch Proxyklassen zu generieren (JDK 1.3).
ReflectPermission
Eigenschaften zur Bereitstellung von Zugriffkontrolle bei Reflection-Operationen (SDK 2).
B.2.20
Tabelle B.36: Klassen
java.math
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) mit Klassen für große Zahlen. Klassen BigDecimal
Eine sehr große Fließkommazahl.
BigInteger
Eine sehr große Integerzahl.
B.2.21
Tabelle B.37: Klassen
java.net
Ein Package für die Durchführung von Netzwerkoperationen, beispielsweise Socket- und URL-Handling.
Java 2 Kompendium
989
Anhang B Schnittstellen Tabelle B.38: Schnittstellen
ContentHandlerFactory
Methoden zum Erstellen von ContentHandler-Objekten.
DatagramSocketImplFactory
Unterstützung von Datagram-Sockets (JDK 1.3).
FileNameMap
Methoden zum Mappen zwischen Dateinamen und MIME-Typen (Java 1.1).
SocketImplFactory
Methoden zum Erstellen von Socket-Implementationen.
SocketOptions
Socketoptionen.
URLStreamHandlerFactory
Methoden zum Erstellen von URLStreamHandler-Objekten.
Klassen Tabelle B.39: Klassen
990
Authenticator
Ein Objekt, das Netzwerk-Beglaubigungen gewährleistet (SDK 2).
ContentHandler
Abstrakte Eigenschaft zum Lesen von Daten in einer URL-Verbindung und Konstruieren des entsprechenden lokalen Objekts auf Grundlage des MIME-Typs.
DatagramPacket
Ein Datagram-Paket (UDP).
DatagramSocket
Ein Datagram-Socket.
DatagramSocketImpl
Abstrakte Basisklasse für Datagram- und MulticastSockets (Java 1.1).
HttpURLConnection
Eine Verbindung, die das HTTP-Protokoll verarbeiten kann (Java 1.1).
InetAddress
Eine Objektrepräsentation von einem Internethost (Hostname, IP-Adresse).
JarURLConnection
Eine URL-Verbindung zu einer JAR-Datei (SDK 2).
MulticastSocket
Ein serverseitiges Socket mit Unterstützung für übermittelte Daten an mehre Clientsockets (Java 1.1).
NetPermission
Eigenschaften zur Bereitstellung von Netzzugriffskontrolle (SDK 2).
PasswordAuthentication
Username und Passwort für die Verwendung bei Authenticator (SDK 2).
ServerSocket
Ein serverseitiges Socket.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Socket
Ein Socket (2 Socket()-Konstruktoren sind seit Java 1.1 verworfen).
SocketImpl
Abstrakte Klasse für die spezifische Socketimplementation.
SocketPermission
Eigenschaften zur Bereitstellung von Netzzugriffen via Sockets in einem Netzwerk (SDK 2).
URL
Eine Objektrepräsentation einer URL.
URLClassLoader
Klassen und JAR-Archiv-Loader für eine URL-Suchpfad (SDK 2).
URLConnection
Abstrakte Eigenschaft für einen Socket, der verschiedene Web-basierende Protokolle (http, ftp usw.) handhaben kann.
URLDecoder
Konvertierung von MIME-Zeichen in String.
URLEncoder
Verwandelt Strings in das x-www-form-urlencoded-Format.
URLStreamHandler
Abstrakte Klasse zum Handhaben von Objektströmen, auf die URLs verweisen.
B.2.22
Tabelle B.39: Klassen (Forts.)
java.rmi
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) zum Erstellen von verteilten Java-to-Java-Applikationen. Schnittstellen Remote
Methoden zum Identifizieren aller entfernten (Remote-) Objekte.
Tabelle B.40: Schnittstellen
Klassen MarshalledObject
Ein byte-Stream mit einer angeordneten Repräsentation in einem Objekt (SDK 2).
Naming
Eigenschaften zum Behandeln von Referenzen auf Remote-Objekte – basierend auf der URL-Syntax.
RMISecurityManager
Methoden zur Definition der RMI Stub Security Policy für Applikationen (keine Applets).
Java 2 Kompendium
Tabelle B.41: Klassen
991
Anhang B
B.2.23
java.rmi.activation
Dieses Paket (neu eingeführt im SDK 2) unterstützt persistente (beständige) Referenzen auf Remote-Objekte und die automatische Objekt-Reaktivierung über diese Referenzen. Schnittstellen Tabelle B.42: Schnittstellen
ActivationInstantiator
Methoden zum Erstellen von Gruppen von Objekten, die aktiviert werden können.
ActivationMonitor
Methoden zum Reagieren auf Veränderungen.
ActivationSystem
Methoden zum Registieren von Gruppen und aktivierbaren Objekten.
Activator
Methoden in einem aktivierten Remote-Objekt.
Klassen Tabelle B.43: Klassen
Activatable
Remote-Objekte, die über die Zeit ihres Zugriffs persistent gemacht werden und wieder aktiviert werden können.
ActivationDesc
Descriptor mit Informationen, die in aktivierten Objekten benötigt werden.
ActivationGroup
Eigenschaften zum Gruppieren und Verfolgen von aktivierten Objekten.
ActivationGroupDesc
Descriptor mit Information zum Erstellen und wiederaktivieren von Gruppen.
ActivationGroupDesc .CommandEnvironment
Statusinformationen für ActivationGroup-Implementationen.
ActivationGroupID
Identifier für eine registierte aktivierte Gruppe.
ActivationID
Identifier für aktivierte Objekte.
B.2.24
java.rmi.dgc
Dieses Paket (vorhanden seit Java 1.1) unterstützt den (distibuted) GarbageCollection-Algorithmus.
992
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Schnittstellen Methoden zum Bereinigen von Verbindungen für nicht mehr verwendete Clients.
DGC
Tabelle B.44: Schnittstellen
Klassen Lease
Beinhaltet einen einzigartigen VM-Identifier und eine Verwendungsdauer.
VMID
Eigenschaften zur Aufrechterhaltung der einzigartigen VM-ID über alle JVM hinweg.
B.2.25
Tabelle B.45: Klassen
java.rmi.registry
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) zum Behandeln von entfernten Methoden-Aufrufen. Schnittstellen Registry
Methoden zur Bereitstellung der Registratur für verschiedene Hosts.
RegistryManager
Methoden für die Zusammenarbeit mit der privaten Implementation (die registryStub()- und registryImpl()Methoden sind seit SDK 2 verworfen).
Tabelle B.46: Schnittstellen
Klassen LocateRegistry
B.2.26
Eigenschaften zur Bereitstellung der Start-Routineregistrierung in einem Host.
Tabelle B.47: Klassen
java.rmi.server
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) für den serverseitigen Aufruf von entfernten Methoden.
Java 2 Kompendium
993
Anhang B Ausgewählte Schnittstellen Tabelle B.48: Schnittstellen
LoaderHandler
Methoden zum Behandeln von Ladeaufrufen.
RMIFailureHandler
Methoden für das Handling, wenn die RMI-Runtime nicht zum Erstellen eines Sockets oder Server-ockets in der Lage ist.
RemoteCall
Methoden für Implementationsaufrufe in einem entfernten Objekt.
RemoteRef
Repräsentiert eine Behandlung für ein entferntes Objekt.
ServerRef
Repräsentiert die serverseitige Behandlung für eine entfernte Objekt-Implementation.
Skeleton
Repräsentiert die serverseitige Entity, die Rufe zu der entfernten Objekt-Implementation sendet.
Unreferenced
Methoden zum Empfangen von Nachrichten, wenn keine Remote-Referenz mehr da ist.
Klassen Tabelle B.49: Klassen
994
LogStream
Enthält einen Mechanismus für Logging-Fehler.
ObjID
Dient zur eindeutigen Identifizierung des entfernten Objekts in einer VM.
Operation
Enthält eine Beschreibung einer Java-Methode.
RMIClassLoader
Enthält statische Methoden für das Laden von Klassen über das Netzwerk.
RMISocketFactory
Verwendet vom RMI-Runtime zur Bereitstellung von Client- und Server-Sockets für RMI-Aufrufe.
RemoteObject
Enthält die entfernte Semantik von dem Objekt über die Implementation von Methoden für hashCode, equals und toString.
RemoteServer
Die Superklasse einer Server-Implementation.
RemoteStub
Unterstützung für Stub-Objekte.
UID
Abstraktion für das Generieren von eindeutigen Identifiern.
UnicastRemoteObject
Definiert ein nicht-replizierbares Remote-Objekt, dessen Referenze nur so lange gültig ist, wie der Serverprozess läuft.
Java 2 Kompendium
Beschreibung der Pakete
B.2.27
Anhang B
java.security
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) zur Implementation von Zertifikaten und digitalen Signaturen in Java-Komponenten. Ausgewählte Schnittstellen Certificate
Methoden zum Verwalten eines Zertifikats, inklusive Verund Entschlüsselung (im SDK 2 als verworfen deklariert).
Guard
Methoden zum Schutz des Zugriffs auf ein Objekt (SDK 2).
Key
Methoden zum Definieren der gemeinsamen Funktionalität bei allen Schlüssel-Objekten (SDK 2).
Principal
Repräsentiert die prinzipielle Komponente eines Zertifikats.
PrivateKey
Methoden zum Gruppieren und Bereitstellen von PrivateKey-Schnittstellen (SDK 2).
PublicKey
Methoden zum Gruppieren und Bereitstellen von PublicKey-Schnittstellen (SDK 2).
Tabelle B.50: Schnittstellen
Ausgewählte Klassen AccessControlContext
Bedingungen für Zugangskontroll-Entscheidungen (SDK 2).
AccessController
Bereitsteller von kontrollierten Zugriffen – basierend auf einer Security Policy (SDK 2).
AlgorithmParameter Generator
Eigenschaften zum Erstellen von Parametern.
AlgorithmParameter GeneratorSpi
Serviceprovider-Interface für den AlgorithmusParameterGenerator (SDK 2).
AlgorithmParameters
Repräsentation von kryptografischen Parametern (SDK 2).
AlgorithmParametersSpi
Serviceprovider-Interface für den AlgorithmusParameter (SDK 2).
BasicPermission
Eigenschaften zur Bereitstellung von Basisrechten für die Zugriffskontrolle (SDK 2).
CodeSource
URL-Erweiterung zur Verwendung von öffentlichen Schlüsseln (SDK 2).
Java 2 Kompendium
Tabelle B.51: Klassen
995
Anhang B Tabelle B.51: Klassen (Forts.)
996
DigestInputStream
Repräsentiert einen Eingabestrom mit einer Zusammenfassung.
DigestOutputStream
Repräsentiert einen Ausgabestrom mit einer Zusammenfassung.
GuardedObject
Ein Objekt, das zum Zugriffsschutz eines anderen Objekts verwendet wird (SDK 2).
Identity
Methoden zum Verwalten von Identities (die Methoden addZertifikat() , removeZertifikat() und Zertifikats() sind seit SDK 2 verworfen).
IdentityScope
Methoden zum Definieren des Anwendungsbereichs für eine Identity inklusive dem Namen der Identity, der Schlüssel und der vereinbarten Zertifikate.
KeyFactory
Konvertor von Schlüssel-zu-Schlüssel-Spezifikationen (SDK 2).
KeyFactorySpi
Serviceprovider-Interface zur Schlüsselerstellung (SDK 2).
KeyPair
Ein einfacher Halter für ein Schlüsselpaar.
KeyPairGenerator
Generator zum Produzieren von Schlüsselpaaren (SDK 2).
KeyPairGeneratorSpi
Serviceprovider-Interface für Schlüsselpaar-Generatoren (SDK 2).
KeyStore
Im-Speicher-Halten von privaten Schlüsseln und zugehörigen Zertifikatsketten(SDK 2).
MessageDigest
Methoden zur Unterstützung von einem Message-DigestAlgorithmus zur Nachrichtenverarbeitung.
MessageDigestSpi
Serviceprovider-Interface für Nachrichtenverarbeitung (SDK 2).
Permission
Repräsentation von einem Zugriff in eine Systemressource (SDK 2).
PermissionCollection
Sammlung von Permission-Objekten (SDK 2).
Permissions
Heterogene Sammlung von Permission-Objekten (SDK 2).
Policy
Repräsentation einer Policy für ein Java-Runtime (SDK 2).
Provider
Repräsentiert ein SecurityPackageProvider (SPP) für die JavaSecurity-API.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
SecureClassLoader
Extension des ClassLoader für Klassen mit Quellcode und Signer-Informationen (SDK 2).
SecureRandom
Generiert eine Zufallszahl.
Security
Metohoden zum Verwalten von SPPs (die Methoden setParameter() und getParameter() sind seit SDK 2 verworfen).
SecurityPermission
Eigenschaften zur Bereitstellung der Security-Zugriffskontrolle (SDK 2).
Signature
Enthält den Algorithmus für digitale Signaturen.
SignatureSpi
Serviceprovider-Interface für Signatur-Objekte (SDK 2; die Methoden engineGetParameter() und engineSetParameter() sind seit SDK 2 verworfen).
SignedObject
Authentisches Runtime-Objekt, dessen Integrität ohne Aufdeckung nicht verglichen werden kann (SDK 2).
Signer
Repräsentiert eine Identity, die ebenso signieren kann.
B.2.28
Tabelle B.51: Klassen (Forts.)
java.security.acl
Hierbei handelt es sich um ein Paket, das nur Schnittstellen enhält, mit denen Zugriffe auf Ressourcen durch Wächterfunktionen kontrolliert werden können. Schnittstellen Acl
Ein Interface, das eine Zugriffskontroll-Liste (Access Control List = ACL) darstellt.
AclEntry
Methoden zum Hinzufügen, Entfernen oder Setzen von Eigenschaften für die prinzipiellen Objekte von jeder ACLEntry in dem ACL.
Group
Methoden zum Hinzufügen oder Entfernen eines Mitglieds der Gruppe von prinzipiellen Objekten.
Owner
Repräsentiert den Eigentümer eines ACL.
Permission
Repräsentiert den Typ von gewährtem Zugriff.
B.2.29
Tabelle B.52: Schnittstellen
java.security.cert
Ein Package (neu eingeführt im SDK 2) für die Identity-Zertifikation.
Java 2 Kompendium
997
Anhang B Schnittstellen Tabelle B.53: Schnittstellen
X509Extension
Extensions definiert für X.509 v3 Zertifikat- und v2 Zertifikat-Aufruflisten.
Ausgewählte Klassen Tabelle B.54: Klassen
Certificate
Identity-Zertifikat mit verschiedenen Formaten und für emeinsamen Gebrauch.
RevokedCertificate
Widerrufenes Zertifikat in einer Zertifikat-Aufrufliste.
X509CRL
X.509 Zertifikat-Aufrufliste.
X509Certificat
X.509 Zertifikat.
B.2.30
java.security.interfaces
Hierbei handelt es sich um ein Paket (eingeführt in Java 1.1) für die RSAund DSA-Technologie. Ausgewählte Schnittstellen Tabelle B.55: Schnittstellen
DSAKey
Methoden für die Verwendung in beglaubigten Komponenten inklusive Java-Applets und ActiveX-Controls.
DSAKeyPairGenerator
Methoden zum Generieren eines DSA-Schlüsselpaars.
DSAParams
Methoden zum Zugriff auf DSA-Parameter.
DSAPrivateKey
Ein Interface für private DSA-Schlüssel.
DSAPublicKey
Ein Interface für öffentliche DSA-Schlüssel.
B.2.31
java.security.spec
Ein Package (neu eingeführt im SDK 2) zur Unterstützung von Verschlüsselung. Schnittstellen Tabelle B.56: Schnittstellen
998
AlgorithmParameterSpec
Methoden zum Spezifizieren von kryptografischen Parametern.
KeySpec
Methoden zum Spezifizieren von kryptografischen Schlüsseln.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Ausgewählte Klassen DSAParameterSpec
Parameter für die Verwendung mit dem DSA-Algorithmus.
DSAPrivateKeySpec
Private DSA-Schlüssel und zugehörige Parameter.
DSAPublicKeySpec
Öffentliche DSA-Schlüssel und zugehörige Parameter.
EncodedKeySpec
Öffentliche oder private Schlüssel im verschlüsselten Format.
PKCS8EncodedKeySpec
DER-Verschlüsselung von privaten Schlüssel im PKCS #8-Standard.
X509EncodedKeySpec
DER-Verschlüsselung von privaten oder öffentlichen Schlüsseln im X.509-Standard.
B.2.32
Tabelle B.57: Klassen
java.sql
Hierbei handelt es sich um das zentrale Paket (eingeführt in Java 1.1), um mittels Structured Query Language (SQL) auf Datenbanken zuzugreifen. Sie finden darin die hauptsächliche JDBC-Funktionalität von Java. Ausgewählte Schnittstellen CallableStatement
Methoden für die Verwendung von Prozeduren und die Behandlung der Resultate.
Connection
Repräsentiert eine Session mit der Datenbank.
DatabaseMetaData
Ein Interface, um zusätzliche Informationen (Metadaten) über die Datenbank zu bekommen.
Driver
Methoden für den Aufbau einer Verbindung zu einer Datenbank.
PreparedStatement
Methoden für die Ausführung von vorkompilierten SQLStatements.
ResultSet
Methoden zum Empfangen von Werten der ausgeführten SQL-Statements.
ResultSetMetaData
Methoden mit Informationen über die Typen und Eigenschaften von den Spalten in einem Resultatsatz.
Statement
Methoden für die Verwendung von statischen SQL-Statements.
Java 2 Kompendium
Tabelle B.58: Schnittstellen
999
Anhang B Klassen Tabelle B.59: Klassen
Date
Enthält Methoden zum Formatieren und Referenzieren von Daten (SDK 2, ein Date()-Konstruktor und einige Methoden wurden verworfen: getHours(), getMinutes(), getSeconds(), setHours() setMinutes(), und setSeconds().
DriverManager
Erlaubt die Verwaltung von einem Satz von JDBC-Treibern.
DriverPropertyInfo
Enthält Methoden für die Verwaltung von verschiedenen Eigenschaften eines Treibers.
SQLPermission
Die Berechtigung, nach der der Securitymanager bei einem Applet suchen wird, wenn es eine der setLog-Writer-Methoden aufruft (JDK 1.3).
Time
Enthält Methoden zum Formatieren und Referenzieren von Zeit-Daten (Einige Methoden sind seit SDK 2 verworfen : getDate(), getDay(), getMonth(), getYear(), setDate(), setMonth() und setYear()).
Timestamp
Ein Wrapper mit den SQL-TIMESTAMP-Werten (Ein TimeStamp()-Konstruktor gilt seit SDK 2 als verworfen).
Types
Definiert Konstanten für die Identifikation von SQLTypen.
B.2.33
java.text
Dieses Paket ist die Basis der Arbeit mit Strings im Allgemeinen, zur Erstellung von Strings aus anderen Objekten und der Konvertierung von Strings in andere Objekte. Auch dieses Paket hatte einige neue Elemente und Strukturen in den Betaversionen des JDK 1.2 eingeführt, die für die Finalversion 1.2 wieder verworfen wurden. Schnittstellen Tabelle B.60: Schnittstellen
1000
AttributeCharacterIterator
Methoden zum Durchforsten des Texts und der AttributInformationen (SDK 2).
CharacterIterator
Methoden zum Analysieren eines Strings und der Rückgabe diverser Informationen über ihn.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Ausgewählte Klassen Annotation
Wrapper für Textattribut-Werte (SDK 2).
AttributedString
Text- und zugehörige Attribut-Informationen (SDK 2).
BreakIterator
Eigenschaften zur Lokalisierung von Textgrenzen bzw. -Breaks (SDK 2).
ChoiceFormat
Methoden zum Anheften von Formaten an Werte.
CollationElementIterator
Iterator zum Durchlaufen von Zeichen in einem internationalen String (SDK 2).
Collation
Vergleichen von Unicode-Text.
CollationElementIterator
Iterieren eines internationalen Strings.
CollationKey
Behandelt einen String nach den Regeln eines spezifischen Vergleichsobjekts (SDK 2).
Collator
String-Vergleiche (SDK 2).
DateFormat
Abstrakte Klasse mit einigen Datum-/Uhrzeit-Formatierungs-Subklassen.
DateFormatSymbols
Lokale Datum-/Uhrzeit-Formatierungs-Daten (SDK 2).
DecimalFormat
Methoden zum Formatieren von Zahlen.
DecimalFormatSymbols
Symbole für die Verwendung des Dezimalformats bei der Formatierung von Zahlen (SDK 2).
FieldPosition
Eigenschaften zur Identifizierung von Feldern in formatierten Ausgaben (SDK 2).
Format
Eine Basisklasse für alle Formate.
MessageFormat
Methoden zum Erstellen von formatierten Nachrichten.
NumberFormat
Abstrakte Klasse für alle Zahlenformate.
ParseStatus
Der Status von der jeweiligen Gliederung, wenn man durch einen String mit verschiedenen Formaten geht.
RuleBasedCollator
Subklasse von Collator, um eine einfache Vergleichstabelle zu erstellen (SDK 2).
SimpleDateFormat
Methoden zum Formatieren eines Datums oder der Zeit in einem String.
StringCharacterIterator
Methoden für die bidirektionale Iteration über einen String.
Java 2 Kompendium
Tabelle B.61: Klassen
1001
Anhang B
B.2.34
java.util
Das Paket stellt – wie der Namen schon sagt – Hilfsmittel für die verschiedensten Zwecke bereit. Es beinhaltet verschiedene Utility-Klassen und -Schnittstellen, etwa Zufallszahlen oder Systemeigenschaften. Ausgewählte Schnittstellen Tabelle B.62: Schnittstellen
Collection
Methoden zur Implementation von Sammlungen (SDK 2).
Comparator
Methoden zur Anforderung einer Sammlung von Objekten (SDK 2).
Enumeration
Ein Objekt, das eine Aufzählungsschnittstelle implementiert. Auf die einzelnen Elementen einer Serie kann sukzessive mit der nextElement-Methode zugegriffen werden.
EventListener
Methoden zum Beobachten von Ereignissen (Java 1.1).
Iterator
Methoden zur Iteratation einer Sammlung (SDK 2).
List
Methoden um eine angeforderte Sammlung aufzuzählen (SDK 2).
ListIterator
Methoden zum Aufzählen einer Liste in jedem Verzeichnis (SDK 2).
Map
Methoden zum Mappen von Schlüsseln in Werte (SDK 2).
Map.Entry
Ein Map-Eintrag (ein Paar an Schlüsselwerten).
Observer
Methoden für die Unterstützung von Klassen mit Observable-Objekten.
Set
Sammlung ohne doppelte Elemente (SDK 2).
Ausgewählte Klassen Tabelle B.63: Klassen
1002
AbstractCollection
Skelettartige Implementation von einer Sammlung (SDK 2).
AbstractList
Skelettartige Implementation von einer Liste (SDK 2).
AbstractMap
Skelettartige Implementation von einer Map (SDK 2).
AbstractSequentialList
Skelettartige Implementation von einer Liste in Verbindung mit einem sequenziellen Zugriff (SDK 2).
AbstractSet
Skelettartige Implementation von einem Set (SDK 2).
ArrayList
Implementation von einer Liste mit in der Grö ß e veränderbarem Array (SDK 2).
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Arrays
Eigenschaften für die Array-Sortierung und anderer Manipulationen (SDK 2).
BitSet
Eine Bitmenge.
Calendar
Ein allgemeiner Kalender (Java 1.1).
Collections
Eigenschaften zum Manipulierung oder Zurückgeben von Collection-Objekten (SDK 2).
Date
Das aktuelle Systemdatum, sowie Methoden zum Generieren und Abgleichen von Datumsangaben (Java 1.1, 4 Date()-Konstruktoren, und zahlreiche Methoden gelten mittlerweile als verworfen: UTC(), parse(), getYear(),
Tabelle B.63: Klassen (Forts.)
setYear(), getMonth(), setMonth(), getDate(), setDate(), getDay(), getHours(), setHours(), getMinutes(), setMinutes(), getSeconds(), setSeconds(), toLocaleString(), toGMTString(), und getTimeZoneOffset()). Dictionary
Abstrakte Klasse, die zwischen Schlüsseln und Werten konvertiert (Superklasse von HashTable).
EventObject
Ein Ereignis-Objekt (Java 1.1).
GregorianCalendar
Eine Repräsentation des Gregorianischen Kalenders (Java 1.1).
HashMap
Implementation einer Map – basierend auf Hash-Tabellen (SDK 2).
HashSet
Implementation eines Sets – basierend auf Hash-Tabellen (SDK 2).
Hashtable
Eine Hash-Tabelle.
LinkedList
Implementation von einer gelinkten Liste mit in der Grö ß e veränderbarem Array (SDK 2).
ListResourceBundle
Ein Ressourcen-Versorger für einen Ort (Java 1.1).
Locale
Eine Beschreibung eines geografischen Orts (Java 1.1).
Observable
Abstrakte Klasse für observable-Objekte.
Properties
Eine Hash-Tabelle, die die Eigenschaften zum Setzen und Abrufen von persistenten Merkmalen des Systems oder einer Klasse enthält.
PropertyPermissions
Eigenschaften um den Zugang zu Eigenschaften zu kontrollieren (SDK 2).
PropertyResourceBundle
Ein Ressoursenversorger, der Eigenschaften von einer Datei verwenden kann (Java 1.1).
Java 2 Kompendium
1003
Anhang B Tabelle B.63: Klassen (Forts.)
Random
Utilities für die Erzeugung von Zufallszahlen.
ResourceBundle
Ein Satz von Objekten, die einem Ort zugeordnet sind (Java 1.1).
SimpleTimeZone
Eine vereinfachte Zeitzone (Java 1.1).
Stack
Ein Stack.
StringTokenizer
Utilities für das Splitting von Zeichenketten in einzelne Token.
TimeZone
Eine allgemeine Zeitzone (Java 1.1).
TreeMap
Implementation einer Map – basierend auf einer Baumstruktur (SDK 2).
Vector
Ein Array von Objekten, das dynamisch wachsen kann.
B.2.35
java.util.jar
Hierbei handelt es sich um ein Paket (neu eingeführt im SDK 2) für die Behandlung von Java Archive Resource (JAR)-Dateien. Klassen Tabelle B.64: Klassen
Attribute
Mapping von manifestierten Attributnamen in zugehörigen String-Werten.
Attributes.Name
Repräsentiert einen Attributnamen in dieser Map.
JarEntry
JAR-Datei-Entry.
JarFile
Eigenschaften zum Lesen von JAR-Dateien.
JarInputStream
Eingabestrom, der JAR-Dateien liest.
JarOutputStream
Ausgabestrom, der JAR-Dateien schreibt.
Manifest
Manifestierte Entry-Namen und zugehörige Attribute.
B.2.36
java.util.zip
Dieses Paket enthält Klassen für den Zugriff auf komprimierte Dateiarchive (Zip- und gZip-Algorithmus). Schnittstellen Tabelle B.65: Schnittstellen
1004
Checksum
Methoden zur Berechnung einer Checksumme.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Klassen Adler32
Berechnet eine Adler 32-Checksumme.
CRC32
Berechnet eine CRC 32-Checksumme.
CheckedInputStream
Eingabestrom mit zugehöriger Checksumme.
CheckedOutputStream
Ausgabestrom mit zugehöriger Checksumme.
Deflater
Komprimierer für unkomprimierte Dateien.
DeflaterOutputStream
Ausgabestrom, der auch komprimiert.
GZIPInputSteam
Eingabestrom von einer gZip-Datei.
GZIPOutputStream
Ausgabestrom in eine gZip-Datei.
Inflater
Dekomprimierer für komprimierte Dateien.
InflaterInputStream
Eingabestrom, der auch dekomprimiert.
ZipEntry
Eine Datei-Entry innerhalb einer Zip-Datei.
ZipFile
Eine vollständige Zip-Datei.
ZipInputStream
Eingabestrom von einer Zip-Datei.
ZipOutputStream
Ausgabestrom in eine Zip-Datei.
B.2.37
Tabelle B.66: Klassen
javax.accessibility
Dieses Paket (ehemals java.awt.accessibility), eingeführt im SDK 2, beinhaltet Möglichkeiten, um mit innovativen Hilfstechnologien (etwa Spracheingabesystemen, Touchscreens oder Blindensprache-Terminals) interagieren zu können. Die daraus resultierenden Applikationen sind nicht auf bestimmte technische Plattformen beschränkt, sondern können auf jeder Maschine eingesetzt werden, die die virtuelle Javamaschine unterstützt.
Ausgewählte Schnittstellen Accessible
Methoden, um ein Benutzerschnittstellen-Element für die verschiedenen Zugriffsmöglichkeiten zugänglich zu machen.
AccessibleText
Methoden, um Text exakt an einer angegebenen Koordinate auf einem grafischen Ausgabegerät auszugeben.
Java 2 Kompendium
Tabelle B.67: Schnittstellen
1005
Anhang B Ausgewählte Klassen Tabelle B.68: Klassen
AccessibleRole
Eine präzise Beschreibung von Regeln, die ein Element in einem User-Interface innerhalb der Schnittstelle einhalten muss.
AccessibleState
Eine präzise Beschreibung des Status von einem Element in einem User-Interface.
AccessibleStateSet
Das Set von allen AccessibleState-Objekten, die den vollständigen Status von einem Schnittstellenelement repräsentieren.
B.2.38
javax.naming
Unterstützung von Nameservices. Neu im JDK 1.3 eingeführt. Das Paket stellt insbesondere eine große Anzahl von spezialisierten Ausnahmen bereit Ausgewählte Schnittstellen Tabelle B.69: Schnittstellen
Context
Namen-Kontext mit einem Satz von Name-zu-ObjektBindungen.
Name
Eine namentliche Repräsentation einer Sequenz von Komponenten.
NameParser
Parsing von Namen.
Ausgewählte Klassen Tabelle B.70: Klassen
Binding
Eine Name-zu-Objekt-Bindung in einem Kontext.
Reference
Eine Referenz auf ein außerhalb des Namens/Verzeichnis-Systems befindlichen Objekt.
Exceptions AuthenticationException AuthenticationNotSupportedException CannotProceedException CommunicationException ConfigurationException ContextNotEmptyException InsufficientResourcesException InterruptedNamingException InvalidNameException LimitExceededException
1006
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
LinkException LinkLoopException MalformedLinkException NameAlreadyBoundException NameNotFoundException NamingException NamingSecurityException NoInitialContextException NoPermissionException NotContextException OperationNotSupportedException PartialResultException ReferralException ServiceUnavailableException SizeLimitExceededException TimeLimitExceededException
B.2.39
javax.naming.directory
Eine im JDK 1.3 eingeführte Erweiterung von javax.naming zur Unterstützung des Zugriffs auf Directory-Services. Schnittstellen Attribute
Mit dem benannten Objekt assoziierte Attribute.
Attributes
Eine Collection von Attributen.
DirContext
Ein Directory-Service-Interface fürVerzeichnisoperationen.
Tabelle B.71: Schnittstellen
Ausgeswähte Klassen BasicAttribute
Basisimplementation des Attribute-Interfaces.
BasicAttributes
Basisimplementation des Attributes-Interfaces.
InitialDirContext
Start-Kontext zur Unterstützung von Verzeichnisoperationen.
B.2.40
Tabelle B.72: Klassen
javax.naming.event, javax.naming.ldap und javax.naming.spi
Drei weitere Pakete zur Unterstützung des Naming-Services von Java. Das Paket javax.naming.event bietet Unterstützung für Ereignisse beim Zugriff auf Naming- und Directory-Services, javax.naming.ldap für erweiterte Operationen und Controls auf Basis von LDAPv3 und javax.naming.spi fungiert als Service-Provider-Interface (SPI).
Java 2 Kompendium
1007
Anhang B
B.2.41
javax.rmi und javax.rmi.CORBA
Das im JDK 1.3 eingeführte Paket javax.rmi umfasst ein User-API für RMIIIOP. Es beinhaltet nur die Klasse PortableRemoteObject. Auch das ebenfalls im JDK 1.3 eingeführte Paket javax.rmi.CORBA dient der Unterstützung von RMI-IIOP.
B.2.42
javax.sound.midi
Im JDK 1.3 wurde die Unterstützung für Multimedia unter Java erheblich erweitert. Dies Paket stellt Interfaces und Klassen zur Ein- und Ausgabe, Sequencing und MIDI (Musical Instrument Digital Interface)-Daten bereit. Ausgewählte Schnittstellen Tabelle B.73: Schnittstellen
MidiChannel
Ein MidiChannel-Objekt, das einen einzelnen MIDI-Channel darstellt.
MidiDevice
Basis-Interface für alle MIDI-Devices.
Receiver
Empfänger für MidiEvent-Objekte.
Sequencer
Ein Hardware- oder Software-Device, der als MIDISequencer zur Wiedergabe dient.
Soundbank
Ein Satz von Instrumenten zum Laden in einen Synthesizer.
Synthesizer
Ein Synthesizer zur Tonerzeugung.
Transmitter
Ein Transmitter, der MidiEvent-Objekte an einen oder mehrere Receiver sendet.
Ausgewählte Klassen Tabelle B.74: Klassen
1008
Instrument
Ein Algorithmus zum Erzeugen eines Instrumentenklangs.
MidiEvent
Eine MIDI-Botschaft mit korrespondierendem Timestamp in Ticks.
MidiFileFormat
Allgemeine Informationen über MIDI-Dateitypen und Timing.
MidiMessage
Basisklasse für alle MIDI-Messages.
MidiSystem
Zugriff auf die installiereten MIDI-Systemressourcen.
Patch
Repräsentation eines einzelnen Instruments in einem MIDI-Synthesizer.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Sequence
Datenstruktur mit Musikinformationen, die von einem Sequencer-Objekt wiedergegeben werden kann.
Track
Ein unabhängiger Strom von MIDI-Events, der zusammen mit anderen Tracks in einem Standard-MIDI-File abgelegt werden kann.
B.2.43
Tabelle B.74: Klassen (Forts.)
javax.sound.midi.spi, javax.sound.sampled und javax.sound.sampled.spi
Diese drei im JDK 1.3 eingeführten Pakete bieten das Paket javax.sound.midi erweiternde Unterstützung für MIDI. javax.sound.midi.spi ist ein Serviceprovider zur Implementierung von neuen MIDI-Devices, MIDI-Filereaders und MIDI-Filewriters sowie neuen Sounds. javax.sound.sampled unterstützt gesampelde Audiodaten und javax.sound.sampled.spi ist ein weiterer Serviceprovider zur Implementierung von neuen MIDI-Devices, MIDI-Filereaders und MIDI-Filewriters sowie neuen Audioformaten.
B.2.44
javax.swing & Co
Bei Swing handelt es sich um eine Paketsammlung – oder besser: ein ganzes Konzept – (in der aktuellen Form neu eingeführt im SDK 2), das ein ganzes Set von neuen grafischen Benutzerschnittstellen-Komponenten und andere Interface-Erweiterungen enthält. Swing Komponenten können automatisch das Look and Feel einer Plattform (beispielsweise Windows 95, Macintosh und Solaris) annehmen. Swing gab es schon vor dem SDK 2. Wurde das Swing-Paket in den den Vorgängerversionen des JDK 1.2 Final noch unter java.awt.swing geführt, ist es jetzt – wie zahlreiche damit verbundenen Pakete in der javax-Struktur eingeordnet. Insgesamt ist die Struktur des Swing-APIs vollkommen überarbeitet worden und hat vielfach nichts mehr gemein mit dem Konzept der Vorgängerversionen. Zahlreiche Klassen und Schnittstellen, die selbst in den Beta-Ausführungen des JDK 1.2 vorgestellt wurden, waren in dessen Finalrelease nicht realisiert. Entweder ist deren Funktionalität in anderen Paketen und Klassen aufgegangen oder die Realisierung hat sich als nicht sinnvoll herausgestellt. Die Swing-Komponenten beinhalten Duplikate von allen AWT-Komponenten und unzählige zusätzliche Komponenten. Das Konzept umfasst neben dem Hauptpaket javax.swing im JDK 1.3 die folgenden Unterpakete: javax.swing.border javax.swing.colorchooser
Java 2 Kompendium
1009
Anhang B javax.swing.event javax.swing.filechooser javax.swing.plaf javax.swing.plaf.basic javax.swing.plaf.metal javax.swing.plaf.multi javax.swing.table javax.swing.text javax.swing.text.html javax.swing.text.html.parser javax.swing.text.rtf javax.swing.tree javax.swing.undo javax.transaction
Das Paket javax.transaction kam erst im JDK 1.3 hinzu. Die anderen Pakete stehen bereits seit dem JDK 1.2 zur Verfügung. Wir werden hier nur das Hauptpaket javax.swing behandeln und nachfolgend einige ausgewählte Subpakete. Eine vollständige Auflistung sprengt unseren Rahmen. Detaillierte Informationen finden Sie in der Dokumentation. Ausgewählte Schnittstellen Tabelle B.75: Schnittstellen
1010
Action
Methoden in Verbindung mit verschiedenen Komponenten mit action-Kommandofunktionalität.
BoundedRangeModel
Methoden, um die Daten in einer Bildlaufleiste oder einer Slider-Komponente darzustellen.
ButtonModel
Methoden, um den Status eines Buttons darzustellen.
CellEditor
Methoden zum Editieren von Tabellen in Komponenten, beispielsweise ComboBoxen und Auswahllisten.
ComboBoxEditor
Methoden zum Editieren von ComboBoxen.
ComboBoxModel
Methoden, um die Daten in einer in einer ComboBox darzustellen.
DesktopManager
Methoden, um die Look-and-Feel-Eigenschaft für JDesktopPane zu implementieren.
Icon
Kleines Bild für die Verwendung bei Komponenten.
JComboBox.KeySelectionManager
Methode zum Definieren von einem KeySelectionManager.
ListCellRenderer
Methoden zum Zeichnen der Zellen in einer Liste.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
ListModel
Methoden zum Darstellen der Daten in einer Liste.
ListSelectionModel
Methoden zum Darstellen der aktuellen Selektion in einer Liste.
Renderer
Tabelle B.75: Schnittstellen (Forts.)
Enthält die abstrakten Methoden getComponent() setValue(Object, boolean).
ScrollPaneConstants
Konstanten für die Verwendung mit JscrollPane-Objekten.
Scrollable
Methoden zur Verwaltung von Informationen in einem scrollenden Container.
SingleSelectionModel
Methoden zum Darstellen der ausschließlich erlaubten Selektion in einer Liste.
SwingConstants
Konstanten für die Verwendung mit Swing-Komponenten
UIDefaults.ActiveValue
Methoden zum Speichern eines Eintrags in der DefaultTabelle.
UIDefaults.LazyValue
Methoden zum Speichern eines Eintrags in der DefaultTabelle, die nicht konstruiert wird, bis sie angewendet wird.
WindowConstants
Konstanten für die Verwendung mit Jwindow-Komponenten.
Ausgewählte Klassen AbstractAction
Eigenschaften für action-Objekte.
AbstractButton
Gemeinsame Eigenschaften für button-Komponenten (die Methoden getLabel() und setLabel()gelten im SDK 2 als veraltet).
AbstractListModel
Datenmodell, das eine Listenkomponente füllt.
BorderFactory
Erzeuger von Standardrand-Objekten.
Box
Container, der den Boxlayoutmanager verwendet.
Box.Filler
Boxcontainer mit keiner sichtbaren Oberfläche.
BoxLayout
Box-Layoutmanager.
ButtonGroup
Eine Klasse, die innerhalb einer Gruppe von Schaltflächen nur einem Button erlaubt, selektiert zu werden.
CellRendererPane
Eine Klasse, die zwischen Zellinterpretationen und Komponenten eingefügt wird, um repaint() und invalidate()Aufrufe abzublocken.
Java 2 Kompendium
Tabelle B.76: Klassen
1011
Anhang B Tabelle B.76: Klassen (Forts.)
1012
DebugGraphics
Unterstützung von grafischem Debuggen.
DefaultBoundedRangeModel
Allgemein begrenztes Bereichsmodell.
DefaultButtonModel
Defaultversion eines Button-Datenmodells.
DefaultCellEditor
Default-Editor für Tabellen und Baumzellen.
DefaultDesktopManager
Allgemeiner Desktopmanager.
DefaultFocusManager
Allgemeiner Focusmanager.
DefaultListModel
Defaultversion eines Listkomponenten-Datenmodells.
DefaultListSelectionModel
Default-Version der selektierten Einträgen in einer Liste.
DefaultSingleSelectionModel
Default-Version des ausschließlich selektierten Eintrags in einer Liste.
FocusManager
Ein Komponenten-Fokusmanager.
GrayFilter
Unterbinden der Selektion einer Komponente, indem sie grau gesetzt wird.
ImageIcon
Implementation eines Icon-Interfaces.
JApplet
Swing-Appletfenster.
JButton
Swing – anklickbarer Button.
JCheckBox
Swing-Checkbox.
JCheckBoxMenuItem
Swing-Checkbox-Eintrag in einem Pulldown-Menü.
JColorChooser
Swing-Farbauswahldialog.
JComboBox
Swing – kombinierte Listbox und Textfeld.
JComponent
Swing-Komponenten-Ursprungsklasse.
JDesktopPane
Swing-Desktoppanel.
JDialog
Swing-Dialogfenster.
JEditorPane
Swing-Editorpanel.
JFileChooser
Swing-Dateiauswahldialog.
JFrame
Swing-Framefenster.
JInternalFrame
Swing-internes Frame.
JLabel
Swing-Label.
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
JLayeredPane
Swing – schichtenweiser Panecontainer.
JList
Swing-Auswahlliste.
JMenu
Swing-Pulldown-Menü.
JMenuBar
Swing-Menubar in einer Fensterkomponente.
JMenuItem
Swing-Menüeintrag in einem Pulldown-Menü.
JOptionPane
Swing-Options-Panelcontainer.
JPanel
Swing-Panelcontainer.
JPasswordField
Swing-Passwort-Textfeld mit verdeckten Zeichen.
JPopupMenu
Swing-Popup-Menü.
JProgressBar
Swing-Progressbar Komponente.
JRadioButton
Swing-Radiobutton.
JRadioButtonMenuItem
Swing-Radiobutton in einem Pulldown-Menü.
JRootPane
Swing-Rootpanecontainer.
JScrollBar
Swing-Bildlaufleiste.
JScrollPane
Swing – scrollbarer Panecontainer.
JSeparator
Swing-Menü-Separatorkomponente.
JSlider
Swing-Slider.
JSplitPane
Swing-geteilter Panelcontainer.
JTabbedPane
Swing-Panelcontainer mit Tabulator.
JTable
Swing-Tabelle.
JTextArea
Swing – multiline Textfeld.
JTextField
Swing – singleline Textfeld.
JTextPane
Swing-Text-Panecontainer.
JToggleButton
Swing – umschaltbarer Button.
JToggleButton. ToggleButtonModel
Das ToggleButton-Modell.
JToolBar
Swing-Toolbar.
JToolBar.Separator
Seperator für die Swing-Toolbar.
JToolTip
Swing-Popup-ToolTip-Komponente.
Java 2 Kompendium
Tabelle B.76: Klassen (Forts.)
1013
Anhang B Tabelle B.76: Klassen (Forts.)
JTree
Swing-Verzeichnisbaum.
JTree.DynamicUtilTreeNode
Unterstützung von dynamischen Vorgängen bei der Veränderung eines Verzeichnisbaums.
JTree.EmptySelectionModel
Ein Baumselektionsmodell, das keine Selektion erlaubt (nur Anzeige).
JTree. TreeSelectionRedirector
Unterstützung der Generierung eines neuen TreeSelectionEvent mit JTree als Source und Weiterreichen an alle betroffenen Listener.
JViewport
Swing-Viewportcontainer.
JWindow
Swing-Fenstercontainer.
KeyStroke
Ein Schlüssel, der mit der Tastatur eingegeben wird.
OverlayLayout
Overlay-Layoutmanager.
ProgressMonitor
Eigenschaften zum Verfolgen von Fortschritten bei einer Operation.
ProgressMonitorInputStream
Eigenschaften zum Verfolgen von Fortschritten bei einem Eingabestrom.
RepaintManager
Manager für die Komponenteanzeige.
ScrollPaneLayout
Scrollpanel-Layoutmanager.
SizeRequirements
Grö ß enangaben für die Verwendung in einem Layoutmanager.
SwingUtilities
Utility-Methoden für die Verwendung unter Swing.
Timer
Ein Event, das ein Intervall steuert.
ToolTipManager
Manager von ToolTip-Komponenten.
UIDefaults
Defaultwerte für Swing-Komponenten.
UIManager
Klasse zum Kennzeichnen des aktuellen Look and Feel.
ViewportLayout
Viewport-Layoutmanager.
B.2.45
javax.swing.event
Hierbei (vormals java.awt.swing.event) handelt es sich um ein Swing-Unterpaket (neu eingeführt im SDK 2) zur Unterstützung der neuen Ereignisse, die von den Swing-Komponenten ausgelöst werden.
1014
Java 2 Kompendium
Beschreibung der Pakete
Anhang B
Ausgewählte Schnittstellen AncestorListener
Methoden, um eine Veränderung in einer Swing-Komponente oder den Superklassen zu bemerken.
ChangeListener
Methoden, um auf Textveränderungen zu reagieren.
DocumentEvent
Methoden, um auf Dokumentveränderungen zu reagieren.
DocumentEvent. ElementChange
Beschreibt die Veränderungen eines Elements.
DocumentListener
Weitere Methoden, um auf Dokumentveränderungen zu reagieren.
ListDataListener
Ein ListData-Listener.
ListSelectionListener
Ein Listener, der beobachtet, wenn sich in einer Listenselektion Werte ändern.
MenuListener
Ein Menu-Listener.
TableColumnModelListener
Methoden, um auf Veränderungen in einer Tabellenspalte zu reagieren
TableModelListener
Methoden, um auf Verän.derungen in einer Tabellen zu reagieren.
TreeExpansionListener
Methoden, um auf die Erweiterung von einem Verzeichnisbaum zu reagieren.
TreeModelListener
Methoden, um auf die Veränderungen von einem Verzeichnisbaum zu reagieren.
TreeSelectionListener
Methoden, um auf die Selektionen in einem Verzeichnisbaum zu reagieren.
Tabelle B.77: Schnittstellen
Ausgewählte Klassen AncestorEvent
Ereignisse, wenn sich JComponent oder die Superklassen verändern.
ChangeEvent
Text-Veränderungsereignisse.
EventListenerList
Liste der Ereignis-Listener.
ListDataEvent
ListData-Ereignisse.
ListSelectionEvent
Ereignisse, wenn eine Listenselektion durchgeführt wird.
MenuEvent
Menü-Ereignisse.
Java 2 Kompendium
Tabelle B.78: Klassen
1015
Anhang B Tabelle B.78: Klassen (Forts.)
TableColumnModelEvent
Ereignisse bei Tabellenspalten-Veränderungen.
TableModelEvent
Ereignisse bei Tabellen-Veränderungen.
TreeExpansionEvent
Ereignisse bei Tabellen-Erweiterungen.
TreeModelEvent
Ereignisse bei Veränderungen im Verzeichnisbaum.
TreeSelectionEvent
Ereignisse bei Selektionen im Verzeichnisbaum.
B.2.46
javax.swing.undo
Hierbei (vormals java.awt.swing.undo) handelt es sich um ein Swing-Unterpaket (neu eingeführt im SDK 2) zur Unterstützung für Undo-Befehlen beim Editieren. Schnittstellen Tabelle B.79: Schnittstellen
StateEditable
Methoden für Objekte, deren Status Undo unterstützt.
UndoableEdit
Methoden zur Darstellung einer vollständigen Veränderung, die rückgängig gemacht werden kann.
Klassen Tabelle B.80: Klassen
AbstractUndoableEdit
Eigenschaften, die die UndoableEdit-Schnittstelle implementieren.
CompoundEdit
Eigenschaften, um einige kleinere Rückgängig-Schritte mit grö ß eren zu kombinieren.
StateEdit
Allgemeine Veränderungen für Objekte, die den Status verändern können.
UndoManager
Listener für rückgängig zu machende Ereignisse.
UndoableEditSupport
Unterstützung der Ereignisse von UndoableEditEvent.
B.2.47
Die CORBA-Pakete
Neben den bisher behandelten Paketen der SDK 2-Standard-API zählen noch die nachfolgenden Pakete zum SDK 2-Kern. Sie stellen die Funktionalitäten für die Zusammenarbeit zwischen Java und dem CORBA-Konzept bereit: org.omg.CORBA org.omg.CORBA_2_3 1016
Java 2 Kompendium
Die veralteten Elemente des Java-API 1.3
Anhang B
org.omg.CORBA_2_3.portable org.omg.CORBA.DynAnyPackage org.omg.CORBA.ORBPackage org.omg.CORBA.portable org.omg.CORBA.TypeCodePackage org.omg.CosNaming org.omg.CosNaming.NamingContextPackage org.omg.SendingContext org.omg.stub.java.rmi
Die Pakete org.omg.CORBA_2_3, org.omg.CORBA_2_3.portable, org.omg.SendingContext und org.omg.stub.java.rmi kamen im JDK 1.3 neu hinzu.
B.2.48
Nicht enthalten – das Servlets-API
Die vor dem SDK 2 zur Standard-API des JDK gehörenden Pakete javax.servlet und javax.servlet.http für die Realisierung von ServletFunktionalität sind in ein eigenständiges API ausgelagert. Das eigenständige Produkt – das Java Servlet Development Kit – wird wie das JDK frei von Sun zur Verfügung gestellt und kann von der Servlet-Produkt-Seite auf den Java-Software-Webseiten geladen werden (siehe dazu auch Kapitel 16).
B.3
Die veralteten Elemente des Java-API 1.3
Die nachfolgenden Schnittstellen, Klassen, Methoden, Konstruktoren und Felder werden mittlerweile von Sun als veraltet bzw. verworfen (deprecated) bezeichnet, werden aber dennoch in der 1.3-API mit aufgenommen, um die Kompatibilität mit den vorangegangenen Versionen sicherzustellen. Es gibt jedoch für fast jedes der veralteten Elemente mittlerweile neuere Lösungen oder die Funktionalität wird nicht mehr benötigt. Auch dazu finden Sie detailiertere Informationen in der API-Dokumention. Um die Veränderungen in der Java-API auf einen Blick zur Verfügung zu haben, folgt hier die Auflistung der als veraltet oder verworfen gekennzeichneten Elemente – die deprecated APIs. Um es noch einmal deutlich zu machen – die Verwendung dieser veralteten Elemente ist keinenfalls verboten (und in vielen Fällen sogar noch notwendig – beispielsweise für Applets, denn viele Browser unterstützten den 1.3Standard oder gar den 1.1-Standard von Java noch nicht). Eine als deprecated gekennzeichnete API ist eine Klasse oder ein Klassenbestandteil einer Vorgängerversion der aktuellen Java-Plattform, für die es in der neuen API eine bessere Lösung gibt und die – wenn es geht – nicht mehr verwendet werden soll.
Java 2 Kompendium
1017
Anhang B Hier folgt die Liste mit deprecated gekennzeichneten Elementen des 1.3-API (Final):
B.3.1
Klassen (deprecated)
javax.accessibility.AccessibleResourceBundle javax.swing.text.DefaultTextUI java.security.Identity java.security.cert package java.security.Principal. java.security.IdentityScope java.io.LineNumberInputStream java.rmi.server.LogStream java.rmi.server.Operation org.omg.CORBA.Principal org.omg.CORBA.PrincipalHolder java.security.Signer java.io.StringBufferInputStream javax.swing.text.TableView.TableCell
B.3.2
Interfaces (deprecated)
java.security.Certificate java.rmi.server.LoaderHandler java.rmi.registry.RegistryHandler java.rmi.server.RemoteCall java.rmi.server.Skeleton
B.3.3
Exceptions (deprecated)
java.rmi.RMISecurityException java.rmi.ServerRuntimeException java.rmi.server.SkeletonMismatchException java.rmi.server.SkeletonNotFoundException
B.3.4
Felder (deprecated)
javax.swing.JViewport.backingStore javax.swing.plaf.basic.BasicDesktopPaneUI.closeKey java.awt.Frame.CROSSHAIR_CURSOR java.awt.Frame.DEFAULT_CURSOR javax.swing.JRootPane.defaultPressAction javax.swing.JRootPane.defaultReleaseAction javax.swing.plaf.basic.BasicSplitPaneUI.dividerResizeToggleKey javax.swing.plaf.basic.BasicTabbedPaneUI.downKey
1018
Java 2 Kompendium
Die veralteten Elemente des Java-API 1.3
Anhang B
javax.swing.plaf.basic.BasicToolBarUI.downKey javax.swing.plaf.basic.BasicSplitPaneUI.downKey java.awt.Frame.E_RESIZE_CURSOR javax.swing.plaf.basic.BasicSplitPaneUI.endKey java.awt.Frame.HAND_CURSOR javax.swing.plaf.basic.BasicSplitPaneUI.homeKey java.net.HttpURLConnection.HTTP_SERVER_ERROR java.lang.SecurityManager.inCheck javax.swing.plaf.basic.BasicSplitPaneUI.keyboardDownRightListener javax.swing.plaf.basic.BasicSplitPaneUI.keyboardEndListener javax.swing.plaf.basic.BasicSplitPaneUI.keyboardHomeListener javax.swing.plaf.basic.BasicSplitPaneUI.keyboardResizeToggleListener javax.swing.plaf.basic.BasicSplitPaneUI.keyboardUpLeftListener javax.swing.plaf.basic.BasicTabbedPaneUI.leftKey javax.swing.plaf.basic.BasicToolBarUI.leftKey javax.swing.plaf.basic.BasicSplitPaneUI.leftKey javax.swing.plaf.basic.BasicDesktopPaneUI.maximizeKey javax.swing.plaf.basic.BasicDesktopPaneUI.minimizeKey java.awt.Frame.MOVE_CURSOR java.awt.Frame.N_RESIZE_CURSOR javax.swing.plaf.basic.BasicDesktopPaneUI.navigateKey javax.swing.plaf.basic.BasicDesktopPaneUI.navigateKey2 java.awt.Frame.NE_RESIZE_CURSOR java.awt.Frame.NW_RESIZE_CURSOR javax.swing.plaf.basic.BasicInternalFrameUI.openMenuKey java.awt.datatransfer.DataFlavor.plainTextFlavor getTransferData(DataFlavor.plainTextFlavor). javax.swing.text.html.FormView.RESET javax.swing.table.TableColumn.resizedPostingDisableCount javax.swing.plaf.basic.BasicTabbedPaneUI.rightKey javax.swing.plaf.basic.BasicToolBarUI.rightKey javax.swing.plaf.basic.BasicSplitPaneUI.rightKey java.awt.Frame.S_RESIZE_CURSOR java.awt.Frame.SE_RESIZE_CURSOR javax.swing.text.html.FormView.SUBMIT java.awt.Frame.SW_RESIZE_CURSOR java.awt.Frame.TEXT_CURSOR javax.swing.plaf.basic.BasicTabbedPaneUI.upKey javax.swing.plaf.basic.BasicToolBarUI.upKey javax.swing.plaf.basic.BasicSplitPaneUI.upKey java.awt.Frame.W_RESIZE_CURSOR java.awt.Frame.WAIT_CURSOR
B.3.5
Methoden (deprecated)
java.awt.Component.action(Event, Object) java.awt.List.addItem(String) java.awt.List.addItem(String, int) java.awt.CardLayout.addLayoutComponent(String, Component)
Java 2 Kompendium
1019
Anhang B java.awt.BorderLayout.addLayoutComponent(String, Component) java.awt.List.allowsMultipleSelections() java.lang.ThreadGroup.allowThreadSuspension(boolean) java.awt.TextArea.appendText(String) java.awt.Component.bounds() java.lang.SecurityManager.classDepth(String) java.lang.SecurityManager.classLoaderDepth() java.awt.List.clear() java.awt.image.renderable.RenderContext.concetenateTransform(AffineTransform) java.awt.Container.countComponents() java.awt.Menu.countItems() java.awt.List.countItems() java.awt.Choice.countItems() java.awt.MenuBar.countMenus() java.lang.Thread.countStackFrames() org.omg.CORBA.ORB.create_recursive_sequence_tc(int, int) javax.swing.plaf.basic.BasicSplitPaneUI.createKeyboardDownRightListener() javax.swing.plaf.basic.BasicSplitPaneUI.createKeyboardEndListener() javax.swing.plaf.basic.BasicSplitPaneUI.createKeyboardHomeListener() javax.swing.plaf.basic.BasicSplitPaneUI.createKeyboardResizeToggleListener() javax.swing.plaf.basic.BasicSplitPaneUI.createKeyboardUpLeftListener() javax.swing.JTable.createScrollPaneForTable(JTable) javax.swing.text.TableView.createTableCell(Element) java.lang.SecurityManager.currentClassLoader() java.lang.SecurityManager.currentLoadedClass() java.lang.ClassLoader.defineClass(byte[], int, int) java.awt.List.delItem(int) java.awt.List.delItems(int, int) java.awt.Component.deliverEvent(Event) java.awt.Container.deliverEvent(Event) java.awt.Component.disable() java.awt.MenuItem.disable() javax.swing.table.TableColumn.disableResizedPosting() java.rmi.server.Skeleton.dispatch(Remote, RemoteCall, int, long) java.rmi.server.RemoteCall.done() java.rmi.server.RemoteRef.done(RemoteCall) java.awt.Component.enable() java.awt.MenuItem.enable() java.awt.Component.enable(boolean) java.awt.MenuItem.enable(boolean) javax.swing.table.TableColumn.enableResizedPosting() java.security.SignatureSpi.engineGetParameter(String) java.security.SignatureSpi.engineSetParameter(String, Object) java.awt.datatransfer.DataFlavor.equals(String) org.omg.CORBA.ServerRequest.except(Any) java.rmi.server.RemoteCall.executeCall() org.omg.CORBA.Any.extract_Principal() org.omg.CORBA.ORB.get_current() java.security.Security.getAlgorithmProperty(String, String) java.sql.CallableStatement.getBigDecimal(int, int)
1020
Java 2 Kompendium
Die veralteten Elemente des Java-API 1.3
Anhang B
java.sql.ResultSet.getBigDecimal(int, int) java.sql.ResultSet.getBigDecimal(String, int) java.awt.Polygon.getBoundingBox() java.lang.String.getBytes(int, int, byte[], int) java.awt.Graphics.getClipRect() javax.swing.JPopupMenu.getComponentAtIndex(int) javax.swing.JMenuBar.getComponentAtIndex(int) java.awt.CheckboxGroup.getCurrent() java.awt.Frame.getCursorType() java.sql.Time.getDate() java.util.Date.getDate() java.sql.Time.getDay() java.util.Date.getDay() java.net.URLConnection.getDefaultRequestProperty(String) java.rmi.server.LogStream.getDefaultStream() javax.swing.plaf.basic.BasicSplitPaneUI.getDividerBorderSize() java.lang.System.getenv(String) java.awt.Toolkit.getFontList() javax.swing.text.LabelView.getFontMetrics() java.awt.Toolkit.getFontMetrics(Font) java.awt.Toolkit.getFontPeer(String, int) java.sql.Date.getHours() java.util.Date.getHours() java.lang.SecurityManager.getInCheck() java.rmi.server.RemoteCall.getInputStream() javax.swing.KeyStroke.getKeyStroke(char, boolean) javax.swing.AbstractButton.getLabel() java.awt.Scrollbar.getLineIncrement() java.lang.Runtime.getLocalizedInputStream(InputStream) java.lang.Runtime.getLocalizedOutputStream(OutputStream) java.sql.DriverManager.getLogStream() java.awt.FontMetrics.getMaxDecent() javax.swing.JInternalFrame.getMenuBar() javax.swing.JRootPane.getMenuBar() java.sql.Date.getMinutes() java.util.Date.getMinutes() java.sql.Time.getMonth() java.util.Date.getMonth() java.rmi.server.Operation.getOperation() java.rmi.server.Skeleton.getOperations() java.rmi.server.RemoteCall.getOutputStream() java.rmi.server.LogStream.getOutputStream() java.awt.Scrollbar.getPageIncrement() java.security.Signature.getParameter(String) java.awt.Component.getPeer() java.awt.MenuComponent.getPeer() java.awt.Font.getPeer() java.rmi.server.RemoteCall.getResultStream(boolean) java.sql.Date.getSeconds() java.util.Date.getSeconds()
Java 2 Kompendium
1021
Anhang B java.rmi.server.RMIClassLoader.getSecurityContext(ClassLoader) java.rmi.server.LoaderHandler.getSecurityContext(ClassLoader) javax.swing.JPasswordField.getText() javax.swing.JPasswordField.getText(int, int) java.util.Date.getTimezoneOffset() Calendar.get(Calendar.DST_OFFSET). java.net.MulticastSocket.getTTL() java.net.DatagramSocketImpl.getTTL() java.sql.ResultSet.getUnicodeStream(int) java.sql.ResultSet.getUnicodeStream(String) javax.swing.ScrollPaneLayout.getViewportBorderBounds(JScrollPane) java.awt.Scrollbar.getVisible() java.sql.Time.getYear() java.util.Date.getYear() java.awt.Component.gotFocus(Event, Object) java.awt.Component.handleEvent(Event) java.awt.Component.hide() javax.swing.JComponent.hide() java.lang.SecurityManager.inClass(String) java.lang.SecurityManager.inClassLoader() org.omg.CORBA.Any.insert_Principal(Principal) javax.swing.text.html.HTMLEditorKit.InsertHTMLTextAction.insertAtBoundry(JEdi torPane, HTMLDocument, int, Element, String, HTML.Tag, HTML.Tag) java.awt.TextArea.insertText(String, int) java.awt.Container.insets() java.awt.Component.inside(int, int) java.awt.Polygon.inside(int, int) java.awt.Rectangle.inside(int, int) java.rmi.server.RemoteRef.invoke(RemoteCall) javax.swing.JViewport.isBackingStoreEnabled() java.lang.Character.isJavaLetter(char) java.lang.Character.isJavaLetterOrDigit(char) java.awt.List.isSelected(int) java.lang.Character.isSpace(char) java.rmi.dgc.VMID.isUnique() java.awt.Component.keyDown(Event, int) java.awt.Component.keyUp(Event, int) java.awt.Component.layout() java.awt.Container.layout() java.awt.ScrollPane.layout() java.rmi.server.RMIClassLoader.loadClass(String) java.rmi.server.LoaderHandler.loadClass(String) java.rmi.server.LoaderHandler.loadClass(URL, String) java.awt.Component.locate(int, int) java.awt.Container.locate(int, int) java.awt.Component.location() java.rmi.server.LogStream.log(String) java.awt.Component.lostFocus(Event, Object) java.awt.Component.minimumSize() java.awt.Container.minimumSize()
1022
Java 2 Kompendium
Die veralteten Elemente des Java-API 1.3
Anhang B
java.awt.List.minimumSize() java.awt.TextField.minimumSize() java.awt.TextArea.minimumSize() java.awt.List.minimumSize(int) java.awt.TextField.minimumSize(int) java.awt.TextArea.minimumSize(int, int) javax.swing.text.View.modelToView(int, Shape) java.awt.Component.mouseDown(Event, int, int) java.awt.Component.mouseDrag(Event, int, int) java.awt.Component.mouseEnter(Event, int, int) java.awt.Component.mouseExit(Event, int, int) java.awt.Component.mouseMove(Event, int, int) java.awt.Component.mouseUp(Event, int, int) java.awt.Component.move(int, int) java.awt.Rectangle.move(int, int) org.omg.CORBA.Principal.name() org.omg.CORBA.Principal.name(byte[]) java.rmi.server.RemoteRef.newCall(RemoteObject, Operation[], int, long) java.awt.Component.nextFocus() java.awt.datatransfer.DataFlavor.normalizeMimeType(String) java.awt.datatransfer.DataFlavor.normalizeMimeTypeParameter(String, String) org.omg.CORBA.ServerRequest.op_name() org.omg.CORBA.ServerRequest.params(NVList) java.util.Date.parse(String) java.rmi.server.LogStream.parseLevel(String) java.awt.Component.postEvent(Event) java.awt.MenuComponent.postEvent(Event) java.awt.MenuContainer.postEvent(Event) java.awt.Window.postEvent(Event) java.awt.image.renderable.RenderContext.preConcetenateTransform(AffineTransfo rm) java.awt.Component.preferredSize() java.awt.Container.preferredSize() java.awt.List.preferredSize() java.awt.TextField.preferredSize() java.awt.TextArea.preferredSize() java.awt.List.preferredSize(int) java.awt.TextField.preferredSize(int) java.awt.TextArea.preferredSize(int, int) org.omg.CORBA.portable.InputStream.read_Principal() java.io.ObjectInputStream.readLine() java.io.DataInputStream.readLine() java.rmi.registry.RegistryHandler.registryImpl(int) java.rmi.registry.RegistryHandler.registryStub(String, int) java.rmi.server.RemoteCall.releaseInputStream() java.rmi.server.RemoteCall.releaseOutputStream() java.awt.TextArea.replaceText(String, int, int) java.awt.Component.reshape(int, int, int, int) java.awt.Rectangle.reshape(int, int, int, int) java.awt.Component.resize(Dimension)
Java 2 Kompendium
1023
Anhang B java.awt.Component.resize(int, int) java.awt.Rectangle.resize(int, int) org.omg.CORBA.ServerRequest.result(Any) java.lang.ThreadGroup.resume() java.lang.Thread.resume() java.lang.System.runFinalizersOnExit(boolean) java.lang.Runtime.runFinalizersOnExit(boolean) java.util.Properties.save(OutputStream, String) javax.swing.JViewport.setBackingStoreEnabled(boolean) java.awt.CheckboxGroup.setCurrent(Checkbox) java.awt.Frame.setCursor(int) java.sql.Time.setDate(int) java.util.Date.setDate(int) java.net.URLConnection.setDefaultRequestProperty(String, String) java.rmi.server.LogStream.setDefaultStream(PrintStream) java.awt.TextField.setEchoCharacter(char) java.sql.Date.setHours(int) java.util.Date.setHours(int) javax.swing.AbstractButton.setLabel(String) java.awt.Scrollbar.setLineIncrement(int) java.sql.DriverManager.setLogStream(PrintStream) javax.swing.JInternalFrame.setMenuBar(JMenuBar) javax.swing.JRootPane.setMenuBar(JMenuBar) java.sql.Date.setMinutes(int) java.util.Date.setMinutes(int) java.sql.Time.setMonth(int) java.util.Date.setMonth(int) java.awt.List.setMultipleSelections(boolean) java.rmi.server.LogStream.setOutputStream(OutputStream) java.awt.Scrollbar.setPageIncrement(int) java.security.Signature.setParameter(String, Object) java.rmi.server.RemoteStub.setRef(RemoteStub, RemoteRef) java.sql.Date.setSeconds(int) java.util.Date.setSeconds(int) java.net.MulticastSocket.setTTL(byte) java.net.DatagramSocketImpl.setTTL(byte) use setTimeToLive instead. java.sql.PreparedStatement.setUnicodeStream(int, InputStream, int) java.net.URLStreamHandler.setURL(URL, String, String, int, String, String) java.sql.Time.setYear(int) java.util.Date.setYear(int) java.awt.Component.show() java.awt.Component.show(boolean) java.awt.Component.size() javax.swing.JTable.sizeColumnsToFit(boolean) java.lang.ThreadGroup.stop() java.lang.Thread.stop() java.lang.Thread.stop(Throwable) java.lang.ThreadGroup.suspend() java.lang.Thread.suspend()
1024
Java 2 Kompendium
HTML-Elemente und -Attribute
Anhang B
java.util.Date.toGMTString() java.util.Date.toLocaleString() java.rmi.server.Operation.toString() java.rmi.server.LogStream.toString() java.io.ByteArrayOutputStream.toString(int) java.util.Date.UTC(int, int, int, int, int, int) javax.swing.text.View.viewToModel(float, float, Shape) org.omg.CORBA.portable.OutputStream.write_Principal(Principal) java.rmi.server.LogStream.write(byte[], int, int) java.rmi.server.LogStream.write(int)
B.3.6
Constructors (deprecated)
java.sql.Date(int, int, int) java.util.Date(int, int, int) java.util.Date(int, int, int, int, int) java.util.Date(int, int, int, int, int, int) java.util.Date(String) java.rmi.server.Operation(String) java.rmi.RMISecurityException(String) java.rmi.RMISecurityException(String, String) java.rmi.ServerRuntimeException(String, Exception) java.rmi.server.SkeletonMismatchException(String) java.net.Socket(InetAddress, int, boolean) java.net.Socket(String, int, boolean) java.io.StreamTokenizer(InputStream) java.lang.String(byte[], int) java.lang.String(byte[], int, int, int) org.omg.CORBA.TCKind(int) java.sql.Time(int, int, int) java.sql.Timestamp(int, int, int, int, int, int, int)
B.4
HTML-Elemente und -Attribute
HTML 4.0 beinhaltet eine umfangreiche Anzahl von offiziellen Befehlen und noch mehr Attribute. Hier finden Sie die Tags und zugehörige Attribute.
B.4.1
HTML-Tags
Nachfolgend sollen alphabetisch sämtliche Elemente, die zum offiziellen HTML 4.0-Sprachstandard gehören, aufgelistet werden. Die Auflistung beruht auf der offiziellen Veröffentlichung des W3C (http://www.w3.org/TR/ REC-html40/index/elements.html).
Java 2 Kompendium
1025
Anhang B Wenn im Start- und Ende-Tag keine Angaben stehen, werden die Tags jeweils gefordert. Dabei gilt, dass es Situationen geben kann, wo das EndeTag zwar gefordert wird, es aber in der Praxis ohne negative Auswirkung weggelassen werden kann. Umgekehrt gilt: Sofern ein Ende-Tag verboten ist, gibt es keinen Container, der dem Start-Tag nachfolgenden Inhalt enthalten kann. Ein solches Element, wo das Ende-Tag verboten ist, kann aber ohne Probleme mit einem fiktiven Ende-Tag ausgestattet werden (etwa aus dokumentarischen Gründen). Das Ende-Tag wird keinen Fehler erzeugen – er wird durch das Prinzip der Fehlertoleranz einfach ignoriert. Als deprecated gekennzeichnete Elemente gelten als veraltet. Dafür gibt es im Rahmen des neuen Sprachstandards andere Elemente, die statt dessen verwendet werden sollen. Die Verwendung ist aber keinenfalls verboten. Viele der Elemente können durch Attribute erweitert werden. Die Tabelle mit den Attributen finden Sie direkt anschließend. Tabelle B.81: HTML-Tags
1026
Tag
Beschreibung
A
Anker.
ABBR
Abkürzung (z.B., WWW, HTTP, USA, RJS usw.)
ACRONYM
Acronym.
ADDRESS
Adressangabe für Informationen über den Autor.
APPLET
Einbindung eines Java-Applets. Deprecated!
AREA
Clientseitiger Imagemap-Bereich. Kein Ende-Tag vorgesehen.
B
Textstil fett.
BASE
Basis-URL des Dokuments. Kein Ende-Tag vorgesehen.
BASEFONT
Basisschriftgrö ß e. Kein Ende-Tag vorgesehen. Deprecated.
BDO
Deaktivierung der Standardausrichtung des Textes.
BIG
Textstil groß.
BLOCKQUOTE
Zitat (lang).
BODY
Dokumentenkörper.
BR
Zeilenumbruch. Kein Ende-Tag vorgesehen.
BUTTON
Push-Button.
CAPTION
Tabellenbeschriftung.
Java 2 Kompendium
HTML-Elemente und -Attribute
Tag
Beschreibung
CENTER
Zentrieren. Deprecated.
CITE
Zitat.
CODE
Textstil für Computercode.
COL
Tabellenspalte. Kein Ende-Tag vorgesehen.
COLGROUP
Tabellenspaltengruppe. Optionales Ende-Tag.
DD
Definitionsbeschreibung. Optionales Ende-Tag.
DEL
Gelöschter Text.
DFN
Instanzdefinition.
DIR
Verzeichnisliste. Deprecated.
DIV
Allgemeiner Stilcontainer zur Gestaltung (Ausrichtung) von Elementen.
DL
Definitionsliste.
DT
Definitionsterm. Optionales Ende-Tag.
EM
Textstil für eine Betonung.
FIELDSET
Formularkontrollgruppe. Gruppiert gleichartige Steuerelemente.
FONT
Lokale Schriftveränderung. Deprecated.
FORM
Formular.
FRAME
Frame. Kein Ende-Tag vorgesehen.
FRAMESET
Die Oberstruktur einer Framegruppe.
H1
Überschrift der Ordung 1.
H2
Überschrift der Ordung 2.
H3
Überschrift der Ordung 3.
H4
Überschrift der Ordung 4.
H5
Überschrift der Ordung 5.
H6
Überschrift der Ordung 6.
HEAD
Dokumenten-Header (Kopfbereich).
HR
Horizontale Trennlinie. Kein Ende-Tag vorgesehen.
HTML
Äußerer Container einer Webseite.
Java 2 Kompendium
Anhang B Tabelle B.81: HTML-Tags (Forts.)
1027
Anhang B Tabelle B.81: HTML-Tags (Forts.)
1028
Tag
Beschreibung
I
Textstil italic (kursiv).
IFRAME
Innenliegendes Unterfenster.
IMG
Bildreferenz. Kein Ende-Tag vorgesehen.
INPUT
Formulareingabe. Kein Ende-Tag vorgesehen.
INS
Eingefügter Text.
ISINDEX
Einzeiliges Prompt (Eingabeaufforderung). Kein Ende-Tag vorgesehen. Deprecated.
KBD
Stil für Text, der von dem Anwender eingegeben wird.
LABEL
Beschriftungstext für ein Formularfeld.
LEGEND
Fieldset-Legende.
LI
Definition eines Listenelements. Optionales Ende-Tag.
LINK
Ein Medien-unabhängiger Link. Kein Ende-Tag vorgesehen.
MAP
Clientseitige Imagemap.
MENU
Menüliste. Deprecated.
META
Allgemeine Metainformationen. Kein Ende-Tag vorgesehen.
NOFRAMES
Alternativ angezeigter Inhalt, wenn keine Frames angezeigt werden.
NOSCRIPT
Alternativ angezeigter Inhalt, wenn keine Scripts ausgeführt und angezeigt werden.
OBJECT
Allgemeines Einbettungsobjekt.
OL
Sortierte Liste.
OPTGROUP
Optionsgruppe.
OPTION
Selektierbare Auswahl in einem Formular. Optionales Ende-Tag.
P
Absatz. Optionales Ende-Tag.
PARAM
Initialisierungswert für ein Objekt. Kein Ende-Tag vorgesehen.
PRE
Vorformatierter Text.
Q
Kurzes Zitat in einer Zeile.
Java 2 Kompendium
HTML-Elemente und -Attribute
Tag
Beschreibung
S
Textstil durchgestrichen. Deprecated.
SAMP
Textformatierung für die Darstellung von Beispielen.
SCRIPT
Einbindung von Scriptanweisungen.
SELECT
Auswahlmöglichkeiten in einem Formular.
SMALL
Textstil klein.
SPAN
Allgemeiner Sprach- und Stilcontainer.
STRIKE
Textstil durchgestrichen. Deprecated.
STRONG
Textstil starke Hervorhebung.
STYLE
Einbindung von Stilinformationen (Style Sheets).
SUB
Textstil tiefstellen.
SUP
Textstil hochstellen.
TABLE
Tabelle.
TBODY
Tabellenkörper. Nach offizieller W3C-Aussage ist sowohl die Angabe optional als auch das Ende-Tag.
TD
Tabellendatenzelle. Optionales Ende-Tag.
TEXTAREA
Mehrzeiliges Textfeld in einem Formular.
TFOOT
Angabe eines Fußbereichs bei Tabellen. Optionales Ende-Tag.
TH
Tabellenkopfzellen. Optionales Ende-Tag.
THEAD
Angabe eines Kopfbereichs bei Tabellen. Optionales Ende-Tag.
TITLE
Dokumententitel.
TR
Tabellenreihe. Optionales Ende-Tag.
TT
Textstil nichtproportional.
U
Textstil unterstrichen. Deprecated.
UL
Unsortierte Liste.
VAR
Instanz einer Variablen oder eines Programmarguments.
Java 2 Kompendium
Anhang B Tabelle B.81: HTML-Tags (Forts.)
1029
Anhang B
B.4.2
Die HTML 4.0-Attribute
Viele der Tags des HTML 4.0-Sprachstandards können durch Attribute erweitert werden, die sie genauer spezifizieren oder gar erst sinnvoll machen. Die nachfolgende Auflistung gibt alphabetisch sämtliche Attribute, die zum dem HTML 4.0-Sprachstandard gehören. Viele Attribute werden mehrfach angegeben. Dies ist deshalb zwingend, weil sich ein identisch benanntes Attribut verschieden auswirken kann. Zusätzlich werden in den Spalten nach dem Attribut Angaben zum Typ des Attributs, ob das Attribut optional eingesetzt werden kann, ob es bei den zugeordneten Elementen gefordert wird und ob es deprecated ist, gemacht. Auch dies kann sich bei identisch bezeichneten Attributen unterscheiden. Sofern sich Attribute bei verschiedenen HTML-Befehlen gleich auswirken, werden die Elemente zusammengefasst. Die Auflistung enthält die vollständige Liste der Attribute des HTML 4.0Standards und basiert auf der offiziell vom W3C (http://www.w3.org/TR/REChtml40/index/attributes.html) ausgegebenen Liste. Beachten Sie, dass nicht alle der Attribute in den verschiedenen Browserversionen (auch den aktuellen) umgesetzt sind. Dies gilt insbesondere für die Event-Handler, die hauptsächlich der Netscape Navigator nur sehr eingeschränkt unterstützt. Tabelle B.82: HTML-Attribute
Attribut
Beschreibung
abbr
Anwendung bei: TD, TH Typ: %Text; Verwendung: #OPTIONAL Abkürzung für die Kopfzelle einer Tabelle. accept-charset
Anwendung bei: FORM Typ: %Charsets; Verwendung: #OPTIONAL Liste der unterstützten Zeichensätze bei einem Formular.
1030
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
accept
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: INPUT Typ: %ContentTypes; Verwendung: #OPTIONAL Liste der unterstützten MIME-Typen für den DateiUpload. accesskey
Anwendung bei: A, AREA, BUTTON, INPUT, LABEL, LEGEND, TEXTAREA
Typ: %Character; Verwendung: #OPTIONAL Zeichen für den Zugriff auf ein Element (Hotkey). action
Anwendung bei: FORM Typ: %URL; Verwendung: #GEFORDERT Serverseitige Formularbehandlung align
Anwendung bei: CAPTION Typ: %CAlign; Verwendung: #OPTIONAL Deprecated Ausrichtung einer Beschriftung relativ zu einer Tabelle. align
Anwendung bei: APPLET, IFRAME, IMG, INPUT, OBJECT Typ: %IAlign; Verwendung: #OPTIONAL Deprecated Vertikale oder horizontale Ausrichtung der Position eines Objekts in einer Webseite. Java 2 Kompendium
1031
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
align
Anwendung bei: LEGEND Typ: %LAlign; Verwendung: #OPTIONAL Deprecated Relative Angabe zu einem Fieldset. align
Anwendung bei: TABLE Typ: %TAlign; Verwendung: #OPTIONAL Deprecated Position einer Tabelle relativ zum Anzeigefenster im Browser. align
Anwendung bei: HR Typ: (left | center | right) Verwendung: #OPTIONAL Deprecated Ausrichtung der Überschrift. align
Anwendung bei: DIV, H1 – H6, P
Typ: (left | center | right | justify) Verwendung: #OPTIONAL Deprecated Ausrichtung von Elemenen.
1032
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
align
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR
Typ: (left | center | right | justify | char) Verwendung: #OPTIONAL Ausrichtungsangaben bei einer Tabelle. alink
Anwendung bei: BODY Typ: %Color; Verwendung: #OPTIONAL Deprecated Farbe eines besuchten Links. alt
Anwendung bei: APPLET Typ: %Text; Verwendung: #OPTIONAL Deprecated Alternative Kurzbeschreibung. alt
Anwendung bei: AREA, IMG Typ: %Text; Verwendung: #GEFORDERT Alternative Kurzbeschreibung. alt
Anwendung bei: INPUT Typ: CDATA Verwendung: #OPTIONAL Alternative Kurzbeschreibung.
Java 2 Kompendium
1033
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
archive
Anwendung bei: OBJECT Typ: %URL; Verwendung: #OPTIONAL Durch Leerzeichen getrennte Archivliste. archive
Anwendung bei: APPLET Typ: CDATA Verwendung: #OPTIONAL Deprecated Durch Komma getrennte Archivliste. axis
Anwendung bei: TD, TH Typ: CDATA Verwendung: #OPTIONAL Namengruppen von verbundenen Kopfzeilen. background
Anwendung bei: BODY Typ: %URL; Verwendung: #OPTIONAL Deprecated Hintergrund einer Webseite. bgcolor
Anwendung bei: TABLE Typ: %Color; Verwendung: #OPTIONAL Deprecated Hintergrundfarbe für alle Zellen einer Tabelle.
1034
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
bgcolor
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: TR Typ: %Color; Verwendung: #OPTIONAL Deprecated Hintergrundfarbe für eine Zeile einer Tabelle. bgcolor
Anwendung bei: TD, TH Typ: %Color; Verwendung: #OPTIONAL Deprecated Hintergrundfarbe für genau diese Zelle einer Tabelle. bgcolor
Anwendung bei: BODY Typ: %Color; Verwendung: #OPTIONAL Deprecated Hintergrundfarbe des Dokuments. border
Anwendung bei: IMG, OBJECT Typ: %Length; Verwendung: #OPTIONAL Deprecated Wenn ein Bild oder ein anderes Objekt als ein Link fungiert, die Angabe, ob es umrandet dargestellt wird. border
Anwendung bei: TABLE Typ: %Pixels;
Java 2 Kompendium
1035
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung Verwendung: #OPTIONAL Die Angabe, wie dick der Rahmen um eine Tabelle ist.
cellpadding
Anwendung bei: TABLE Typ: %Length; Verwendung: #OPTIONAL Platzangaben innerhalb der Zellen einer Tabelle. cellspacing
Anwendung bei: TABLE Typ: %Length; Verwendung: #OPTIONAL Raum zwischen Zellen einer Tabelle. char
Anwendung bei: COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR
Typ: %Character; Verwendung: #OPTIONAL Anordnungszeichen, z.B. char=':'. charoff
Anwendung bei: COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR
Typ: %Length; Verwendung: #OPTIONAL Offset für das Anordnungszeichen. charset
Anwendung bei: A, LINK, SCRIPT Typ: %Charset; Verwendung: #OPTIONAL Zeichenverschlüsselung der verbundenen Ressource.
1036
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
checked
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: INPUT Typ: (checked) Verwendung: #OPTIONAL Angabe, ob ausgewählt oder nicht bei Radiobutton und Checkboxen innerhalb eines Formulars. cite
Anwendung bei: BLOCKQUOTE, Q Typ: %URL; Verwendung: #OPTIONAL URL für ein Dokument mit Quelltext oder eine Mitteilung. cite
Anwendung bei: DEL, INS Typ: %URL; Verwendung: #OPTIONAL Eine allgemeine Information über den Grund für den Wechsel der letzten Dokumentenversion. class
Anwendung bei allen Tags bis auf: BASE, BASEFONT, HEAD, HTML, META, PARAM, SCRIPT, STYLE, TITLE Typ: CDATA Verwendung: #OPTIONAL Durch Leerraum getrennte Liste von Klassen. classid
Anwendung bei: OBJECT Typ: %URL; Verwendung: #OPTIONAL Identifiziert eine Implementation.
Java 2 Kompendium
1037
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
clear
Anwendung bei: BR Typ: (left | all | right | none) Default: none Deprecated Kontrolle des Textflusses. code
Anwendung bei: APPLET Typ: CDATA Verwendung: #OPTIONAL Deprecated Die Klassendatei eines Applets. codebase
Anwendung bei: OBJECT Typ: %URL; Verwendung: #OPTIONAL Die Angabe, wo sich ein Objekt befindet. codebase
Anwendung bei: APPLET Typ: %URL; Verwendung: #OPTIONAL Deprecated Die Angabe, wo sich ein Applet befindet codetype
Anwendung bei: OBJECT Typ: %ContentType; Verwendung: #OPTIONAL Typ des Codes.
1038
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
color
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: BASEFONT, FONT Typ: %Color; Verwendung: #OPTIONAL Deprecated Textfarbe. cols
Anwendung bei: FRAMESET Typ: %MultiLengths; Verwendung: #OPTIONAL Eine Liste von Längenangaben bei einem Frameset. cols
Anwendung bei: TEXTAREA Typ: NUMBER Verwendung: #GEFORDERT Anzahl von Spalten. colspan
Anwendung bei: TD, TH Typ: NUMBER Verwendung: Angabe grö ß er 0 Anzahl von Spalten, die zu einem Colspan zusammengefasst werden. compact
Anwendung bei: DIR, MENU Typ: (compact) Verwendung: #OPTIONAL Deprecated Reduziert den Platz zwischen Zeichen.
Java 2 Kompendium
1039
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
compact
Anwendung bei: DL, OL, UL Typ: (compact) Verwendung: #OPTIONAL Deprecated Reduziert den Platz zwischen Zeichen. content
Anwendung bei: META Typ: CDATA Verwendung: #GEFORDERT Mit dem <META>-Tag assoziierte Information. coords
Anwendung bei: AREA Typ: %Coords; Verwendung: #OPTIONAL Durch Komma getrennte Liste von Koordinatenangaben. coords
Anwendung bei: A Typ: %Coords; Verwendung: #OPTIONAL Durch Komma getrennte Liste von Koordinatenangaben, die bei clientseitigen Imagemaps verwendet werden. data
Anwendung bei: OBJECT Typ: %URL; Verwendung: #OPTIONAL Referenz auf die Objektdaten.
1040
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
datetime
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: DEL, INS Typ: %Datetime; Verwendung: #OPTIONAL Datum und Uhrzeit einer Veränderung. declare
Anwendung bei: OBJECT Typ: (declare) Verwendung: #OPTIONAL Möglichkeit, ein Objekt zu deklarieren, aber noch nicht zu instanzieren. defer
Anwendung bei: SCRIPT Typ: (defer) Verwendung: #OPTIONAL Verzögern der Ausführung eines Scripts. dir
Anwendung bei allen Tags bis auf: APPLET, BASE, BASEFONT, BDO, BR, FRAME, FRAMESET, HR, IFRAME, PARAM, SCRIPT
Typ: (ltr | rtl) Verwendung: #OPTIONAL Fließrichtung für gewöhnlichen Text (von rechts nach links oder links nach rechts). dir
Anwendung bei: BDO Typ: (ltr | rtl) Verwendung: #GEFORDERT Fließrichtung für gewöhnlichen Text (von rechts nach links oder links nach rechts).
Java 2 Kompendium
1041
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
disabled
Anwendung bei: BUTTON, INPUT, OPTGROUP, OPTION, SELECT, TEXTAREA Typ: (disabled) Verwendung: #OPTIONAL Die Angabe, dass das Element in diesem Kontext nicht aktivierbar ist. enctype
Anwendung bei: FORM Typ: %ContentType; Verwendung: »application/x-www- form-urlencoded" face
Anwendung bei: BASEFONT, FONT Typ: CDATA Verwendung: #OPTIONAL Deprecated Durch Komma getrennte Liste von Schriftnamen. for
Anwendung bei: LABEL Typ: IDREF Verwendung: #OPTIONAL Der ID-Wert eines auszuwählenden Feldes. frame
Anwendung bei: TABLE Typ: %TFrame; Verwendung: #OPTIONAL Angabe, welcher Teil eines Frames ausgegeben werden soll.
1042
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
frameborder
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: FRAME, IFRAME Typ: (1 | 0) Gibt an, ob ein Frame einen Rahmen hat oder nicht. headers
Anwendung bei: TD, TH Typ: IDREFS Verwendung: #OPTIONAL Liste von IDs von Kopfzellen. height
Anwendung bei: IFRAME Typ: %Length; Verwendung: #OPTIONAL Framehöhe. height
Anwendung bei: IMG, OBJECT Typ: %Length; Verwendung: #OPTIONAL Explizite Höhenangabe für ein Bild oder Objekt. Überschreibt die natürliche Höhe. height
Anwendung bei: APPLET Typ: %Length; Verwendung: #GEFORDERT Deprecated Initialisierunghöhe eines Applets.
Java 2 Kompendium
1043
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
height
Anwendung bei: TD, TH Typ: %Pixels; Verwendung: #OPTIONAL Deprecated Höhe einer Zelle. href
Anwendung bei: A, AREA, LINK Typ: %URL; Verwendung: #OPTIONAL URL zu der gelinkten Ressource. href
Anwendung bei: BASE Typ: %URL; Verwendung: #OPTIONAL URL, die als Basis-URL fungiert. hreflang
Anwendung bei: A, LINK Typ: %LanguageCode; Verwendung: #OPTIONAL Sprachcode. hspace
Anwendung bei: APPLET, IMG, OBJECT Typ: %Pixels; Verwendung: #OPTIONAL Deprecated Horizontale Abstandsangabe.
1044
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
http-equiv
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: META Typ: NAME Verwendung: #OPTIONAL HTTP-Antwort auf den den Header-Namen. id
Anwendung bei allen Tags bis auf: BASE, HEAD, HTML, META, SCRIPT, STYLE, TITLE ID
Typ: NAME Verwendung: #OPTIONAL Dokumentenweit eindeutige ID. ismap
Anwendung bei: IMG Typ: (ismap) Verwendung: #OPTIONAL Verwendung des Bildes als serverseitige Imagemap. label
Anwendung bei: OPTION Typ: %Text; Verwendung: #OPTIONAL Eine Beschriftung für die Verwendung in hierarchischen Menüs. label
Anwendung bei: OPTGROUP Typ: %Text; Verwendung: #GEFORDERT Eine Beschriftung für die Verwendung in hierarchischen Menüs.
Java 2 Kompendium
1045
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
lang
Anwendung bei allen Tags bis auf: APPLET, BASE, BASEFONT, BR, FRAME, FRAMESET, HR, IFRAME, PARAM, SCRIPT
Typ: %LanguageCode; Verwendung: #OPTIONAL Typ: Sprachcode. language
Anwendung bei: SCRIPT Typ: CDATA Verwendung: #OPTIONAL Deprecated Name der Scriptsprache. link
Anwendung bei: BODY Typ: %Color; Verwendung: #OPTIONAL Deprecated Farbe der Links. longdesc
Anwendung bei: IMG Typ: %URL; Verwendung: #OPTIONAL Link zu einer langen Beschreibung. longdesc
Anwendung bei: FRAME, IFRAME Typ: %URL; Verwendung: #OPTIONAL Link zu einer langen Beschreibung.
1046
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
marginheight
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: FRAME, IFRAME Typ: %Pixels; Verwendung: #OPTIONAL Randhöhe in Pixel. marginwidth
Anwendung bei: FRAME, IFRAME Typ: %Pixels; Verwendung: #OPTIONAL Randbreite in Pixel. maxlength
Anwendung bei: INPUT Typ: NUMBER Verwendung: #OPTIONAL Maximale Anzahl von Zeichen in einem Textfeld. media
Anwendung bei: STYLE Typ: %MediaDesc; Verwendung: #OPTIONAL Angabe des angegebenen Medientyps. media
Anwendung bei: LINK Typ: %MediaDesc; Verwendung: #OPTIONAL Angabe des angegebenen Medientyps für Rendering auf diesem Media-Element.
Java 2 Kompendium
1047
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
method
Anwendung bei: FORM Typ: (GET | POST) Verwendung: #OPTIONAL Defaulteinstellung: GET HTTP-Methode zur Anwendung bei der Übertragung eines Formulars. multiple
Anwendung bei: SELECT Typ: (multiple) Verwendung: #OPTIONAL Angabe, ob eine Mehrfachauswahl bei einer Selektionsliste in einem Formular erlaubt ist. Defaulteinstellung ist Einfachauswahl. name
Anwendung bei: BUTTON, TEXTAREA Typ: CDATA Verwendung: #OPTIONAL Name eines Elements. Es kann bei einer Zuweisung über diesen Namen von deren Strukturen (etwa Scripten) angesprochen werden. name
Anwendung bei: APPLET Typ: CDATA Verwendung: #OPTIONAL Deprecated Name eines Applets. Applets können sich über den Namen identifizieren.
1048
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
name
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: SELECT Typ: CDATA Verwendung: #OPTIONAL Feldname. name
Anwendung bei: FRAME, IFRAME Typ: CDATA Verwendung: #OPTIONAL Name eines Frames. name
Anwendung bei: A Typ: CDATA Verwendung: #OPTIONAL Benennung eines Links. name
Anwendung bei: INPUT, OBJECT Typ: CDATA Verwendung: #OPTIONAL Name im Rahmen eines Formulars. name
Anwendung bei: MAP Typ: CDATA Verwendung: #GEFORDERT Name zur Referenzierung durch eine Usemap.
Java 2 Kompendium
1049
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
name
Anwendung bei: PARAM Typ: CDATA Verwendung: #GEFORDERT Eigenschaftenname. name
Anwendung bei: META Typ: NAME Verwendung: #OPTIONAL Name einer Meta-Information. nohref
Anwendung bei: AREA Typ: (nohref) Verwendung: #OPTIONAL Angabe, dass innerhalb diese Region keine Aktion stattfindet. noresize
Anwendung bei: FRAME Typ: (noresize) Verwendung: #OPTIONAL Angabe, ob ein Anwender einen Frame in der Grö ß e verändern darf oder nicht. Wenn das Attribut gesetzt ist, ist es nicht erlaubt. noshade
Anwendung bei: HR Typ: (noshade) Verwendung: #OPTIONAL Deprecated Angabe, ob eine Linie mit einem Schaden dargestellt wird oder nicht (Flag verwendet). 1050
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
nowrap
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: TD, TH Typ: (nowrap) Verwendung: #OPTIONAL Deprecated Unterdrückung von Wortummantelung. object
Zugeordnete HTML-Befehle: APPLET Typ: CDATA Verwendung: #OPTIONAL Deprecated Serialisiert ein Applet. onblur
Anwendung bei: A, AREA, BUTTON, INPUT, LABEL, SELECT, TEXTAREA
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Zuordnung einer Aktion, die stattfindet, wenn das Element den Fokus verloren hat. onchange
Anwendung bei: INPUT, SELECT, TEXTAREA Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Zuordnung einer Aktion, die stattfindet, wenn der Wert des Elements sich ändert.
Java 2 Kompendium
1051
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
onclick
Anwendung bei allen Tags bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX,META, PARAM, SCRIPT, STYLE, TITLE
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Button wurde geklickt. ondblclick
Anwendung bei allen Tags bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Button wurde doppelt geklickt. onfocus
Anwendung bei: A, AREA, BUTTON, INPUT, LABEL, SELECT, TEXTAREA
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Element bekommt den Fokus. onkeydown
Anwendung bei allen Tags bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Eine Taste wurde gedrückt.
1052
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
onkeypress
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Eine Taste wurde gedrückt und wieder losgelassen. onkeyup
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Eine Taste wurde losgelassen. onload
Anwendung bei: FRAMESET Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Alle Frames wurden geladen. onload
Anwendung bei: BODY Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Das Dokument wurde geladen.
Java 2 Kompendium
1053
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
onmousedown
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Button wurde gedrückt. onmousemove
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Mauszeiger wurde über einem Element bewegt. onmouseout
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Mauszeiger hat den Bereich eines Elements verlassen. onmouseover
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE
Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Mauszeiger wurde in den Bereich eines Elements hineinbewegt. 1054
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
onmouseup
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei allen HTML-Elementen bis auf: APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Ein Mauszeiger wurde losgelassen. onreset
Anwendung bei: FORM Typ: %Script; Verwendung: #OPTIONAL Event-Handler: Das Formular wurde über den RESETButton gelöscht. onselect
Anwendung bei: INPUT, TEXTAREA Typ: %Script; Verwendung: #OPTIONAL Event-Handler: Text wurde selektiert. onsubmit
Anwendung bei: FORM Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Das Formular wurde gesendet. onunload
Anwendung bei: FRAMESET Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Alle Frames wurden wieder entfernt.
Java 2 Kompendium
1055
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
onunload
Anwendung bei: BODY Typ: %Script; Verwendung: #OPTIONAL Event-Handler. Das Dokument wurde wieder entfernt. profile
Anwendung bei: HEAD Typ: %URL; Verwendung: #OPTIONAL Benennung des Verzeichnisses für eine Meta-Information. prompt
Anwendung bei: ISINDEX Typ: %Text; Verwendung: #OPTIONAL Deprecated Die Prompt-Anzeige. readonly
Anwendung bei: TEXTAREA Typ: (readonly) Verwendung: #OPTIONAL Nur Leseerlaubnis. readonly
Anwendung bei: INPUT Typ: (readonly) Verwendung: #OPTIONAL Nur Leseerlaubnis.
1056
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
rel
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: A, LINK Typ: %LinkTypes; Verwendung: #OPTIONAL Vorwärts-Linkangaben. rev
Anwendung bei: A, LINK Typ: %LinkTypes; Verwendung: #OPTIONAL Rückwärts-Linkangaben. rows
Anwendung bei: FRAMESET Typ: %MultiLengths; Verwendung: #OPTIONAL Liste von Längenangaben (Anzahl Reihen). rows
Anwendung bei: TEXTAREA Typ: NUMBER Verwendung: #GEFORDERT Anzahl der Reihen. rowspan
Anwendung bei: TD, TH Typ: NUMBER Verwendung: Angabe grö ß er 0 Anzahl der Reihen, die von einer Zelle überspannt werden sollen.
Java 2 Kompendium
1057
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
rules
Anwendung bei: TABLE Typ: %TRules; Verwendung: #OPTIONAL Verhaltensregeln zwischen Zeilen und Spalten in einer Tabelle. scheme
Anwendung bei: META Typ: CDATA Verwendung: #OPTIONAL Selektiert einen Inhalt. scope
Anwendung bei: TD, TH Typ: %Scope; Verwendung: #OPTIONAL Wiederholungsbereich der Kopfzellen. scrolling
Anwendung bei: FRAME, IFRAME Typ: (yes | no | auto) Defaulteinstellung: auto Scrollbalken oder nicht. selected
Anwendung bei: OPTION Typ: (selected) Verwendung: #OPTIONAL Selektiert.
1058
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
shape
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: AREA Typ: %Shape; Defaulteinstellung: rect Koordinatenangaben. shape
Anwendung bei: A Typ: %Shape; Defaulteinstellung: rect Koordinatenangaben in einer clientseitigen Imagemap. size
Anwendung bei: HR Typ: %Pixels; Verwendung: #OPTIONAL Deprecated Grö ß enangabe einer Trennlinie. size
Anwendung bei: FONT Typ: CDATA Verwendung: #OPTIONAL Deprecated Grö ß enangabe für eine Schrift. Immer relative Angabe zur Basisschrift. Entweder relativ mit Plus oder Minus von der Basisschriftgrö ß e [+|-]nn, z.B. size="+3", oder genaue Relativangabe zwischen 1 und 7, z.B. size="6"
Java 2 Kompendium
1059
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
size
Anwendung bei: INPUT Typ: CDATA Verwendung: #OPTIONAL Spezifiziert jeden Typ eines Feldes bezüglich seiner Grö ß e. size
Anwendung bei: BASEFONT Typ: CDATA Verwendung: #GEFORDERT Deprecated Basisschriftgrö ß e für jedes Schriftelement. size
Anwendung bei: SELECT Typ: NUMBER Verwendung: #OPTIONAL Sichtbare Einträge in einer Auswahlliste. span
Anwendung bei: COL Typ: NUMBER Verwendung: Angabe grö ß er 0 Die COL-Attribute sollen sich auf die angegebene Anzahl von Spalten auswirken. span
Anwendung bei: COLGROUP Typ: NUMBER Verwendung: Angabe grö ß er 0 Defaultanzahl von Spalten in einer Colgroup.
1060
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
src
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: SCRIPT Typ: %URL; Verwendung: #OPTIONAL URL für ein externes Script. src
Anwendung bei: INPUT Typ: %URL; Verwendung: #OPTIONAL URL für Felder mit Bildern. src
Anwendung bei: FRAME, IFRAME Typ: %URL; Verwendung: #OPTIONAL Source des Inhaltes eines Frames. src
Anwendung bei: IMG Typ: %URL; Verwendung: #GEFORDERT URL des Bildes, das eingebettet werden soll. standby
Anwendung bei: OBJECT Typ: %Text; Verwendung: #OPTIONAL Die Nachricht, die während des Ladevorgangs eines Objekts angezeigt werden soll.
Java 2 Kompendium
1061
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
start
Anwendung bei: OL Typ: NUMBER Verwendung: #OPTIONAL Deprecated Startnummer einer Aufzählung. style
Anwendung bei allen HTML-Elementen bis auf: BASE, BASEFONT, HEAD, HTML, META, PARAM, SCRIPT, STYLE, TITLE
Typ: %StyleSheet; Verwendung: #OPTIONAL Assoziierte Stilinformation. summary
Anwendung bei: TABLE Typ: %Text; Verwendung: #OPTIONAL Strukturangaben für die Sprachausgabe. tabindex
Anwendung bei: A, AREA, BUTTON, INPUT, OBJECT, SELECT, TEXTAREA Typ: NUMBER Verwendung: #OPTIONAL Der Tabulatorindex. target
Anwendung bei: A, AREA, BASE, FORM, LINK Typ: %FrameTarget; Verwendung: #OPTIONAL Die Angabe, wo in dem Frame eine Anzeige erfolgen soll.
1062
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
text
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: BODY Typ: %Color; Verwendung: #OPTIONAL Deprecated Globale Textfarbe im Dokument. title
Anwendung bei: STYLE Typ: %Text; Verwendung: #OPTIONAL Erklärender Titel. Es sollte nicht mit dem TITLE-Element verwechselt werden, das Bestandteil des Header-Teils einer Webseite ist. title
Anwendung bei allen HTML-Elementen bis auf: BASE, BASEFONT, HEAD, HTML, META, PARAM, SCRIPT, STYLE, TITLE Typ: %Text; Verwendung: #OPTIONAL Erklärender Titel für das Element, auf das das Attribut angewandt wird (Quickinfo). Es sollte nicht mit dem TITLE-Element verwechselt werden, das Bestandteil des Header-Teils einer Webseite ist. type
Anwendung bei: A, LINK Typ: %ContentType; Verwendung: #OPTIONAL Erklärender Inhaltstyp.
Java 2 Kompendium
1063
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
type
Anwendung bei: OBJECT Typ: %ContentType; Verwendung: #OPTIONAL Inhaltstyp der Daten. type
Anwendung bei: PARAM Typ: %ContentType; Verwendung: #OPTIONAL Inhaltstyp für Werte, wenn valuetype=ref gilt. type
Anwendung bei: SCRIPT Typ: %ContentType; Verwendung: #GEFORDERT Typ des Inhalts der Script-Sprache. type
Anwendung bei: STYLE Typ: %ContentType; Verwendung: #GEFORDERT Typ des Inhalts der Style-Sprache. type
Anwendung bei: INPUT Typ: %InputType; Default: TEXT Art der Eingabe, die gefordert wird.
1064
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
type
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: LI Typ: %LIStyle; Verwendung: #OPTIONAL Deprecated Stil der Aufzählungsliste. type
Anwendung bei: OL Typ: %OLStyle; Verwendung: #OPTIONAL Deprecated Stil der Nummerierung. type
Anwendung bei: UL Typ: %ULStyle; Verwendung: #OPTIONAL Deprecated Bullet-Stil. type
Anwendung bei: BUTTON Typ: (button | submit | reset) Default: submit Typ der Schaltfläche bei der Verwendung als FormularButton. usemap
Anwendung bei: IMG, INPUT, OBJECT Typ: %URL; Verwendung: #OPTIONAL Verwendung als clientseitige Imagemap. Java 2 Kompendium
1065
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
valign
Anwendung bei: COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR
Typ: (top | middle | bottom | baseline) Verwendung: #OPTIONAL Vertikale Ausrichtug in Zellen. value
Anwendung bei: OPTION Typ: CDATA Verwendung: #OPTIONAL Defaultwert eines Elementinhalts. value
Anwendung bei: PARAM Typ: CDATA Verwendung: #OPTIONAL Eigenschaftenwert. value
Anwendung bei: INPUT Typ: CDATA Verwendung: #OPTIONAL Wert bei Radioboxen und Checkboxen. value
Anwendung bei: BUTTON Typ: CDATA Verwendung: #OPTIONAL Wird bei der Übermittlung zum Server gesendet.
1066
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
value
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: LI Typ: NUMBER Verwendung: #OPTIONAL Deprecated Setzt eine Aufzählungsnummer. valuetype
Anwendung bei: PARAM Typ: (DATA | REF | OBJECT) Default: DATA Beschreibung, wie ein Wert zu interpretieren ist. version
Anwendung bei: HTML Typ: CDATA Typ: %HTML.Version; Deprecated Verwendung: Konstante. vlink
Anwendung bei: BODY Typ: %Color; Verwendung: #OPTIONAL Deprecated Farbe von bereits besuchten Links. vspace
Anwendung bei: APPLET, IMG, OBJECT Typ: %Pixels; Verwendung: #OPTIONAL Deprecated Vertikale Abstandsangabe. Java 2 Kompendium
1067
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Attribut
Beschreibung
width
Anwendung bei: HR Typ: %Length; Verwendung: #OPTIONAL Deprecated Breite der Trennlinie. width
Anwendung bei: IFRAME Typ: %Length; Verwendung: #OPTIONAL Breite des Frames. width
Anwendung bei: IMG, OBJECT Typ: %Length; Verwendung: #OPTIONAL Breitenangabe. width
Anwendung bei: TABLE Typ: %Length; Verwendung: #OPTIONAL Breite der Tabelle. width
Anwendung bei: APPLET Typ: %Length; Verwendung: #GEFORDERT Deprecated Initialisierungsbreite eines Applets.
1068
Java 2 Kompendium
HTML-Elemente und -Attribute
Attribut
Beschreibung
width
Anhang B Tabelle B.82: HTML-Attribute (Forts.)
Anwendung bei: COL Typ: %MultiLength; Verwendung: #OPTIONAL Spaltenbreite. width
Anwendung bei: COLGROUP Typ: %MultiLength; Verwendung: #OPTIONAL Defaultbreite für eingeschlossene Spalten. width
Anwendung bei: TD, TH Typ: %Pixels; Verwendung: #OPTIONAL Deprecated Breite für Zellen. width
Anwendung bei: PRE Typ: NUMBER Verwendung: #OPTIONAL Deprecated Breitenangaben.
Java 2 Kompendium
1069
Anhang B
B.5
JavaScript- Token
JavaScript ist in der Version 1.3 mit der ECMA-262-Norm kompatibel. Dies umfasst folgende Token: Tabelle B.83: JavaScript-Token
1070
Kategorie
Token
Datenfeldverarbeitung
Array, join, length, reverse, sort
Zuweisungen
Zuweisungsoperatoren und Verbundzuweisungsoperatoren
Boolesche Werte
Boolean
Kommentare
/*...*/ oder //
Konstanten/Literale
NaN, null, true, false, +Infinity, undefined
Ablaufsteuerung
break, continue, for, for...in, if...else, return, while
Java 2 Kompendium
JavaScript- Token
Anhang B
Kategorie
Token
Datum und Zeit
Date, getDate, getDay, getFullYear, getHours, getMilliseconds, getMinutes, getMonth, getSeconds, getTime, getTimezoneOffset, getYear,, getUTCDate, getUTCDay, getUTCFullYear, getUTCHours, getUTCMilliseconds, getUTCMinutes, getUTCMonth, getUTCSeconds,, setDate, setFullYear, setHours, setMilliseconds, setMinutes, setMonth, setSeconds, setTime, setYear,, setUTCDate, setUTCFullYear, setUTCHours, setUTCMilliseconds, setUTCMinutes, setUTCMonth, setUTCSeconds,, toGMTString, toLocaleString, toUTCString, parse, UTC
Deklarationen
function, new, this, var, with
Java 2 Kompendium
Tabelle B.83: JavaScript-Token (Forts.)
1071
Anhang B Tabelle B.83: JavaScript-Token (Forts.)
1072
Kategorie
Token
Funktionserstellung
Function, arguments, length
Globale Funktionen
Global, escape, unescape, eval, isFinite, isNaN, parseInt, parseFloat
Math
Math, abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan, E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2
Zahlen
Number, MAX_VALUE, MIN_VALUE, NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY
Java 2 Kompendium
JavaScript- Token
Anhang B
Kategorie
Token
Objekterstellung
Object, new, constructor, prototype, toString, valueOf
Operatoren
Addition +, Subtraktion –, Modulo %, Multiplikation *, Division /, Unäre Negation –, Gleichheit ==, Ungleichheit !=, Kleiner als =, Logisches AND &&, Logisches OR ||, Logisches NOT !, Bitweises AND &, Bitweises OR |, Bitweises NOT ~, Bitweises XOR ^, Bitweises Left Shift , Vorzeichenloses Right Shift >>>, trinäre Bedingung ?:, Komma ,, delete, typeof, void, Dekrement --, Inkrement ++
Java 2 Kompendium
Tabelle B.83: JavaScript-Token (Forts.)
1073
Anhang B Tabelle B.83: JavaScript-Token (Forts.)
1074
Kategorie
Token
Objekte
Array, Boolean, Date, Function, Global, Math, Number, Object, String
Zeichenfolgen
String, charAt, charCodeAt, fromCharCode, indexOf, lastIndexOf, split, toLowerCase, toUpperCase, length
Java 2 Kompendium
C
Anhang C
In diesem Anhang werden wir uns mit ein paar Hintergrundtheorien beschäftigen, die von Java in verschiedenster Weise genutzt werden. Außerdem finden Sie einige Java-Quellen.
C.1
JAR-Archive oder wie arbeiten Komprimierungstechnologien?
Ab der Version 1.1.1 wurde in das JDK und Java die Möglichkeit integriert, so genannte JAR-Files (Java-Archive mit der Erweiterung .jar) zu nutzen. Damit wird die Datenmenge ziemlich komprimiert. In folgendem kleinen Exkurs wollen wir und ein bisschen mit der Theorie der Datenkomprimierung beschäftigen. Vielleicht wollen Sie ja mal selbst ein Komprimierungsprogramm in Java schreiben. Java bietet durch seine an C/C++ angelegte Programmierungsmöglichkeiten auf Bit-Ebene durchaus die Voraussetzung dafür. Programmiersprachen, die diese Programmierungsmöglichkeiten auf Bit-Ebene nicht so direkt zur Verfügung stellen (z.B. PASCAL) erschweren die Erstellung eines Komprimierungsprogramms wiederum.
C.1.1
Komprimierungsverfahren und Programme
Nahezu jedem Computer-Anwender sind schon verschiedene Komprimierungsprogramme über den Weg gelaufen. Insbesondere Java-Anwendern, denn das JDK wird wie nahezu jedes Softwareprodukt komprimiert verteilt. Im Internet ist es sowieso nur noch möglich, die Daten komprimiert zu verschicken, denn die Datentransferraten sind immer niedrig. JAR-Archive sind daher ein weiterer großer Schritt in Richtung Akzeptanz von Java-Technologie im Internet. Wir werden uns bei den zu komprimierenden Daten auf Zeichendarstellungen in einem Byte beschränken, was jedoch keine Beschränkung der Allgemeinheit darstellt. Zuerst stellt sich die Frage, was Komprimierung von Daten heißt? Es bedeutet, Dateien oder Programme zu verkleinern, ohne Informationen zu verlieren. Eine Information, die in der Ursprungsdatei vorhanden ist, muss auch
Java 2 Kompendium
1075
Anhang C in der verkleinerten Datei wiederzufinden sein. Zusätzlich sollte die verkleinerte Datei auch alle Informationen enthalten, um die Ursprungsdatei (bzw. die vollständige Ursprungsinformation) wieder vollständig herzustellen. Die Anzahl der Bytes (Bits), die zur Darstellung von Daten benötigt wird, soll verringert werden. Intuitiv ist klar, dass man eine Datei nur bis zu einer gewissen Grenze verkleinern kann, ohne Informationen zu verlieren (wenn es keine Grenze gäbe, könnte man eine Datei immer wieder komprimieren, hätte zum Schluss noch ein Bit übrig und trotzdem noch alle Informationen). Neben der Verkleinerung der Datenmenge ist die Datensicherheit ein Grund für Komprimierung, denn komprimierte Daten lassen sich nicht so ohne Weiteres entschlüsseln – gerade in der Datenfernübertragung. Noch besser sind natürlich spezielle Kodierungsprogramme, die in ihrer Arbeitsweise Komprimierungsprogrammen aber durchaus ähnlich sein können (zumindest einige der Kodierungstechniken). Einen wesentlichen Nachteil erkauft man sich mit Datenkomprimierung. Entweder man arbeitet mit so genannten Online-Komprimierern, die prinzipiell während des Lesen und Schreibens von Daten komprimieren bzw. entkomprimieren. Dadurch hat man deutlich längere Lese-/Schreibzugriffe auf die Datenträger. Oder man nimmt Packer, die manuell aufgerufen werden und dann die angegebenen Daten komprimieren/dekomprimieren, unabhängig von den normalen Lese-/Schreibzugriffen. Eine dritte Variante sind die so genannten EXE-Komprimierer, die direkt in den Hauptspeicher entpacken, wo das Programm dann sofort gestartet wird. In jedem Fall bedeutet die Verwendung von Packern Zeitaufwand. Das gleichzeitige Verwenden von verschiedenen Komprimierungsvorgängen macht meist keinen Sinn, da bereits einmal komprimierte Daten in der Regel nicht weiter komprimiert werden. Desgleichen macht die nacheinander folgende Anwendung von verschiedenen Komprimierungsverfahren wenig Sinn. Im Gegenteil – es liegt in der Natur der Sache (wir werden es gleich sehen), dass eine mehrfache Verwendung von Komprimierungsprogrammen meist zu einer erheblichen Vergrö ß erung der Datenmenge führt. Welche verschiedenen Methoden zum Komprimieren von Daten gibt es nun? Die Art der Datenkompression ist stark abhängig von der zu verarbeitenden Datei. Nicht jede Komprimierungsart hat bei jedem Typ von Datei den gleichen Erfolg. Bei Dateien, wo sich bestimmte Informationen oft wiederholen, lassen sich recht schnell ordentliche Komprimierungsraten (Komprimierungsrate in % = Grö ß e der Ursprungsdatei / Grö ß e der komprimierten Datei, also je kleiner, desto besser) erzielen, indem man nur angibt, wie oft sich ein Zeichen wiederholt.
1076
Java 2 Kompendium
JAR-Archive oder wie arbeiten Komprimierungstechnologien?
Anhang C
Beispiel: Eine Datei, die wie folgt aussieht XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
benötigt 40 Byte (sie besteht aus 40 mal dem Zeichen X). Die gleiche Information lässt sich auch in X40 verschlüsseln. Diese Datei wäre nur 3 Byte groß. Das Komprimierungsprogramm müsste in der zu verkleinernden Datei nur die Zahl der sich wiederholenden Zeichen ermitteln und in die Zieldatei diese Zahl und einmal das gefundene Zeichen schreiben. Die Entkomprimierung läuft genau umgekehrt. Sobald das Entkomprimierungsmodul eine Zahl findet, schreibt es das vorherige Zeichen in dieser Anzahl in die Zieldatei. Ein entsprechender Algorithmus muss nur in das Komprimierungsprogramm integriert werden. Dieses Verfahren hat zwei ganz offensichtliche Schwachstellen. Die zu komprimierende Datei darf keine Zahlen enthalten – wie sollte sonst das Entkomprimierungsmodul unterscheiden können, ob die gefundene Zahl die Mengenangabe oder das Zeichen ist. Außerdem wird z.B. kaum eine Textdatei so viele Buchstabenwiederholungen haben, dass dieses Verfahren Erfolg hat – erst ab drei gleichen Buchstaben hintereinander würde die Datei kleiner. Daran sieht man bereits, dass dieses Verfahren i.a. nicht geeignet ist, um beliebige Dateien zu verkleinern. Es hat trotzdem eine große Bedeutung. Grafikformate – z.B. PCX vom Windows-Programm Paintbrush – verwenden ein solches Verfahren, sind also bereits gepackt. Es wird eine gute Komprimierungsrate erzielt, wenn große einfarbige Flächen zu speichern sind. Für reine Textdateien lässt sich auch ein funktionierendes Komprimierungsmodell entwerfen. Bekannterweise können auf dem PC alle verfügbaren Zeichen im ASCII-Code gespeichert werden. Der Unicode von Java kann selbstverständlich genauso als Grundlage dienen (alles mal 2). Wir bleiben aber wie schon angedeutet ohne Beschränkung der Allgemeinheit beim ASCII-Code. Ein Zeichen im ASCII-Code hat genau die Länge von 1 Byte, d.h. 8 Bit. Damit lassen sich im Dualsystem 256 (2 hoch 8) Zeichen darstellen, eben den Umfang der ASCII-Tabelle. Wenn nun maximal 128 (2 hoch 7) Zeichen gespeichert werden sollen, kommt man im Prinzip auch mit 7 Bit aus. Das achte Bit ist bei einer geeigneten Kodierung (d.h. Umsortierung oder Verschiebung) immer 0. Damit könnte man alle reinen Textzeichen (mit Umlauten, Punkt, Komma usw.) zuordnen. Eine reine Textdatei lässt sich mit einem solchen Programm schnell und einfach auf 87,5 % der Ursprungsgrö ß e reduzieren. Aber wie gesagt, dieses Verfahren macht nur für Dateien Sinn, die maximal 128 verschiedene Zeichen beinhalten. In der Praxis wird dieses Verfahren so gut wie nicht verwendet. Allerdings steckt in diesem Modell bereits ein wichtiger Hinweis auf einen wesentlichen Bestandteil von allgemeinen Komprimierungsprogrammen. Zeichen müssen
Java 2 Kompendium
1077
Anhang C nicht unbedingt in einem Byte (oder 2 Byte beim Unicode) gespeichert werden, sondern können durchaus in einer geringeren Zahl von Bits verschlüsselt werden – natürlich auch in einer grö ß eren Zahl von Bits. Eine erste Idee könnte sein, bei einem Zeichen, das eine gewisse Zahl von führenden Nullen in seinem Code hat, nur ab dem ersten von Null verschiedenen Bit zu speichern. Wenn z.B. das Zeichen A den ASCII-Code 65 hat, wird das binär als 1000001 dargestellt. Also in 7 Bit. Das Zeichen B mit dem ASCII-Code 66 ist binär 1000010. Wenn man sie nun ohne die führenden Nullen hintereinander wegschreibt, erhält man eine reduzierte Grö ß e der Datei. Das Problem ist aber, dass man nicht weiß, wie viel Bit beim Entkomprimieren einzulesen sind, um den vollständigen Code eines Zeichens zu erhalten. Die kodierte Darstellung ist bei diesem Verfahren nicht eindeutig. Beispiel: 100101 kann ein Zeichen mit dem ASCII-Code 37, aber auch zwei verschiedene Zeichen mit den ASCII-Codes 4 (100) und 5 (101) bedeuten. Eine Darstellung in der Form 100 101 wäre eindeutig, da hier das Leerzeichen als Begrenzer für ein Zeichen dient. Da aber jedes in Frage kommende Zeichen in einer beliebigen Datei auch vorkommen kann und natürlich auch kodiert werden müsste (auch das Leerzeichen, das in einer Binärdatei natürlich nichts zu suchen hat!), hat man wieder ein ähnliches Problem wie bei der Verschlüsselung von Grafikdateien. Es darf mindestens ein Zeichen – eben der Begrenzer einer Zeichendarstellung – nicht in der Quelldatei vorkommen. Begrenzer eignen sich also nicht, um bei verschieden langer Darstellung von Zeichen die einzelnen Zeichen voneinander zu trennen. Welche Lösung gibt es nun für dieses Problem? Es werden genau dann keine Begrenzer benötigt, wenn kein Zeichencode mit dem Anfang eines anderen übereinstimmt, wenn also nach dem Einlesen von jedem Bit klar ist, ob es noch zur Bitfolge des bis dahin gelesenen Zeichens gehört oder bereits der Anfang eines neuen Zeichens ist. Das allgemeine Verfahren, um einen solchen Code zu bestimmen, wurde 1952 von D. Huffman entdeckt und wird nach ihm die Huffman-Kodierung genannt Die meisten gängigen Komprimierungsverfahren arbeiten mit diesem (meist leicht modifizierten) Huffman-Algorithmus.
C.1.2
Der Huffman-Algorithmus
Bei der Erzeugung des Huffman-Codes hat man im Wesentlichen zwei Probleme zu lösen. Zum einen will man einen kürzeren Code erzeugen und zum anderen soll die Darstellung von Zeichen in dem neuen Code eindeutig sein. Klar ist, dass eine Datei, die nur aus tausend mal dem Buchstaben A besteht, auch in der normalen Form 1000 Byte groß ist. Wenn man nun irgendwo definiert, dass der Buchstabe A binär durch 0 dargestellt werden soll, kann diese Datei in 1000 Bit – tausend mal Null – dargestellt werden. Dies ist viel kleiner und eindeutig, solange bekannt ist, dass eine 0 das Zeichen A bedeu1078
Java 2 Kompendium
JAR-Archive oder wie arbeiten Komprimierungstechnologien?
Anhang C
tet. Komme nun noch der Buchstabe B genau einmal in dieser Datei vor. Die Datei wäre 1001 Byte groß in der normalen Darstellung. Das Zeichen B sei binär in der Form 1111111111111111 verschlüsselt, also in einer Zeichenkette von 2 Byte. Die kodierte Darstellung ist damit 1016 Bit groß (1000 x 1 Bit + 1 x 16 Bit), also immer noch bedeutend kleiner und eindeutig. Solange man beim Einlesen der kodierten Datei eine 0 findet, hat man einmal das Zeichen A; sobald eine 1 auftritt, muss man bis zur nächsten 0 lesen. Nachdem 16 mal eine 1 vorkam, ist eindeutig dieser Bitfolge das Zeichen B zugeordnet. Aber wer sagt denn, dass das Zeichen A mit Null und das Zeichen B in der Form 1111111111111111 zu verschlüsseln ist? Man kann ja auch auf die Idee kommen, genau umgekehrt zu verfahren. Oder man hat eine Datei, in der das Zeichen A nur einmal und das Zeichen B 1000-mal vorkommt. Damit wäre die verschlüsselte Datei immer noch eindeutig, aber auf Grund der unglücklichen Wahl des Verschlüsselungsmechanismus ungefähr doppelt so groß wie die Ursprungsdatei (1000 x 16 Bit + 1 x 1 Bit). Es erscheint also äußert sinnvoll, häufig vorkommende Zeichen in einem kürzeren und selten vorkommende Zeichen in einem längeren Code zu verschlüsseln, unter Umständen auch in einem Code, der mehr als ein Byte groß ist, solange das zugehörige Zeichen nur »selten genug« vorkommt. Genau dieses ist der erste Schritt beim Erstellen des Huffman-Codes. Es ist in der zu verschlüsselnden Datei die Häufigkeit jedes Zeichens zu ermitteln. Diese bilden dann eine Häufigkeitsmenge aus lauter so genannten Knoten. Der nächste Schritt besteht darin, dem am häufigsten vorkommenden Zeichen den kürztest möglichen Code zuzuordnen, dem seltensten Zeichen den optimalen längsten Code. Zeichen, die überhaupt nicht in der Ursprungsdatei vorkommen, werden nicht verschlüsselt. Wie wird nun ein optimaler und eindeutiger Code ermittelt? Zunächst werden die zwei Zeichen mit den geringsten (von Null verschiedenen) Häufigkeiten genommen (falls mehr als zwei Zeichen die gleiche Häufigkeit haben, kann man sich beliebig entscheiden). Diese beiden bilden einen neuen Knoten, dessen Wert die Summe der Häufigkeiten der beiden erzeugenden Zeichen ist. Danach werden die beiden erzeugenden Knoten gestrichen und der neu erzeugte Knoten in die verbleibende Häufigkeitsmenge – oder auch Menge von Bäumen – aufgenommen. Die Zahl der Bäume hat sich um 1 reduziert. In der neuen Häufigkeitsmenge sucht man erneut die beiden Knoten mit der geringsten Häufigkeit und fährt wie oben fort. So wird Schritt für Schritt die Anzahl der Bäume reduziert (zwei entfernen und einen hinzufügen). Zum Schluss sind alle Knoten zu einem einzigen Baum verbunden. Nunmehr kann der Huffman-Code abgeleitet werden, indem man die Häufigkeiten an den untersten Knoten des Baumes durch das jeweilige zugehörige Zeichen ersetzt. Wenn man noch vereinbart, dass links in dem binären Baum dem Bit 0 und rechts dem Bit 1 entspricht, kann man jedes vorkommende Zeichen über eine entsprechende
Java 2 Kompendium
1079
Anhang C Folge darstellen. Diese Kodierung ist eindeutig und es lässt sich mit dem mathematischen Mittel der Induktion beweisen, dass keine Kodierungsstrategie zu einem besseren Ergebnis führen kann als die oben beschriebene Methode. Der Huffman-Code ist i.a. der bestmögliche Code. Jetzt muss nur noch jedes in der Ursprungsdatei vorkommende Zeichen durch seinen neuen Code ersetzt werden. Zusätzlich muss noch irgendwo in der komprimierten Datei (im Header) für eine spätere Entkomprimierung hinterlegt werden, welcher Code welchem Zeichen entspricht. Meist werden dort noch diverse weitere statistische und technische Parameter gespeichert. Diese Maßnahme vergrö ß ert die Datei wieder geringfügig und macht auch deutlich, dass eine Komprimierung von Dateien nur dann Sinn macht, wenn der Headerteil der komprimierten Datei nicht grö ß er ist als der Komprimierungsfaktor. Daher würde z.B. ein erneutes Komprimieren eines bereits komprimierten Codes in der Regel keine Vorteile bringen, sondern den Code eher noch vergrö ß ern (der neue Header muss ja noch zusätzlich gespeichert werden und der Code war ja in der Regel schon optimal). Für Java hat dies einige unangenehme Konsequenzen. In diesen JAR-Archiven können neben .class-Dateien auch Image- und Sound-Dateien verpackt werden. Für .class-Dateien lassen sich sehr gute Komprimierungsraten erzielen, aber Image- und Sound-Dateien sind normalerweise schon hochkomprimiert. Ein Verpacken von vielen Image- und Sound-Dateien in JAR-Dateien kann also sogar dazu führen, dass diese sogar grö ß er ist als die Summe der einzelnen Dateien. In diesem spezielen Fall bleibt nur der Vorteil, dass die Applikation in einer einzigen HTTP-Transaktion übertragen wird und nicht in vielen einzelnen Übertragungsschritten. Statt vieler einzelner und unkomprimierter Dateien wird beim Laden aus dem Netz ein gepacktes Archiv übertragen. Wir wollen an einem Beispiel den Huffman-Algorithmus durchsprechen. Unser zu komprimierender Beispieltext lautet wie folgt: EXTREMER ERNST
Es sind 13 Zeichen (lassen wir einmal das Leerzeichen außer Acht) und damit wäre der Text 13 Byte groß. Nach Durchzählen der Zeichen ergibt sich, dass E viermal, R dreimal, T zweimal und alle anderen Zeichen einmal vorkommen. Dies kann beispielsweise eine einfache Java-Routine leicht lösen. Verfolgen wir auf unser Beispiel bezogen unsere einzelnen Schritte zur Erstellung eines Huffman-Codes. Die häufig vorkommenden Zeichen sollen den kürzesten Code, die seltener vorkommenden den längeren Code bekom-
1080
Java 2 Kompendium
JAR-Archive oder wie arbeiten Komprimierungstechnologien?
Anhang C
men. Der Code muss zudem eindeutig sein, denn nur auf Grund einer Eindeutigkeit lässt er sich wieder eindeutig entkomprimieren. Führen wir also diesen Schritt beim Huffman-Verfahren in unserem Beispiel durch. Die Anzahl der jeweiligen Zeichen (die Häufigkeitsmenge) – ist in unserem Beispiel (4, 3, 2, 1, 1, 1, 1). Wir versuchen also, dem am häufigsten vorkommenden Zeichen (E, da es viermal vorkommt) den kürztest möglichen Code zuzuordnen, dem seltensten Zeichen den optimalen längsten Code (wir habe 4 Zeichen zur Auswahl, die jeweils nur einmal vorkommmen – da müssen wir uns gleich entscheiden). Zunächst nehmen wir zwei der Zeichen mit den geringsten (von Null verschiedenen) Häufigkeiten. Da wir 4 Zeichen mit gleicher Häufigkeit haben, kann man sich beliebig entscheiden. Die beiden ausgewählten Zeichen bilden einen neuen Knoten, dessen Wert die Summe der Häufigkeiten der beiden erzeugenden Zeichen ist. Danach werden die beiden erzeugenden Knoten gestrichen und der neu erzeugte Knoten in die verbleibende Häufigkeitsmenge aufgenommen. In unserem Beispiel sind es (eine willkürliche Auswahl unter den 4 Kandidaten mit der Häufigkeit 1) N und M. Die neue Häufigkeitsmenge sieht dann so aus: (4, 3, 2, 2, 1, 1). Die Zahl der Bäume hat sich um eins reduziert, denn es sind offensichtlich nur noch 6 Einträge in der Häufigkeitsmenge (gegenüber 7 am Anfang). In der neuen Häufigkeitsmenge sucht man erneut die beiden Knoten mit der geringsten Häufigkeit (in unserem Fall S und X, denn die haben noch den Häufigkeitswert 1 – das Tupel NM hat nun den Häufigkeitswert 2) und fährt fort, die Anzahl der Bäume zu reduzieren. Zum Schluss sind alle Knoten zu dem Baum verbunden, den wir unten sehen. Leiten wir jetzt den Huffman-Code ab. Wir verfolgen in dem binären Baum von der Wurzel (W) den Weg zu jedem Zeichen. Nach der oben getroffenen Vereinbarung ist eine linke Abzweigung an einem Konten dem Bit 0 zugeordnet und rechts dem Bit 1. Um zu dem Zeichen E zu kommen, müssen wir von der Wurzel aus zweimal links verzweigen. Daraus folgt zweimal das Bit 0. Die Kodierung für das häufigste Zeichen ist nur 2 Bit groß, was einer (eindeutigen) Komprimierung auf 25 % entspricht. Nehmen wir Zeichen S. Dies ist eines der Zeichen, die am seltensten vorkommen. Der Weg von der Wurzel aus ist links, rechts, rechts, links (= 0110), eindeutig und mit 4 Bit immer noch halb so groß wie die orginale ASCII-Codierung in einem Byte. Wenn Sie sich den Baum ansehen, werden Sie anhand der Wege und Verzweigungen von der Wurzel zu einem Zeichen immer die eindeutige Huffman-Verschlüsselung des Zeichens ableiten können. (Alle Striche sollen von einem Knoten (Zahl) zum anderen verbunden sein) W=Wurzel
Java 2 Kompendium
1081
Anhang C Tabelle C.1: Ein Huffman-Baum
E
N
M
S
X
T
R
4
1
1
1
1
2
3
|
\
/
\
/
|
|
|
2
2
|
|
|
\
/
|
|
|
\ \
/
\
4 \
/ 5
/
/
8
/ \
/ \
/ 13
=
W
Daraus ergibt sich folgender Code für die vorkommenden Zeichen – von der Wurzel W aus gesehen: E N M S X T R
= = = = = = =
00 0100 0101 0110 0111 10 11
C.1.3
Selbstextrahierende Programme
Eine Besonderheit in der Welt der Komprimierung sind die so genannten selbstextrahierenden Programme oder auch SFX-Archive. Diese sind im Prinzip lauffähige Programme, deren einziger Zweck es ist, bei Aufruf die in dem Archiv komprimierten Daten zu extrahieren. Im Header dieser Archive ist also in lauffähiger Form die vollständige Information enthalten, wie die komprimierten Daten zu extrahieren sind, der Rest ist die »normale« gepackte Datei. Die meisten gängigen Packer sind in der Lage, selbstextrahierende Archive zu erzeugen. Die Vorteile liegen auf der Hand. Zum einen ist die Anwendung einfach. Keine kryptischen Befehlszeilen, nur das Programm starten. Zum anderen muss man nicht im Besitz des Komprimierungsprogramms sein, um die Daten zu extrahieren. Da aber die meisten 1082
Java 2 Kompendium
Wie funktionieren Verschlüsselungsverfahren?
Anhang C
Packer Sharwareprodukte sind und man sie sich nahezu von überall, ob aus CompuServe, von diversen CDs mit Shareware oder auch von kommerziell vertriebenen Softwarepaketen besorgen kann, ist dieses eigentlich kein gewichtiges Argument. Man findet sogar inzwischen so viele gute Sharewarepacker, dass praktisch kein Markt für kommerzielle Produkte vorhanden ist. Die meisten Vertreiber von Shareware legen den verwendeten Packer mit bei. Selbstextrahierende Archive haben auch einen großen Nachteil. Sie sind einfach grö ß er, weil eben die Extrahierungsfunktion in lauffähiger Form in jeder Datei mit gespeichert werden muss. Bei dem früher in der DOS-Welt weit verbreiteten ARJ ist das SFX-Modul ca. 15 KByte groß.
C.1.4
Wie groß ist die Reduzierung der Datenmenge?
Man kann keine allgemein gültige Aussage zur Reduzierung der Datenmenge machen, denn diese hängt massiv von den zu komprimierenden Dateien ab. So schaffen moderne Packer bei Textdateien (dazu zählen natürlich auch Java-Source-Dateien) sogar Komprimierungsraten bis zu 10 % (also nur noch 10 % der Orignalgrö ß e), während sich DOS-Programme auch in günstigen Fällen kaum unter 50 % verkleinern lassen. Wenn die Programme mit Overlaytechnik arbeiten, wird die Rate schlechter. Auch Windows-Programme sind kritische Kandidaten für Packer. Noch schlechter sieht die Rate bei Grafikdateien aus, die sich manchmal überhaupt nicht oder im besten Fall auf 70 % komprimieren lassen – der Grund dafür ist, dass Grafikformate bereits komprimiert sind (s.o.). Java-Klassen sind als Bytecode ein Mittelding zwischen Textdateien und komprimiertem Maschinencode. Es lassen sich recht gute Komprimierungsraten erzielen. Die genauen Raten sind von der Struktur der Klasse abhängig. Sie bewegen sich zwischen 30 % und 40 %.
C.2
Wie funktionieren Verschlüsselungsverfahren?
Digitaler Datenaustausch hat Hochkonjunktur. Nicht nur HTML-Seiten und Java-Applets, auch immer mehr Daten werden nicht mehr per Papier, Fax oder Telefon verschickt, sondern mittels digitaler Datenträger oder Leitungen auf die Reise geschickt. Auch sensible Angaben, die nicht unbedingt von unbefugten Personen ausgewertet werden sollen. Denken Sie nur an Online-Banking oder Online-Shopping mit Angabe der Kreditkartennummer. Deshalb raten sämtlich Experten, die Daten vor dem Verschicken in eine Form zu bringen, die ein widerrechtliches Auswerten verhindert oder zumindest erschwert. Dies übernehmen so genannte Verschlüsselungs- oder Kryptographieprogramme bzw. speziell in Programme eingebaute Funktionen zum Kodieren. Ursprünglich wurden Verschlüsselungsverfahren bei der Übermittlung von militärischen und diplomatischen Nachrichten eingesetzt. Schon aus der Java 2 Kompendium
1083
Anhang C Römerzeit sind Verschlüsselungsverfahren für Nachrichten bekannt, und eine der gängigsten Verschlüsselungsalgorithmen ist nach Julius Cäsar benannt, die Cäsar-Chiffre. Der Schutz vor unberechtigter Nutzung von Computern hat sich inzwischen auf allen Ebenen – sowohl auf Großrechnern und Client-Server-Systemen, aber auch auf Stand-Alone-PCs – durchgesetzt (wer hat es schon gerne, wenn jedermann private Dateien lesen kann?). Passwörter und Zugangsbeschränkungen zu verschiedenen Bereichen sind überall üblich. Hat ein Datenspion jedoch diese Zugangsbeschränkungen überwunden, kann er oft frei Daten auswerten. Noch schlimmer ist die Situation, wenn Informationen ein geschlossenes Computersystem verlassen und auf die Reise zu einem anderen System gehen. Sowohl der Datenträger, der per Postweg verschickt wird, als auch die E-Mail oder die Datei, die per Internet oder einem kommerziellen Netzwerk zu einem Empfänger unterwegs ist, können relativ leicht abgefangen und ohne Spuren zu hinterlassen kopiert/analysiert werden. Eine Nachricht läuft im Internet normalerweise über mehrere Server, bis sie ihr Ziel erreicht. Verschlüsseln musst für sensible Daten unbedingt sein. Wie aber werden Daten verschlüsselt, wie arbeiten Kodierungsprogramme?
C.2.1
Verschlüsselungs- bzw. Kryptographieprogramme
Um die Arbeitsweise von Verschlüsselungsprogrammen zu verstehen, sollte man sich erst einmal deutlich machen, was das Ziel der Verschlüsselung sein soll. Geheimhaltung! Dazu bedienen sich die Kodierungsprogramme einer recht alten mathematischen Wissenschaft, der Kryptologie. Diese Wissenschaft besteht aus zwei sich ergänzenden Teilgebieten, der Kryptographie und der Kyptoanalyse. Vereinfacht gesagt, versucht die Kryptographie Systeme für eine geheime Kommunikation zu entwickeln, während das Ziel der Kryptoanalyse die Entschlüsselung derselben ist. Man kann sich der Kryptologie nähern, indem man sie sich als eine Art Spiel vorstellt. Allgemeine Spielregeln Wie lauten nun die Spielregeln der Kryptologie, was ist das Ziel? Das Spiel besteht im Allgemeinen darin, dass ein Spieler – der Sender – Daten zu einem zweiten Spieler – dem Empfänger – übermitteln will. Es kann sich durchaus um dieselbe Person handeln, z.B. dann, wenn Daten auf einem Rechner geschützt werden sollen und der Sender/Empfänger zwischenzeitlich die Daten aus dem Augen verliert (Feierabend oder so). Der Sender nimmt die zu übermittelnden Daten, den Quelltext, und wandelt sie in eine geheime Form, den Chiffretext, um. Diese Umwandlung erfolgt mit einer geeigneten Verschlüsselungsmethode und zugehöriger Verschlüsselungsparametern. Nach der Umwandlung wird die Botschaft – der Chiffretext – auf
1084
Java 2 Kompendium
Wie funktionieren Verschlüsselungsverfahren?
Anhang C
den Weg zum Empfänger geschickt (bzw. auf dem Rechner bis zum nächsten Laden abgelegt). Wenn der Empfänger nun die erhaltene Botschaft lesen will, müssen ihm sowohl die zur Verschlüsselungsmethode passende Entschlüsselungsmethode als auch die Verschlüsselungsparameter bekannt sein. Mit diesen Angaben kann er dann den Chiffretext in den Quelltext zurückwandeln. Ein weiterer Mitspieler – der Kryptoanalyst (der verschieden von Sender und Empfänger sein sollte, sonst ist das Spiel langweilig) – versucht nun, die Daten auf dem Weg vom Sender zum Empfänger abzufangen und zu analysieren. Dazu muss er zum einen die Methode, zum Anderen die Parameter herausfinden, um dann den Chiffretext wieder in den Quelltext zu übersetzen. Ein solches Spielsystem wird in der Informatik ein Kryptosystem genannt. Sicherheit contra Ökonomie Einfache und komplexe Verschlüsselungsverfahren unterscheiden sich im Wesentlichen durch die Anzahl und die Komplexität ihrer Verschlüsselungsparameter. In der Regel gilt, ein Kryptosystem ist umso sicherer, je komplexer der Verschlüsselungsparameter ist oder je mehr Verschlüsselungsparameter vorhanden sind. Bei mehreren Parametern wird nach Anwendung des ersten Parameters ein Zwischencode erzeugt, auf den dann der folgende Parameter angewendet wird. Das Verfahren wird so oft wiederholt, bis alle Parameter abgearbeitet sind. Bei der Dekodierung werden die Parameter dann in umgekehrter Reihenfolge angewandt. Allerdings wird bei komplexen Verfahren auch die Bedienung immer komplizierter, zeitaufwändiger und immer unökonomischer. Ähnlich wie bei einem Zahlenschloß mit immer mehr Nummern. Die Frage nach Aufwand und Nutzen ist von zentraler Bedeutung. Im Prinzip ist es möglich, Kryptosysteme zu entwickeln, die nahezu unmöglich zu knacken sind (denken Sie im Extremfall an ein Zahlenschloss mit vielen Millionen Zahlen). Eine Kodierung und die – berechtigte – Dekodierung einer Botschaft wäre allerdings mit einem erheblichen Aufwand verbunden. Auch einfache Verschlüsselung schützt Jedoch auch einfache Methoden schützen bereits Daten. Sogar dann, wenn der Kryptoanalyst Kenntnis von einer der beiden notwendigen Informationen hat und ihm die zweite Information fehlt. Selbst bei nur einem Verschlüsselungsparameter ist es mit einem gewissen Aufwand verbunden, diesen Parameter zu finden, und wenn er nicht über das Entschlüsselungsverfahren informiert ist, d.h. nicht im Besitz eines passenden Dekodierungs-
Java 2 Kompendium
1085
Anhang C programmes ist, bedeutet es eine nicht unerhebliche Erschwerung bei der Auswertung des Chiffretexts. Auch hier ist ein Vergleich mit einem einfachen Fahrradzahlenschloss nicht abwegig. Für Profis zwar kein Hindernis, dagegen so einfach im Vorbeigehen lässt sich das Fahrrad von einem Laien nicht entwenden.
C.2.2
Einige Verschlüsselungsverfahren
Schauen wir uns einmal ein paar Beispiele für bekannte Verschlüsselungsverfahren an. Cäsar-Chiffre Eine relativ einfache und schon recht alte Verschlüsselungsmethode ist die Cäsar-Chiffre. Diese Verschlüsselungsmethode lautet wie folgt: Für jeden im Quelltext vorkommenden Buchstaben des Alphabets setze im Chiffretext einen um einen festen Parameter versetzten Buchstaben. Wenn beispielsweise im Quelltext der erste Buchstabe des Alphabets – ein A – auftaucht und der Verschlüsselungsparameter 3 ist (angeblich der von Cäsar benutzte Parameter), wird im Chiffretext der vierte Buchstabe des Alphabets – ein D – genommen, usw. Hat man einen Buchstaben vom Ende des Alphabets, wird wieder von vorne gezählt, also aus z.B. dem letzten Buchstaben des Alphabets – Z – wird in unserem Fall ein C. Die Dekodierung läuft entsprechend umgekehrt. Dieses Verfahren ist allerdings relativ einfach zu knacken, da der Kryptoanalyst – sofern er die Methode erraten hat – nur die verwendete Konstante ermitteln muss. Da bestimmte Buchstaben in jeder Sprache mit verschiedener Häufigkeit vorkommen, ist die Bestimmung dieser Verschlüsselungskonstanten meist schnell zu bewerkstelligen. In der deutschen Sprache kommt das E am häufigsten vor und dementsprechend wird mit hoher Wahrscheinlichkeit das am häufigsten im Chiffretext vorkommende Zeichen diesem E entsprechen. Die Differenz zwischen dem häufigsten Chiffrezeichen und dem E ist als Verschlüsselungskonstante einen Test wert. Sofern der damit ermittelte Text einen Sinn ergibt, war es sehr wahrscheinlich ein Treffer. Was tun bei binären Zeichen? Neben der relativen Unsicherheit hat unser Cäsar-Chiffre-Verfahren bisher noch einen weiteren Makel. Bis jetzt steht noch nicht fest, wie das Verfahren bei Zeichen reagieren soll, die nicht im Alphabet vorkommen. Bei Texten auf Papier (oder Textdateien) hat dies geringe Auswirkungen, aber was ist mit allgemeinen Dateien? Bei Zahlen ist das Verfahren leicht zu übertragen, jedoch was ist mit Sonderzeichen, Umlauten oder anderen binären Zeichen? Die Lösung dieses 1086
Java 2 Kompendium
Wie funktionieren Verschlüsselungsverfahren?
Anhang C
Problems führt über die Art, wie Zeichen auf Computern dargestellt werden – die ASCII-Tabelle oder eine entsprechende Kodierung. Statt des Alphabets wird diese Tabelle als Basis genommen, also ein Zeichen mit dem ASCIIWert 100 bekommt in unserem Fall im Chiffretext den ASCII-Wert 103. Bei binären Dateien – keinen reinen Textdateien – ist die einfache CäsarChiffre trotzdem wirkungsvoll. Durch die bereits in der Quelldatei vorkommenden Steuerzeichen ist ein Erraten der verwendeten Konstanten extrem erschwert (das E ist wahrscheinlich nicht mehr das häufigste Zeichen des Quelltextes), selbst wenn man mit einem passenden Programm die verschlüsselte Datei analysieren kann. Wenn sich ein Kryptoanalyst ungeschickt anstellt, muss er bis zu 256 Konstanten ausprobieren. Man kann also davon ausgehen, dass bereits das Cäsar-Chiffre-Verfahren für viele Gelegenheiten ausreicht. Damit soll dem Leichtsinn nicht die Tür geredet werden. Ganz im Gegenteil. Sämtliche sensiblen und auswertbaren oder anderweitig manipulierbare Informationen sollten – sofern die Brisanz es notwendig macht – auf jeden Fall besser verschlüsselt werden, wenn Sie über das Internet verschickt werden. Die Frage ist aber, wie kompliziert ein Verfahren überhaupt sein muss. Wenn Sie erwarten, dass Ihre speziellen Daten gezielt abgefangen werden, sollte das Verfahren natürlich so sicher wie möglich sein. Normalerweise wird ein Datenspion jedoch einen zentralen Platz (beispielsweise einen Server) überwachen und dort mit Programmen automatisch nach interessanten Informationen suchen, etwa sämtliche Mails automatisch nach dem Schlüsselbegriff »Kreditkartennummer« durchforsten lassen. Falls die Mail nur nach der Cäsar-Chiffre verschlüsselt ist (also der ASCII-Code nur verschoben), wird der Begriff »Kreditkartennummer« schon so verstellt, dass er den automatischen Routinen nicht mehr auffällt. Die Cäsar-Chiffre oder andere einfache Verfahren können übrigens auch dazu verwendet werden, eine kompliziertere Verschlüsselung zu verschleiern. Dabei wird das Verschlüsselungsverfahren so trickreich aufgebaut, dass es die Entschlüsselung der einfachen Variante bewusst einkalkuliert und damit eine falsche Spur legen will. Wenn der Datenspion das Verfahren geknackt hat und eine lesbare, aber uninteressante Information erhält, wird er wahrscheinlich die weitere Entschlüsselung abbrechen. In diesem Fall muss noch mindestens eine weitere Verschlüsselungsebene mit einem zugehörigen Verfahren existieren, aus der dieser Zwischencode dann weiter bearbeitet wird. Sichere Verfahren Dennoch, seit Cäsar ist viel Zeit vergangen, und die Cäsar-Chiffre ist auch für Binärdateien nicht die sicherste Verschlüsselungsvariante. Leistungsfähi-
Java 2 Kompendium
1087
Anhang C ger ist eine Methode, wo die Kodierung über Tabellen erfolgt. Bei Programmen sind diese Tabellen intern im Code gespeichert – sonst wäre es sinnlos. Es gibt keine feste Konstante, sondern jedes mögliche Zeichen des Quelltextes bekommt eineindeutig (d.h. eindeutig hin- und zurück zuzuordnen) ein anderes Zeichen aus der Tabelle zugeordnet. Auch bei dieser Methode gilt, dass sie für reine Texte über die Häufigkeit bestimmter Buchstaben bzw. Buchstabenpaare zu knacken ist, bei Binärdateien ist sie entsprechend sicherer. Die Vigenere-Chiffre Eine recht sichere Möglichkeit Daten zu verschlüsseln, ist die Vigenere-Chiffre, eine Verallgemeinerung der Cäsar-Chiffre. Eine sich wiederholende Folge von Zeichen bildet einen Schlüssel, aus dem der Verschlüsselungsparameter für jedes Zeichen des Quelltextes einzeln berechnet wird (Addition des Quellzeichens und des Schlüsselzeichens). Beispiel mit ASCII-Werten: Der Schlüssel bestehe aus 4 Zeichen – 100 101 102 103. Tabelle C.2: Verschlüsselung nach dem Vigenere-Chiffre
Quelltext:
50
54
100
50
100
54
100
100
Schlüssel (periodisch):
100
101
102
103
100
101
102
103
Chiffretext:
150
155
202
153
200
155
202
203
Der wesentliche Vorteil dieses Verfahrens liegt darin, dass gleiche Zeichen im Quelltext (in unserem Beispiel Ord(50)) im Chiffretext unter Umständen durch unterschiedliche Zeichen dargestellt werden (Ord(150) oder Ord(153)), je nach Position im Quelltext. Je länger der Schlüssel ist, d.h. je weniger Perioden auftreten, desto sicherer wird das Verfahren, aber auch gleichzeitig unökonomischer. Im Extremfall ist der Schlüssel genauso lang, wie der zu verschlüsselnde Text. Dieses Verfahren wird dann Vernam-Chiffre genannt und ist eines der sichersten – bekannten – Kryptoverfahren, das von vielen wichtigen Institutionen benutzt wird, sofern die Brisanz der Botschaft den Aufwand rechtfertigt. Wie gelangt ein Schlüssel zum Empfänger? Neben der Übermittlung einer Nachricht vom Sender zum Empfänger gibt es das Problem, wie man den Schlüssel sicher übermittelt. Wenn der Schlüssel geknackt oder gestohlen wurde, nützt das beste Verfahren nichts. Daher
1088
Java 2 Kompendium
Wie funktionieren Verschlüsselungsverfahren?
Anhang C
muss der Schlüssel getrennt von der Nachricht über einen möglichst sicheren Weg zum Empfänger gelangen. Oder aber, er wird ganz öffentlich verteilt.
C.2.3
PGP oder wie Java verschlüsselt
Wie ist der eben angeführte Widerspruch zu klären? Eine relativ neue und zuverlässige Verschlüsselungsvariante arbeitet mit zwei Schlüsseln, einem privaten Schlüssel, der nur beim Sender verbleibt, und einem öffentlichen Schlüssel, der verschickt wird. Diesen zweiten Schlüssel darf jeder kennen, denn er wird ausschließlich zum Kodieren einer Nachricht benutzt. Zum Dekodieren kann er nicht verwendet werden. Die Folge ist, dass bis jetzt nur der Empfänger des Schlüssels an den Sender des Schlüssels eine kodierte Botschaft senden kann, die ausschließlich dieser dann mit seinem privaten Schlüssel dekodieren kann. Will der potenzielle Sender eine kodierte Nachricht verschicken, muss er also erst von dem potenziellen Empfänger den öffentlichen Schlüssel erhalten. Dieses Verfahren hat den riesigen Vorteil, dass der Dekodierungsschlüssel niemals verteilt werden muss und es äußerst sicher ist. Es lässt sich auch mit den oben genannten Methoden kombinieren. Man muss aber einen großen Aufwand mit dem Verschicken und Verwalten der verschiedenen Kodierungs-Schlüssel treiben. PGP (Pretty Good Privacy) nutzt beispielsweise das Zweischlüsselsystem (öffentlicher und privater Schlüssel) mit einem 1024 Bit-Schlüssel. In der Vergangenheit gab es bzgl. der Verwendung eines längeren Schlüssels erhebliche Probleme, denn in den USA fallen Verschlüsselungssysteme unter die Exportbestimmungen für militärische Geheimnisse. Aber auch in Deutschland gibt es eine Diskussion, inwieweit überhaupt Verschlüsselungsverfahren benutzt und vertrieben werden dürfen, die interessierte Behörden nicht nach Belieben entschlüsseln können. Offizielles Argument für die Gegner von sicheren Verschlüsselungsverfahren ist, dass auch kriminelle Kreise solche Verfahren nutzen könnten.
C.2.4
Die heutigen Standard-Algorithmen
In der heutigen Verschlüsselungstechnik werden im Wesentlichen drei verschiedene Standards verwendet: DES IDEA RSA
Java 2 Kompendium
1089
Anhang C DES Der Data Encryption Standard (DES) stammt aus den Siebzigerjahren. Zur Verschlüsselung werden 56 Bit verwendet, was zu einer Anzahl von 2 hoch 56 Schlüsseln führt. Es handelt sich um einen symmetrischen Algorithmus mit einem frei wählbaren Schlüssel zum Ver- und Entschlüsseln der Daten. Mithilfe dieses Schlüssels wird der Orginaltext jeweils in 64-Bit-Blöcke umgewandelt. Dies geschieht durch Substitution und Permutation, also das Ersetzen und Vertauschen einzelner Bits nach festen Regeln. In 16 Durchläufen wird die eine Hälfte der Daten mit einem auf 48 Bit reduzierten Schlüssel unter Verwendung einer XOR-Funktion chiffriert, um anschließend mit der anderen Hälfte der Daten verknüpft zu werden. Für jeden Durchlauf wird ein neuer Schlüssel erzeugt. IDEA Der Intenational Data Encryption Algorithm (IDEA) ist ziemlich neu (Beginn der Neunzigerjahre). Er basiert auf einem 128-Bit-Schlüssel, bietet also 2 hoch 128 Möglichkeiten zur Erzeugung des Verschlüsselungscodes. Wie bei DES werden auch hier jeweils 64 Bits der Daten verschlüsselt. IDEA teilt die Originaldaten jedoch nicht in zwei Hälften, sondern benutzt vier Viertel zu je 16 Bit. Diese Blöcke werden mit einem Teil des 128-Bit-Schlüssels in acht Durchläufen verknüpft. Nach den letzten Durchlauf werden die Viertel in einem neunten Durchgang noch einmal mit vier weiteren Teilschlüsseln bearbeitet. Der Schlüssel wird durch Rotation der Bits um 25 Stellen jeweils neu festgelegt. RSA RSA (die jeweils ersten Buchstaben der Nachnamen der Erfinder Rivest, Shamir und Adleman) stammt wie DES aus den Siebzigerjahren. RSA beruht auf der Zerlegung großer Zahlen in ihre Primfaktoren und Moduloverfahren bezüglich dieser Primzerlegung. Die Originaldaten werden nicht in Blöcke unterteilt, sondern wie eine einzige große Zahl behandelt. Es gibt bei dem Verfahren einen zusammengesetzten öffentlichen Schlüssel zum Verschlüsseln und einen privaten Schlüssel zum Entschlüsseln.
C.2.5
Eine kleine Abschlussbemerkung zum Thema
Es ist zwar eine Binsenweisheit, aber jeder sollte sich klar darüber sein, dass es keine absoluten Schutz gegen eine unberechtigte Dekodierung von Informationen gibt. Auch der beste Code ist zu knacken. Durch Zufall. Mit System. Oder mit viel Zeit und genau das ist der springende Punkt: Eine Information hat nur innerhalb einer gewissen Zeitspanne einen Wert. Je länger eine Dekodierung dauert, umso wahrscheinlicher wird die Information keinen Wert mehr für den Kryptoanalyst haben.
1090
Java 2 Kompendium
Von der Dezimalrechnung abweichende Rechenarten
C.3
Anhang C
Von der Dezimalrechnung abweichende Rechenarten
Vielen Lesern dürfte Binär-, Oktal- und Hexadezimalrechnung vertraut sein. Dennoch soll ein kleiner Exkurs noch einmal die Grundlagen diskutieren. Normalerweise nutzt man in der Mathematik die so genannte Dezimalrechnung. Dabei stehen 10 verschiedene Symbole zur Darstellung einer Zahl zur Verfügung: die bekannten Zahlen von 0-9. Dies ist aber relativ willkürlich und auf keinen Fall zwingend. Das in der Computerwelt überall verwendete Binärsystem ist das bekanntete Beispiel.
C.3.1
Binärrechnung
Die Binärrechnung soll nur ganz kurz angedeutet werden. Bei Verwendung der Basis 2 können dementsprechend nur 2 Zustände in einem Zeichen kodiert werden: 0 und 1. Wenn mehr Zeichen dargestellt werden sollen, muss man mehr Stellen nehmen. Das ist im Dezimalsystem (und anderen Systemen wie dem Oktal- oder das Hexadezimalsystem) genauso, was man oft deshalb nicht zur Kenntnis nimmt, da es uns selbstverständlich erscheint (Zahlen, die grö ß er als 9 sind, werden zusammengesetzt: 10, 11, 23456 usw.). Hier folgt eine kleine Tabelle mit den wichtigsten Umrechnungen aus dem Dezimalsystem in das Binärsystem. Dezimaldarstellung Binärdarstellung 0
0
1
1
2
10
3
11
4
100
5
101
6
110
7
111
8
1000
16
10000
32
100000
Java 2 Kompendium
Tabelle C.3: Dezimal versus binär
1091
Anhang C Tabelle C.3: Dezimal versus binär (Forts.)
Dezimaldarstellung Binärdarstellung 64
1000000
128
10000000
255
11111111
C.3.2
Oktalrechnung
Die oktale Darstellung von Zahlen ist nicht so geläufig wie die binäre Darstellung. Allerdings besteht von der Logik her kein wesentlicher Unterschied. Sämtlich Werte werden nur zur Basis 8 dargestellt. Es gibt dementsprechend 8 Zustände, die in einem Zeichen kodiert werden: 0 bis 7. Ab der Zahl 8 erweitert man um eine Stelle, ab der Zahl 64 wieder um eine Stelle usw. Hier folgt eine kleine Tabelle mit den wichtigsten Umrechnungen aus dem Dezimalsystem in das Oktalsystem. Tabelle C.4: Dezimal versus oktal
1092
Dezimaldarstellung Oktaldarstellung 0
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
10
9
11
10
12
11
13
12
14
13
15
14
16
15
17
16
20
Java 2 Kompendium
Von der Dezimalrechnung abweichende Rechenarten
Dezimaldarstellung Oktaldarstellung 17
21
18
22
63
77
64
100
511
777
512
1000
4096
10000
32768
100000
C.3.3
Anhang C Tabelle C.4: Dezimal versus oktal (Forts.)
Hexadezimalrechnung
Die Hexadezimalrechnung ist meist sogar geläufiger als die oktale Darstellung, obwohl hier das Problem besteht, dass mit den herkömmlichen Zahlen 0-9 nicht genug Zeichen zur Darstellung sämtlicher Zeichen der hexadezimalen Darstellung zur Verfügung stehen. Java stellt einer hexadezimalen Darstellung von Zahlen immer ein 0x (oder auch 0X) voran. Sämtlich Werte werden hier nun zur Basis 16 dargestellt. Es gibt dementsprechend 16 Zustände, die in einem Zeichen kodiert werden: 0 bis 9 und noch 6 weiteren Zeichen, die das Dezimalsystem nicht mehr liefert. Man weicht auf das Alphabet aus und verwendet für die fehlenden 6 Zeichen Buchstaben. Meist nimmt man Großbuchstaben, aber Kleinbuchstaben gehen im Prinzip auch. Nach dem Zeichen F, das der Dezimalzahl 15 entspricht, erweitert man um eine Stelle, nach dem Zeichen FF – der Zahl 255 – wieder um eine Stelle usw. Hier folgt eine kleine Tabelle mit den wichtigsten Umrechnungen aus dem Dezimalsystem in das Hexadezimalsystem. Dezimaldarstellung Hexadezimaldarstellung 0
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
Java 2 Kompendium
Tabelle C.5: Dezimal versus hexadezimal
1093
Anhang C Tabelle C.5: Dezimal versus hexadezimal (Forts.)
1094
Dezimaldarstellung Hexadezimaldarstellung 8
8
9
9
10
A
11
B
12
C
13
D
14
E
15
F
16
10
17
11
18
12
19
13
20
14
21
15
22
16
23
17
24
18
25
19
26
1A
27
1B
28
1C
29
1D
30
1E
31
1F
32
20
254
FE
255
FF
256
100
4095
FFF
Java 2 Kompendium
Die Theorie des Zweierkomplements bei ganzen Zahlen
Dezimaldarstellung Hexadezimaldarstellung 4096
1000
65535
FFFF
65536
10000
C.4
Anhang C Tabelle C.5: Dezimal versus hexadezimal (Forts.)
Die Theorie des Zweierkomplements bei ganzen Zahlen
Ganzzahlige Variablen werden in Java allesamt als ZweierkomplementZahlen mit Vorzeichen verwendet. Zweierkomplement ist eine Methode, um negative ganze Zahlen durch Bits darzustellen. Am einfachsten wird eine Erklärung anhand eines Beispiels. Dabei soll ohne Beschränkung der Allgemeinheit ein Datentyp mit 8 Bit (Datentyp byte) herangezogen werden. Jede ganze Zahl wird auf binärer Ebene wie folgt dargestellt. DezimalZahl =
bit8*(2 bit6*(2 bit3*(2 bit1*(2
hoch hoch hoch hoch
7) + bit7*(2 hoch 6) + 5) + bit5*(2 hoch 4) + bit4*(2 hoch 3) + 2) + bit2*(2 hoch 1) + 0)
Beachten Sie, dass (2 hoch 0) = 1 gilt (und nicht = 0)! Beispiele: 3 + + =
= 00000011 = 0*(2 hoch 7) + 0*(2 hoch 6) + 0*(2 hoch 5) 0*(2 hoch 4) + 0*(2 hoch 3) + 0*(2 hoch 2) 1*(2 hoch 1) + 1*(2 hoch 0) 0 + 0 + 0 + 0 + 0 + 0 + 2 + 1
5 + + =
= 00000101 = 0*(2 hoch 7) + 0*(2 hoch 6) + 0*(2 hoch 5) 0*(2 hoch 4) + 0*(2 hoch 3) + 1*(2 hoch 2) 0*(2 hoch 1) + 1*(2 hoch 0) 0 + 0 + 0 + 0 + 0 + 4 + 0 + 1
7 + + =
= 00000111 = 0*(2 hoch 7) + 0*(2 hoch 6) + 0*(2 hoch 5) 0*(2 hoch 4) + 0*(2 hoch 3) + 1*(2 hoch 2) 1*(2 hoch 1) + 1*(2 hoch 0) 0 + 0 + 0 + 0 + 0 + 4 + 2 + 1
Nehmen wir uns nun das Beispiel 7 vor. Die letzten drei Bit sind auf den Wert 1 gesetzt, alle davor auf den Wert 0. Wie kann man aber nun einen negativen Wert wie -7 darstellen?
Java 2 Kompendium
1095
Anhang C Der wahrscheinlich offensichtlichste Ansatz ist wohl, ein Bit (naheliegenderweise das erste, also das am weitesten links stehende) als Vorzeichen-Bit zu verwenden. Etwa, wenn es den Wert 1 hat, die Zahl als negativ zu interpretieren und wenn es den Wert 0 hat, als positiv. Alles andere (sprich die restliche Darstellung der Zahl) bliebe gleich. Dieser Ansatz hat Einiges für sich, aber den wesentlichen Nachteil, dass in dem Fall sämtliche arithmetischen Operationen für Ganzzahlen kompliziert würden. Die Methode der Zweierkomplement-Arithmetik stellt wesentlich einfachere Algorithmen für binäre Arithmetik und Typkonvertierung zur Verfügung. Man kann wie folgt vorgehen: Stellen Sie eine Zahl positiv da und ziehen Sie davon den Wert 1 ab. Beispielsweise die Zahl 256, und davon 1 abgezogen ergibt 255. Binär ist 256 in 2 Byte darzustellen und sieht so aus: 0000000100000000. Davon 1 (triviale Binärdarstellung 00000001) abgezogen ergibt binär 11111111 = 255. Uns interessiert nur, was im letzten Byte passiert ist. Übertragen wir die Situation auf das letzte Byte: 00000000 – 00000001 = 11111111 Dies heißt jetzt dezimal 0 – 1 = -1. Wir haben die Darstellung von einer negativen Zahl. Wenn wir nun den Vorgang einfach weiter fortsetzen, werden wir die Darstellung aller negativen Zahlen bekommen. Tabelle C.6: Binärrechnungen
Dezimal:
-1
-
1
Binär:
11111111
-
00000001
Dezimal:
-1
-
2
Binär:
11111111
-
11111110
Dezimal:
-1
-
3
Binär:
11111111
-
11111101
Dezimal:
-1
-
4
Binär:
11111111
-
11111100
= = = = = = = =
-2 11111110 -3 11111101 -4 11111100 -5 11111011
Es ist offensichtlich, dass zur Darstellung einer negativen Zahl nur von der analogen positiven Zahl (dem positiven Komplement) die Zahl 1 abgezogen und dann sämtliche Bits umgedreht werden müssen. Diese Aufteilung des Wertebereichs in negativen und positiven Anteil ist auch der Grund, warum beispielsweise in einem Byte Werte von -128 (= – 2 hoch 7) bis 127 (= + (2 hoch 7) – 1) dargestellt werden. Die Null zählt noch zum positiven Anteil. In Java hat dies dann auch die zwangsläufige Folge, 1096
Java 2 Kompendium
Farbangaben in Java und JavaScript
Anhang C
dass das am weitesten links stehende Bit als Vorzeichenbit dient. Wenn das Vorzeichenbit den Wert 1 hat, dann ist der Wert negativ, sonst positiv. So ganz falsch war also unser ursprünglicher Denkansatz nicht, nur musste er ein wenig erweitert werden. Dies führt beispielsweise bei Operationen auf Byte-Variablen zu einigen auf den ersten Blick überraschenden Ergebnissen: 127+1=-128 127+9=-120 127+127=-2
C.5
Farbangaben in Java und JavaScript
Wenn man Farbangaben in Java und JavaScript (oder auch HTML) vornehmen will, hat man normalerweise zwei Varianten zur Definition: Die Angabe der so genannten RGB-Werte (RGB = Rot/Grün/Blau) der Farbe in Hexadezimalform oder in dezimaler Form mit jeweils dem Rot-, Grün- und Blau-Wert als eine Zahl zwischen 0 und 255 Die Angabe eines Farbnamens
C.5.1
Die direkte Angabe eines Farbnamens
Wenn Sie eine Methode, Funktion oder Variable finden, wo Farbangaben eine Rolle spielen und Sie einfach einen standardisierten Namen verwenden können, sind Sie in einer recht glücklichen Situation. Die Eingabe eines Farbnamens ist einfach – es sind die normalen, englischen Farbbezeichnungen. Da es aber noch keine standardisierten Farbnamen gibt, ist die Interpretation der Farbangabe häufig vom Darstellungsmedium – etwa einem Browser bei HTML-Seiten oder JavaScript – abhängig. Wenn das Darstellungsmedium einen Farbnamen nicht kennt, wird es sie nicht darstellen können. Außerdem gibt es nicht für jede denkbare Farbnunance (16,7 Millionen Farben) einen Namen. Flexibler ist da schon die Angabe eines hexadezimalen RGB-Werts.
C.5.2
Die Farbangabe mittels RGB-Werten in Hexadezimalform
Die hexadezimale Variante einer Farbangabe hat den Vorteil, unabhängig vom Darstellungsmedium zu sein, und es stehen im Prinzip 16,7 Millionen Farben zur Verfügung. Die Farben müssen aus hexadezimalen Angaben zu den drei Grundfarben Rot, Grün und Blau zusammengestellt werden. Dabei ist jede hexadezimale Farbdefinition 6-stellig. Die ersten beiden Stellen sind der Rot-Wert, die Stellen drei und vier der Grün-Wert und die letzten beiden Stellen beschreiben den Blau-Wert.
Java 2 Kompendium
1097
Anhang C Eine hexadezimale Ziffer hat bekanntlich 16 Zustände. Für jeden Farbwert (Rot, Grün, Blau) stehen 2 Stellen zur Verfügung. Das macht 16 x 16 (= 256) mögliche Zustände pro Farbwert. Aus diesen 256 Farbnuancen pro Einzelfarbe ergibt sich die Gesamtzahl der Farbzustände (256 * 256 * 256 = 16777216) durch Mischen der einzelnen Farbnuancen entsprechend ihrem Anteil. Wenn wir die RGB-Werte in dezimaler Form (jeweils 2 Byte mit hexadizmalen Werten ergeben den Wertebereich von 0 bis 255) verwenden, erhalten wir die folgenden Beispiele: Tabelle C.7: Farbangaben
Farbe
Standardfarbname
Rot-Wert
Grün-Wert
Blau-Wert
Weiß
Color.white
255
255
255
Hellgrau
Color.lightGray
192
192
192
Grau
Color.gray
128
128
128
Dunkelgrau
Color.darkGray
64
64
64
Schwarz
Color.black
0
0
0
Rot
Color.red
255
0
0
Rosa
Color.pink
255
175
175
Orange
Color.orange
255
200
0
Gelb
Color.yellow
255
255
0
Grün
Color.green
0
255
0
Magenta
Color.magenta
255
0
255
Cyan
Color.cyan
0
255
255
Blau
Color.blue
0
0
255
C.6
Erläuterung der Kurzschreibweisen von Operatoren
Die Kurzschreibweise von Operatoren ist eines der C-Erbstücke, die sicher nicht jeder sofort eingängig findet. Wem die verkürzte Schreibweise von Operatoren nicht ganz so vertraut ist, sollen die Operatoren +=, -=, *=, /= anhand von Beispielen und ihrer ausgeschriebenen Langform erläutert werden.
1098
Java 2 Kompendium
Java-Quellen im Internet
Anhang C
Operator
Beispiel
Langform
+=
n += 42
n = n + 42
-=
n -= 42
n = n – 42
*=
n *= 2
n = n * 2
/=
n /= 4
n = n / 4
%=
n %= 5
n = n % 5
&=
n&=1
n=n&1
|=
n|=1
n=n|1
^=
n^=2
n=n^2
2
>>>=
n>>>= 3
n=n>>>3
C.7
Tabelle C.8: Kurzschreibweisen für Operatoren
Java-Quellen im Internet
Selbstverständlich ist die Java-Adresse http://java.sun.com. Aber auch jenseits davon lohnt es sich zu schauen. Hier folgen einige Quellen rund um Java. Die angegebenen Links können sich in der Aktualität durchaus überholen und als tote Links herausstellen. Das Internet lebt halt. Java-Quellen im Internet gibt es wie Sand am Meer. Selbstverständlich ist Sun mit seinen Töchtern die erste Wahl, wenn Sie Orginalinformationen zu Java suchen. Aber auch andere große Firmen stellen Informationen zu Java zur Verfügung, wenn sie diese Technik unterstützen. Diese Informationen sind aber fast immer in Englisch. Es gibt aber auch zahlreiche deutsche JavaQuellen im Internet. Die deutschsprachige Java-Seite – Kaffee & Kuchen – finden Sie unter http://java.seite.net/. Dort gibt es zahlreiche Informationen rund um Java. Vor allem finden Sie dort Querverweise zu den interessantesten Java-Quellen im deutschsprachigen Raum. Das Java House unter http://www.bodo.com/java.htm sollten Sie sich einmal ansehen, wenn Sie kostenlose Applets suchen, die Magdeburger Java-Seite (http://java.cs.unimagdeburg.de/), wenn Sie eine umfangreiche Linkliste mit Dokumentationen, Tools, News, Mailing Lists, FAQs, Java-Verzeichnisse und Downloads benötigen.
Java 2 Kompendium
1099
Anhang C Selbstverständlich bieten sich die großen Suchdienste als Einstieg zu diverse Quellen für Applets und zahlreiche weitere Java-Informationen an. Als Beispiel sei hier nur Yahoo, der Urvater der Suchmaschinen angeführt, der sogar eine spezielle Java-Seite führt (http:// www.yahoo.com/Computers_and_Internet/ Programming_Languages/Java/). Viele Anregungen zur Erstellung von eigenen Applets können Sie sich von fremden Applets holen. Da viele der Seiten mit Applets auch die Orginalquelltexte beinhalten, kann man da viel lernen. Aber natürlich auch viel Spaß haben, denn es finden sich viele schöne Programme dort. Wenn Sie sich für Chaos-Theorie und Fraktale interessieren, ist die Seite http://www.student.nada.kth.se/~d94-rol/fractals/javaapps.html sicher sehr hilfreich. Sie finden dort eine echtzeitberechnete Juliamengenanimation, die wie die bekannteren, verwandten Apfelmännchen zu der Fraktaltheorie gehört. Dass Java nicht unbedingt zu den Performance-Killern (positiv gemeint) gehört, muss leider zugegeben werden. Wenn Sie die Geschwindigkeit Ihres Java-Runtime-Systems, inkl. Garfikspeed, Speicher usw. testen wollen, hilft Ihnen das BenchBeans-Applet (http://www.cs.tu-berlin.de/~mondraig/ english/benchbeans.html). Sowohl optisch als auch als wissenschaftliche Demonstration sehr spannend ist der NPAC Visible Human Viewer ( http://www.npac.syr.edu/projects/ vishuman/VisibleHuman.html). Dort können Sie hier einen Menschen in Form einer Simulation in Scheiben schneiden. Basic und Java miteinander zu verbinden scheint erstmal so, als wolle man eine Ente gegen einen Ferrari antreten lassen. Zwar ist eine Ente bedeutend schöner, orgineller und praktischer, aber hat im Rennen doch keine Chance. So scheint das wohl auch mit einer Basic-Java-Verbindung zu sein. Im Ernst, da gibt es eine BASIC-Implementation in Java für diejenigen, die keine Lust haben, Java zu lernen und dennoch Java-Applets erstellen wollen. Sie nennt sich HotTea (http://www.mbay.net/~cereus7/HotTEA.html). Skurril, aber dennoch faszinierend.
1100
Java 2 Kompendium
D
Anhang D
Anhang D gibt noch einmal einen komprimierten Überblick über die Neuerungen der Java-2-Plattform.
D.1
Neuerungen der Java-2-Plattform
Wie auch die letzten Wechsel des JDK hat der Wechsel vom JDK 1.2 auf das JDK 1.3 zahlreiche Neuerungen mit sich gebracht. Und das, obwohl beide zur Java-2-Plattform gezählt werden. Aber glücklicherweise sind diesmal die massiven Umstrukturierungen ausgeblieben, die den Wechsel vom JDK 1.1 auf das JDK 1.2 so chaotisch gemacht haben. Die meisten Veränderungen im JDK 1.3 sind Erweiterungen. Etwa die in Anhang B beschriebenen neuen Pakete, die hier nochmals kurz angegeben werden sollen. Neu im API des JDK 1.3 sind folgende Pakete: java.awt.im.spi javax.naming javax.naming.directory javax.naming.event javax.naming.ldap javax.naming.spi javax.rmi javax.rmi.CORBA javax.sound.midi javax.sound.midi.spi javax.sound.sampled javax.sound.sampled.spi javax.transaction org.omg.CORBA_2_3 org.omg.CORBA_2_3.portable org.omg.SendingContext org.omg.stub.java.rmi
Aber auch darüber hinaus gibt es ein paar bemerkenswerte Neuerungen, die wir hier nicht alle im Detail ansprechen können und wollen. Dafür ist die Online-Dokumentation viel besser geeignet, zumal sich laufend in Details weitere Veränderungen ergeben. Ein paar wichtige Schlaglichter sollen dennoch aufgeführt werden.
Java 2 Kompendium
1101
Anhang D Das Java Naming and Directory Interface (JNDI), das vorher nur als Erweiterung bereitstand, zählt nun direkt zur Java-2-Plattform. Dies spielt für den erweiterten Einsatz von Dingen wie CORBA Object Services und RMI eine Rolle. Aber auch direkt im Bereicht Remote Method Invocation (RMI) gab es ein paar kleinere, aber durchaus interessante Veränderungen. So hat die Klasse java.rmi.server.RMIClassLoader eine neue Methode (getClassLoader()) und Strings jenseits von 64 K können serialisiert werden (das gilt allgemein für die Serialisation). Auch die Tools für die Arbeit mit RMI wurden geringfügig modifiziert. rmic hat einigen neue Optionen bekommen und rmid fordert eine Security-Policy-Datei. Dazu kommt, dass RMI CORBAs IIOP-Kommunikationsprotokoll verwenden kann. Beim Drag&Drop unter Java gab es nur kleine Erweiterungen, aber beim Java Sound mit seiner Sound-Engine gibt es ein vollständig neues API. Damit können die Audioformate AIFF, AU und WAV und die Musikformate MIDI Type 0, MIDI Type 1 und Rich Music Format (RMF) verwendet werden. Auch in Hinblick auf die Sampling-Rate hat sich viel getan. Für Applets gab es im Wesentlichen Feinschliff für die Performance. Bei Java 2 D gab es dagegen einige Neuerungen, u.a. multiplen Monitor Support über die Klassen Frame(GraphicsConfiguration) und Window(Window, GraphicsConfiguration) und dynamisches Laden von Fonts. Auch Swing und das AWT wurden erheblich erweitert. Der Umfang der Erweiterungen sprengt bei weitem den Rahmen dieses Buchs. Besonders erwähnenswert ist dabei die Einführung einer Klasse zum Generieren von nativen Systemen für Eingabe-Events (Robot) und die Überarbeitung der Druckmöglichkeiten von Java im AWT-API. Mit dem neuen Konzept sind hier zahlreiche neue Klassen eingeführt worden: JobAttributes JobAttributes.DefaultSelectionType JobAttributes.DestinationType JobAttributes.DialogType JobAttributes.MultipleDocumentHandlingType JobAttributes.SidesType PageAttributes PageAttributes.ColorType PageAttributes.MediaType PageAttributes.OrientationRequestedType PageAttributes.OriginType PageAttributes.PrintQualityType
1102
Java 2 Kompendium
Neuerungen der Java-2-Plattform
Anhang D
Auch im Bereich Sicherheit, Serialization und der Arbeit mit Netzwerken hat das JDK 1.3 viele Detailerweiterungen erfahren, deren Details hier nicht besrochen werden können. Zum Thema Accessibility kann man als Schlaglicht anführen, dass diverse neue Klassen zur Java-2-Plattform hinzugefügt wurden (AccessibleIcon, AccessibleRelation, AccessibleRelationSet, AccessibleTable, AccessibleTableModelChange). Ansonsten halten sich die Neuerungen in der API des JDK 1.3 jedoch in Grenzen (mit Ausnahme der zahlreichen neuen Pakete, die in Anhang B angesprochen werden). Allgemein hat Sun mit dem JDK 1.3 wieder versucht, ein großes Problem von Java weiter zu entschärfen – die Performance. Wichtigster Schritt in Hinblick auf eine bessere Performance ist die Hinzufügung der Java HotSpot Client Virtual Machine zu dem SDK. Diese bewirkt eine verbesserte Startup-Zeit, Speicheroperation und Programmausführung. Für den Tool-Support (also die Unterstützung von Programmen, die das JDK nutzen) wurden mit dem Java Platform Debugger Architecture (JPDA) drei Schnittstellen bereitgestellt, die Debugger in fremden Entwicklungsumgebungen verwenden können. Bei den JDK-Tools selbst ist besonders erwähnenswert, dass der Compiler komplett neu reimplementiert wurde und nun bedeutend schneller ist. Die Tools jarsigner und keytool bekamen eine neue Option und das JarTool unterstützt nun die Indizierung von Jar-Dateien. Damit wird der Zugriff auf diese hochkomprimierten Dateien schneller und einfacher.
Java 2 Kompendium
1103
Stichwortverzeichnis
! <APPLET>, Einbindung von Applets 349 <EMBED>, Einbindung von Applets 358 , Einbindung von Applets 360 <SERVLET> 868 2D-API, Grundsätzliches 481 2D-Geometrie 971 2D-Java Operationen auf Bildern 506 Texte 503 2-Tier-System 853 3D-Rechteck zeichnen 425 3-Tier-System 853 A Abfragen von Fonts 448 Abgerundete gefüllte Rechtecke 426 Abgerundete Rechtecke 426 Abrufen von Farbinformationen 444 Abspielen einer Animation 458 abstract, Methoden 307 Abstract Window Toolkit Siehe AWT AbstractMethodError 987 Abstrakte Klassen 160, 282 Abstrakte Methoden 307 accept() 721 Sockets 876 Accessibility 49 AccessibleObject, Reflection 830 action(), Methode 607 actionPerformed(), Methode 615 activation system daemon 410, 937 Activation-Framework 937 Activator 35 activeCount() 400, 407 activeGroupCount() 407 ActiveX-Bridge 837 Java 2 Kompendium
ActiveX-Controls Sicherheitskonzept 766 Vergleich zu Java Beans 837 Adapterklassen 289 add(), Methode 526 addImage(), MediaTracker 455 addItem(), Methode 555 Addition von Zeichenketten 199 Ad-hoc-Typkonvertierungen 250 Advanced Research Projects Agency 58, 69 Ändern von Elementen in Datenfeldern 239 Affine Transformation 487, 501 AffineTransform 501 afterLast(), Datenbanknavigation 891 all, JavaScript-Objekt 807 allowsMultipleSelections(), Methode 564 Alphachannel 478, 494 AlphaComposite 503 anchor, JavaScript-Objekt 807 Andreessen, Marc 61 A-Netz 67 Animation 417, 457 Abspielen 458 Animationsrahmen 458 Clipping 474 Double-Buffering 476 Flimmereffekte 468 Überschreiben der update()-Methode 468 Anonymous Classes 46, 287 Anpassung einer Applikation an verschiedene Länderstandards 40 ANSI SQL92 EntryLevel 903 Antialiasing 500 Anweisungen 258 Anweisungsarten 259f. Anwender-Koordinatenraum 479 Anzeigen von Bildern 452 1105
Stichwortverzeichnis Apache 854 Apfelmännchen 439 appendText(), Methode 571 Applet Bilder 373 dynamisch mit Scripten schreiben 823 Einbindung von 343 Grundmethoden 364 Initialisierung 364 Interaktion 375 interne Arbeitsweise 363 Leben eines 140 Mausereignisse 379 Multithreading-fähig machen 388, 404 Musterapplet als Schablone 366 paint() 368 serverseitige Siehe Servlets Sound 375 Start 365 Stop 365 Tastaturereignisse 384 Unterschrift 364 wichtige Methoden 367 Zerstören 365 applet, JavaScript-Objekt 808 Applet can’t start 115 Applet not initializied 115 AppletContext 376 Applet-Erstellung, Grundlagen 341 Applet-Klasse 367 Applet-Referenzierung, HotJava-Syntax 363 Appletviewer 121 Interne Arbeitsweise 124 Menü 123 appletviewer_g 118 Applikationen und Applets, Unterschiede 137 Architekturneutral 173 Architekturunabhängig Siehe plattformunabhängig Argumentliste, Vergleich Java zu C/C++ 783 ArithmeticException 985 Arithmetische Operatoren 201 Arithmetische Zuweisungsoperatoren 206 ARPA 58 ARPANET 58 ARPNET Siehe ARPANET
1106
Array 235 dynamische 238 JavaScript 802 JavaScript-Objekt 808 mit allgemeinen Objekten 242 Reflection 830 Vergleich Java zu C/C++ 778 ArrayIndexOutOfBoundsException 985 Arrays, verschachtelte 241 ArrayStoreException 680, 985 ASCII-Code 185 Audio-Unterstützung, Neuigkeiten 47 Aufbau eines Animationsrahmens 458 Auflösung von Namensräumen bei Bezeichnern 195 Ausdrucksanweisungen 259, 264 Ausdrücke und Operatoren 245 Ausführungsumgebung 177 Typzustand 761 Ausgabe-Koordinatenraum 479 Ausnahme ArithmeticException 985 ArrayIndexOutOfBoundsException 985 ArrayStoreException 985 ClassCastException 985 ClassNotFoundException 985 CloneNotSupportedException 985 IllegalAccessException 985 IllegalArgumentException 985 IllegalStateException 986 IllegalThreadStateException 986 in Schnittstellen 321 IndexOutOfBoundsException 986 InstantiationException 986 InterruptedException 986 NegativeArraySizeException 986 NoSuchFieldException 986 NoSuchMethodException 986 NullPointerException 986 NumberFormatException 986 RuntimeException 986 SecurityException 986 selbstdefinierte 687 StringIndexOutOfBoundsException 986 UnsupportedOperationException 986 Ausnahmebehandlung 675
Java 2 Kompendium
Stichwortverzeichnis Ausnahmen-Handling, explizites 680 Auswahlanweisung 259, 265 Automatische Speicherbereinigung 177 available(), Daten einlesen 702 AWT 517 Bildlaufleisten 572 Container 523, 525 Eventmodelle 605 Komponenten 522 Kontrollkästchen 545 Label 543 Layoutmanager 524 Listen 554 Menüs 580 Neuigkeiten 42 Optionsfelder 545 Panels 526 Schaltflächen 538 Textbereiche 566 Textfelder 566 Zeichenbereiche 578 Zusammenfassende Beschreibung 521 AWT Drawing Model 480 AWTEvent, Klasse 612 AWTLayoutmanager 590 B Bad command or filename 104 BDK 46, 838 BeanBox 838 Beans 832, 977f. Befehlszeilenargumente, Vergleich Java zu C/C++ 783 beforeFirst(), Datenbanknavigation 891 Benutzer-Threads 409 Berners-Lee 60 Bewertung von Ausdrücken 246 Bewertungsreihenfolge 248 Bezeichner 192 Namenskonventionen 192 Bezeichnete Anweisung 259, 261 Bildlaufleisten 522, 561f., 566, 572f., 575ff., 621 AWT 572 Swing 644 Binärrechnung 1091 Binden 165
Java 2 Kompendium
Bitweise Arithmetik 206 Bitweise arithmetische Operatoren 201, 206 Bitweise Verschiebungsoperatoren 201, 211 Bitweise Zuweisungsoperatoren 201, 213 Bitweiser And-Operator (&) 207 Bitweiser Komplement-Operator (~) 210 Bitweiser OR-Operator (|) 209 Bitweiser Xor -Operator (^) 209 Blockanweisungen 259 Blöcke 261 B-Netz 67 Boolean, JavaScript-Objekt 808 Boolesche Literale 200 Boolesche Werte, Vergleich Java zu C/C++ 780 bootstrap Classpath 108 BorderLayout, Klasse 600 Botschaften 155 break-Anweisung 272 bezeichnete 273 unbezeichnete 272 BufferedInputStream 709 BufferedOutputStream 709 Bug 668 Button Klasse 538 Swing 631 ByteArrayInputStream, Datenfeldströme 707 ByteArrayInputStream(), Daten einlesen 707 ByteArrayOutputStream, Datenfeldströme 707 Bytecode 82 Bytecode-Strom 175 Bytecode-Verifier 761 C C/C++ Ahn von Java 79 Unterschiede zu Java 777 Cäsar-Chiffre 724, 1086 call(), Aufruf von JavaScripten 816 Can't make a static reference to nonstatic..., Fehlermeldung 306 Can’t find class 112 cancel(), Drucken 749 canRead() 719 Canvas, Klasse 578 canWrite() 719
1107
Stichwortverzeichnis CardLayout, Klasse 603 Casting 187, 250 Casting-Operator 250 catch 276, 681 Cedar/Mesa-System 85 CERN 60 CGI 78, 854 Chaostheorie 440 charWidth() 450 C-Header-Dateien 909 checkAll(), MediaTracker 457 Checkbox, Klasse 546 CheckboxGroup, Klasse 548 CheckboxMenuItem, Klasse 581 checkConnect() 874 checkid(), MediaTracker 457 Choice, Klasse 555 Class not found 112 ClassCastException 985 ClassCircularityError 987 classes.zip 93 ClassFormatError 987 CLASSID, Sicherheitskonzept ActiveX-Controls 769 Classloader 756, 762 ClassNotFoundException 680, 985 CLASSPATH 105, 116 CLASSPATH-Bug 773 clear(), Methode 562 clearRect() 423 Client-Server-Architektur mehrschichtige 843 zweischichtig 842 Client-Stubs, CORBA 847 Clipping 474 clipRect() 474 CloneNotSupportedException 985 close() Beispiel 726 Daten einlesen 704 Daten schreiben 707 CMYK, Farbraum 506 C-Netz 67 CODEBASE 115 Codec 514 Collections 244 Color 506
1108
Color-Klasse 435 COM 767 Common Gateway Interface Siehe CGI Common Object Request Broker Architecture Siehe CORBA Component, Drucken 745 Component Object Model Siehe COM componentAdded(), Methode 614 componentRemoved(), Methode 614 connect() 714 Constant Pool 178 Constructor, Reflection 830 Constructors 289 Container AWT 523, 525 HTML 345 ContainerListener, Schnittstelle 614 continue-Anweisung 273 controlDown() 386 Controls 768 copyArea() 424 CORBA 45, 844 Could not read properties file 116 countItems(), Methode 556, 564 createImage() 507 currentThread() 400 D Daemon Siehe Dämonen Dämonen 409 Dämon-Threads 409 Darstellung von Zeichen aus einem Zeichen- oder einem Byte-Datenfeld 445 Data Encryption Standard 1090 Datagram 878 DatagramPacket 880 DatagramSocket 879 Datagram-Sockets 878 DataInput 699, 710 Beispiel 699, 706, 724 DataInputStream 710, 712 Beispiel 699, 706, 724 DataOutput 699, 710, 712 Beispiel 706, 724 DataOutputStream 710, 712 Beispiel 706, 724
Java 2 Kompendium
Stichwortverzeichnis Date, JavaScript-Objekt 808 Dateien löschen 720 Datenbank 880 Löschen 901 Selects 894 Update 897 Datenbankunterstützung 44 Datenbankzugriff, Access 891 Datenfelddeklaration 263 Datenfelder 235 Deklarieren 236 Erstellen 237 Datenkapselung 154, 757, 820 Datentypen 188 JavaScript 801 Vergleich Java zu C/C++ 780 dbx 915 DCE 844 DCOM 767, 844 DDE 767 Deadlock, Multithreading 413 Debuggen, Applets 919 Debugger Arbeit mit einem 673 Direkter Aufruf 917 Folgeprozess des Interpreters 918 Vorbereitung einer Debugger-Sitzung 916 Debugging 668 Deklaration 259, 262 einer Methode 303 einer Schnittstelle 318 primitiver Typen 264 Deklarieren von Datenfeldern 236 Dekrementoperator 201, 204 Delegates 520 delete() 720 delItem(), Methode 562 delItems(), Methode 562 DE-NIC 65 deprecated 39 DES 1090 deselect(), Methode 563 destroy() 140, 398 Destruktor 297 Deutsches Network Information Center 65 Dialog, Klasse 527, 533
Java 2 Kompendium
Dienstprotokolle 60 Digital Signature Algorithm Siehe DSA Digital Signing Tool 929 disable(), Methode 539 Disassemblierung, Bytecode 906 Disk And Execution Monitor 409 dispose(), Methode 529 Distributed Component Object Model Siehe DCOM Distributed Computing Environment Siehe DCE DNS 68 DNS-Bug 773 DNS-Konzept 68 do-Anweisung 270 document, JavaScript-Objekt 808 doDelete(), Servlets 865 doGet(), Servlets 864 Dokumentations-Tool 911 Domain Name System Siehe DNS doPost(), Servlets 864 doPut(), Servlets 864 DOSKEY 119 Double-Buffering 476 do-while-Anweisung 270 Drag & Drop API 50 Drag&Drop 967 draw3DRect() 425 drawArc() 433 drawImage() 373, 452 drawLine() 421 drawOval() 431 drawPolygon() 428 drawRoundRect() 426 drawString() 445 Drucken 746 Drucken 697, 744 Druckvorschau 478 DSA 930 Duke 74 Dynamisches Binden Siehe Spätes Binden E Early Binding 165 echoCharIsSet(), Methode 571 ECMA-262-Norm, JavaScript 1070 Eiffel, Ahn von Java 79 Einbindung von Java-Applets in HTML-Seiten,
1109
Stichwortverzeichnis Grundlagen 343 Einfachvererbung 157, 162 Einstellige arithmetische Operatoren 203 Emulation 174 enable(), Methode 539 enumerate() 407 Enumeration 245 EOFException 710 Beispiel 700 Ergänzungstasten 386 err, System 713 Error 987 Klasse 679 Errors trappable 675 untrappable 672 Errors java.lang 987 Erstellen eines Applets 364 eines Pakets 335 von Datenfeld-Objekten 237 von Fontobjekten 445 von Schnittstellen 318 Erweiterung einer Klasse mit Thread 394 von Schnittstellen 319 Erzeugung eines Datenfeldes mit dem new-Operator 237 European Organisation for Nuclear Research 60 eval(), Aufruf von JavaScripten 816 Event, Klasse 607 event, JavaScript-Objekt 808 Event-Handler 799 Eventhandling 1.0 606 Eventhandling 1.1 Standard-Adapter 632 WindowListener 666 Event-Klasse 385 Event-Listener, Eventmodell 1.1 613 Eventmodell 1.1 611 Eventmodelle, AWT 605 EventObject, Klasse 612 Exception 985 Klasse 679 Exception-Handling, global 678
1110
ExceptionInInitializerError 987 Exceptions 677 selbstdefinierte 687 Vergleich Java zu C/C++ 784 executeQuery() 895 executeUpdate() 897 Execution Environment Siehe Ausführungsumgebung exists() 719 exit(), Methode 529 Explizite Konvertierungen 253 extends 285 eXtensible Markup Language Siehe XML F Farbangaben 434 Farbangaben in Java und JavaScript 1097 Farben setzen 436 Farbraum 506 Fehlerbehandlung, individuell programmierte 676 Festlegungsoperator 253 Field, Reflection 830 FIFO 177 File 718 Beispiel 721 Dateizugriffe 698 file not found 104 FileDescriptor 722 FileDialog, Klasse 537 FileInputStream 721 Beispiel 699, 706 FilenameFilter Beispiel 721 Dateizugriffe – gefiltert 698 FileOutputStream 721 Beispiel 706 fill3dRect() 425 fillArc() 434 fillOval() 432 fillPolygon() 430 fillRect() 423 fillRoundRect() 426 FilterInputStream 709 FilterOutputStream 709 final, Methoden 308 Finale Klassen 281
Java 2 Kompendium
Stichwortverzeichnis Finalisierer 297 Finalisierung 297 finalize() 140, 297 finally 276, 685 First Person 74 first() Datenbanknavigation 891 Methode 604 Flimmereffekte in Animationen 468 FlowLayout, Klasse 593 flush(), Daten schreiben 706 Fonts, 2D Java 503 for-Anweisungen 271 form, JavaScript-Objekt 808 forName() Datenbanktreiber laden 889 Reflection 831 Fraktale 439 Fraktal-Programme 439 Frame, Klasse 527 frame 176 JavaScript-Objekt 808 Freundliche Klassen 280 Freundliche Methoden 303 Frühes Binden 165 Function, JavaScript-Objekt 808 Funktionen 302 G Gamelan 342 Ganzzahlliterale 195 Garbage Collection Heap, theoretischer Aufbau 177 gdb 915 Gefülltes 3D-Rechteck zeichnen 425 Gefülltes Rechteck zeichnen 423 General Inter-ORB Protocol Siehe GIOP GeneralPath 482, 485 Geschützte Methoden 304 getAbsolutePath() 720 getAddress() 875 getAlignment(), Methode 544 getAllByName() 875 getAppletContext() 376 getAppletInfo() 369 getApplets() 377 getAscent() 449 getAudioClip() 375, 510 Java 2 Kompendium
getBoundingBox() 429 getByName() 875 getCheckboxGroup(), Methode 549 getClass(), Reflection 831 getCodeBase() 377, 452 getColumns(), Methode 570 getConfigurations() 508 getConnection(), Datenbankverbindung aufbauen 890 getContentPane(), Swing 626 getCopies(), Drucken 749 getCurrent(), Methode 549 getCursorType(), Methode 530 getDescent() 449 getDeviceConfiguration() 508 getDirectory(), Methode 537 getDocumentBase() 377, 452 getEchoChar(), Methode 571 getFD() 722 getFile(), Methode 537 getFilePointer() 723 getFont() 447, 449 getFontList() 448 getGlyphMetrics() 504 getGlyphOutline() 504 getGraphics(), Drucken 744 getHeight() 450, 454 getHostAddress() 875 getHostName() 874 getImage() 373, 451 Methode 579 getItem(), Methode 556 getLabel(), Methode 539 getLeading() 449 getLineIncrement(), Methode 575 getLineNumber() 716 getLocalHost() 875 getMaximum(), Methode 574 getMaxPriority() 406 getMember(), Zugriff auf JavaScript 817 getMinimum(), Methode 574 getName() 449, 719 Threads 400 getOrientation(), Methode 575 getPageDimension(), Drucken 745 getPageResolution(), Drucken 745 getParameterInfo() 369 1111
Stichwortverzeichnis getParent() 406, 719 getPath() 720 getPrinterJob(), Drucken 749 getPrintJob(), Drucken 744 getPriority() 401 getRows(), Methode 572 getSelectedIndex(), Methode 556, 563 getSelectedIndexes(), Methode 563 getSelectedItem(), Methode 556, 563 getSelectedItems(), Methode 563 getSelectedText(), Methode 569 getSelectionEnd(), Methode 569 getSelectionStart(), Methode 569 getSize() 449 getState(), Methode 547 getStringOutline() 504 getStyle() 449 Getter-Methoden, Java Beans 839 getText(), Methode 543, 569 getTitle(), Methode 530 getToolkit(), Methode 579 getWidth() 454 getWindow(), Zugriff auf JavaScript 817 GIOP, ORB 846 Glasgow 45 Gleichheitsoperatoren 219 Gleitpunktliterale 196 Gleitzahl-Literale 196 Glyph 500, 504 Gosling, James 73 gotFocus(), Methode 610 GradientPaint 502 Graphical User Interface Siehe GUI Graphics2D, Drucken 749 Graphics2D-Objekt, Casten 481 GraphicsConfiguration 508 GraphicsDevice 508 GraphicsEnvironment 508 Graphik 417 Graphische Ausgabemedien 507 Green-Projekt 73 GridBagConstraints, Klasse 598 GridBagLayout, Klasse 598 GridLayout, Klasse 595
1112
Grundgerüst einer HTML-Datei 347 einer HTML-Seite 345 Grundprinzipien der OOP 166 GUI 88 H handleEvent(), Methode 606 Hash-Code 759 Hashtable 244 Heap 177 Hexadezimalrechnung 1093 hide(), Methode 529 Hintergrundfarben 438 history, JavaScript-Objekt 808 Hostidentifikator 66 HotJava 75 HOTJAVA_HOME 116 HOTJAVA_READ_PATH 116 HOTJAVA_WRITE_PATH 116 HotJava-Syntax 363 HotSpot 30 HTML 62 Applet-Referenz mit Pfaden 352 Auflistung aller HTML 4.0 – Attribute 1030 Auflistung aller HTML 4.0 – Befehle 1025 Body & Header 346 Container 345 Graphikbezüge 348 Hyperlink 347 Kommentare 345 Parameter für ein Java-Applet 355 Position des Applets in der Webseite 353 Referenzierung eines Java-Applets 349 wichtige Elemente 347 HTML + Discussion Document 63 HTML 2.0 63 HTML 3.0 63 HTML 3.2 63 HTML 4.0 64 HTML-Grundlagen 343 HTML-Steueranweisungen 344 Huffman-Algorithmus 188, 1078 Hyperlink 347 Hypertext Markup Language Siehe HTML
Java 2 Kompendium
Stichwortverzeichnis I IAB 65 IDE 88 IDEA 1090 Identifier 192 Identities 930 IDL 45, 170, 844 idlj 847 if-Anweisung 265 if-else-Anweisung 266 if-else-if-Anweisungen 266 if-else-Operator 249 IIOP 844 IllegalAccessError 987 IllegalAccessException 680, 985 IllegalArgumentException 985 IllegalMonitorStateException 985 IllegalStateException 986 IllegalThreadStateException 986 image, JavaScript-Objekt 808 ImageIcon 645 Imageobserver 455 immutable, Eventhandling 1.1 612 Implementation von Runnable 403 Implementierung von Schnittstellen in Klassen 322 implements 317 import, Vergleich Java zu C/C++ 781 import-Anweisung 331 in, System 713 IncompatibleClassChangeError 987 IndexOutOfBoundsException 986 InetAddress 874 Information Hiding 154 init() 140 Inkrement-/Dekrement-Operatoren 204 Inkrement-Operator 201, 204 Inner Classes 46, 287 Innere Klassen 287 input method framework 43 InputStream 698 insertText(), Methode 571 inside() 430 Instanceof-Operator 258 InstantiationError 987 InstantiationException 680, 986
Java 2 Kompendium
Instanzen, allgemeine Erklärung 157 Instanzmethoden 305 Instanzvariablen 326 Integer-Literale 195 Integrierte Entwicklungsumgebungen Siehe IDE Intenational Data Encryption Algorithm 1090 Interface Description Language Siehe IDL Interfaces 317 InternalError 987 Internationalisierung 40, 972 Internet 56 Internet Architecture Board Siehe IAB Internet InterORB Protocol Siehe IIOP Internet Protocol Siehe IP Internet Society Siehe ISOC Internet-Topologien 66 InterNIC 65 Interoperabilität 39 Interoperable Object References Siehe IOR interrupt() 397 interrupted() 397 InterruptedException 680, 986 Introspektion, Java Beans 836 Invalid JAVA_HOME 116 InvocationHandler 830 IOR, ORB 845 IP, erstes Auftreten 60 IP-Nummer 66 isAbsolute() 719 isAlive() 398 isBold() 449 isCancelled(), Drucken 749 isDaemon() 411 isDirectory() 718 isEditable(), Methode 570 isEnabled(), Methode 540 isFile() 718 isInterrupted() 397 isItalic() 449 isModal(), Methode 534 ISOC 65 isPlain() 449 isSelected(), Methode 563 isShowing(), Methode 529 Iterationsanweisung 259, 269
1113
Stichwortverzeichnis J JAR, API 1004 jar 924 JAR-Dateien 43 signieren javakey 933 JAR-Files 1075 jarsigner 934 Java architekturneutral 83 Beans 832 Datenbanken 880 Datentypen 188 dezentral 81 Dokumentation 102 dynamisch 86 einfach 80 Herkunft 79 Installation 91 interpretiert 82 klein 81 leistungsfähig 83 Multithreadingfähigkeit 84 objektorientiert 81 offizielle Definition 80 portierbar 83 sicher 83 stabil 82 Verbindung mit JavaScript 811 Zugriff auf JavaScript 816 Java 2D 48 Anzeige von Bildern 493 Drucken 749 Java Archive 43, 924, 1075 JAR 40 Java Archive Tool 924 Java Beans 45 Java Collection Framework 39 Java DataBase Connectivity Siehe JDBC Java Debug Interface 32 Java Debug Wire Protocol 32 Java Development Kit Siehe JDK Java Foundation Classes 478 Java HotSpot Client Virtual Machine 1103 Java Media Framework. 48 Java Media Player 514
1114
Java Naming and Directory Interface Siehe JNDI Java Native Interface 47 Java Native Interface Siehe JNI Java Register 176 Java RMI Activation System Daemon 410 Java Runtime Environment 96 Java Schlüsselworte 190 Java Servlet Development Kit 46, 1017 Java Virtual Machine Profiler Interface Siehe JVMPI Java, 32-Bit-Register 176 Java, architekturneutral 173 Java, Debuggen des Source 915 Java, Debugger 915 Java, Geschichte 73 Java, globale Variablen 172 Java, Heap 177 Java, Konstanten 172 Java, Late Binding 169 Java, manuelle Speicherfreigabe 178 Java, Mehrfachvererbung 169, 317 Java, Polymorphismus 169 Java, primitive Daten 179 Java, Schnittstellenkonzept 170, 317 Java, Verschlüsselung 41 java.applet 960 java.awt 960 java.awt.accessibility 1005 java.awt.color 966 java.awt.datatransfer 967 java.awt.dnd 967 java.awt.event 968 java.awt.font 970 java.awt.geom 971 java.awt.im 972 java.awt.im.spi 973 java.awt.image 973 java.awt.print 976 java.awt.swing 1009 java.awt.swing.event 1014 java.awt.swing.undo 1016 java.bean.beancontext 978 java.beans 838, 977 java.beans.beancontext 838 java.io 979 Ein- und Ausgabe in Java 698 java.lang 983
Java 2 Kompendium
Stichwortverzeichnis java.lang.Class, Reflection 830 java.lang.ref 988 java.lang.reflect 830, 988 java.math 989 java.net 870, 989 java.rmi 991 java.rmi.activation 992 java.rmi.dgc 992 java.rmi.registry 993 java.rmi.server 993 java.security 995 java.security.acl 997 java.security.cert 997 java.security.interfaces 998 java.security.spec 998 java.sql 999 java.text 1000 java.util 1002 java.util.jar 1004 java.util.zip 1004 Java_g 118 Java-Applets, Einbindung von 343 Javac 125 Javac_g 118 Java-Debugger 915 Java-Disassembler 906 javadoc 911 Javadoc_g 118 javadoc-Kommentare 222 javah 909 Javah_g 118 javah-Generator 909 Java-Interpreter 130 Sicherheitsvorkehrungen 131 javakey 929 Java-Klasse, allgemeine Struktur 278 Java-Plug-In 35 HTML-Konverter 37 Java-PlugIn-Tag 358 Java-Programm, Übergabe von Argumenten 144 Java-Quellen im Internet 1099 JavaScript 796 all 807 anchor 807 applet 808 Array 808
Java 2 Kompendium
Boolean 808 Date 808 document 808 ECMA-262-Norm 1070 event 808 form 808 frame 808 Function 808 history 808 image 808 layer 808 link 808 location 808 Math 808 mimeType 808 navigator 808 Number 808 plugin 808 RegExp 808 screen 808 String 809 Style 809 Token 1070 Verbindung mit Java 811 window 809 JavaServer Pages Siehe JSP Java-Stack 176 Java-Token 189 Java-Workshop 75 javax.accessibility 1005 javax.naming 1006 javax.naming.directory 1007 javax.naming.event 1007 javax.naming.ldap 1007 javax.naming.spi 1007 javax.rmi 1008 javax.rmi.CORBA 1008 javax.sound.midi 1008 javax.sound.midi.spi 1009 javax.sound.sampled 1009 javax.sound.sampled.spi 1009 javax.swing 1009 javax.swing.event 1014 javax.swing.undo 1016 Java-Zeichenmodi 450 JButton, Swing 632
1115
Stichwortverzeichnis JCheckBox, Swing 655 JComboBox, Swing 655 jdb 915 jdb_g 118 JDBC 880 JDBC-2.0 44 JDBCODBC.DLL 888 JDBC-ODBC-Bridge 888 JDBC-Typen 887 JDialog, Swing 650 JDK 75, 87 Details 117, 905 Dokumentation 102 JDK 1.1 Lightweight UI Framework 49 JDK, Download 88 JDK, Fehlervorbeugung und Fehlerbehebung 103 JDK, Größ e 90 JDK, Plattformen 87 JFC 478 JFrame, Swing 638 JIT 84 JLabel, Swing 643 JMenu, Swing 644 JMenuBar, Swing 644 JMenuItem, Swing 644 JMF 48, 514 JNDI 1102 JNI 790 Neuigkeiten 47 join() 399 Joy, William 74 JPanel, Swing 643 JPopupMenu, Swing 655 JProgressBar, Swing 644 JRadioButton, Swing 632 JRE 96 JRootPane, Swing 626 JScrollBar, Swing 644 JSDK 30 JSException 816 JSlider, Swing 644 JSObject 816 JSP 859 JTabbedPane, Swing 655 JTextArea, Swing 655
1116
JTextField, Swing 634 JToggleButton, Swing 655 JToolBar, Swing 644 Just-in-Time-Compiler Siehe JIT JVM 174 Aufbau 175 Datentypen 179 Methodenbereich 178 JVMPI 33 K Kestrel 30 keyDown() 384 Methode 611 keytool 934 keyUp(), Methode 611 Klasse 277 Modifier 279 Thread-fähig 394 Klassendeklaration 262 Klassenmethoden 305 Klassenname 285 Klassenvariablen 326 Kodierungsprogramm 723 mit grafischer Oberfläche 729 Körper einer Schnittstelle 319 Kommentare 222 Kommentartypen, Vergleich Java zu C/C++ 783 Kompatibilität & Inkompatibilität 34 Komponenten, AWT 522 Komprimierungsverfahren 1075 Konstanten 329f. Vergleich Java zu C/C++ 783 Konstantenpool 178 Konstruktoren 289 überschreiben 295 Kontrollkästchen, AWT 545 Konvertieren von Objekten 254 von Objekten in Schnittstellen 255 Konvertierung 250 von primitiven Datentypen in Objekte und umgekehrt 255 Koordinatenraum, 2D 479 Koordinatensystem 420
Java 2 Kompendium
Stichwortverzeichnis Kopieren eines Bereichs 424 Kopierprogramm 705 Kurzschreibweisen von Operatoren 1098 L Label AWT 543 Klasse 543 Labels, Swing 643 Laden von Bildern 451 last() Datenbanknavigation 891 Methode 604 lastModified() 719 lastPageFirst(), Drucken 745 Late Binding Siehe Spätes Binden Laufstatus von Threads verändern 397 Laufzeitfehler 672, 675 layer, JavaScript-Objekt 808 Layoutmanager, AWT 524, 590 LDAPv3 1007 Leben eines Applets 140 Leere Anweisung 259, 261 LineNumberInputStream 716 Linien zeichnen 421 link, JavaScript-Objekt 808 LinkageError 987 Linken 165 List, Klasse 559 list() 720 Listen, AWT 554 Listener, Eventmodell 1.1 613 Literale 195 LiveConnect 811 LiveScript 796 Local Level Domain 68 location, JavaScript-Objekt 808 Löschen eines Bereichs 423 Logische Vergleichsoperatoren 201, 219 Lokale Variable 177, 329 loop() 511 Lose Typisierung, JavaScript 800 lostFocus(), Methode 610
Java 2 Kompendium
M makeVisible(), Methode 564 Makros, Vergleich Java zu C/C++ 783 Mandelbrot 439 mark(), Daten einlesen 703 markSupported(), Daten einlesen 703 Marshalling, ORB 846 Math, JavaScript-Objekt 808 Mausereignisse, Applet 379 MAYSCRIPT, Zugriff auf JavaScript 818 McNealy, Scott 73 MediaTracker 455 Mehrfachvererbung 162 Member 830 Menu, Klasse 580 MenuBar, Klasse 580 Menüs AWT 580 Swing 645 MenuItem, Klasse 580 Messages Siehe Botschaften metaDown() 386 Metaklassen 160, 286 Method, Reflection 830 Methoden 302 der Klasse String 200 in Schnittstellen 320 Parameterliste 310 Rückgabewerte 308 synchronisieren 308 Multithreading 413 Zugriffsspezifizierung 303 Methodenaufruf 259 Methodenbereich 178 Methodenmodifier 305 Methodennamen 309 Methodenunterschrift 303 MFC 768 Microsoft Foundation Classes Siehe MFC Migration, JDK-Versionen 118 MILNET 59 mimeType, JavaScript-Objekt 808 mkdir() 720 mkdirs() 720 modal 533
1117
Stichwortverzeichnis Modifier, Reflection 830 Modulo 202 Modulooperator 202 monolithische Systeme 842 Mosaic-Browser 61 mouseClicked(), Methode 614 mouseDown() 379 Methode 611 mouseDrag() 380 Methode 611 mouseEnter() 380 Methode 611 mouseEntered(), Methode 614 mouseExit() 380 Methode 611 mouseExited(), Methode 614 MouseListener, Schnittstelle 614 mouseMove() 380 Methode 611 mousePressed(), Methode 614 mouseReleased(), Methode 614 mouseUp() 379 Methode 611 moveToCurrentRow(), Datenbanknavigation 891 Multicast, Eventhandling 1.1 614 Multidimensionale Datenfelder 241 Multiple Inheritance 162 Multithreading 387 Deadlock 413 Methoden synchronisieren 413 Schutzmaßnahmen 412 Synchronisierte Blöcke 414 Thread-sichere Zugriffe 415 Musterapplet als Schablone 366 N Nachrichten 155 Nachrichtenselektor 161 Namenskonventionen für Klassen 285 für Methoden 310 für Pakete 332 Namensräume 194 Namensregeln für Schnittstellen 318 Namens-Server 71 NaN 179, 225 1118
National Center for Supercomputing Applications Siehe NCSA National Science Foundation 59 native 785 Native Methoden 308 native2ascii 927 Nativer Code, Einbindung 784 Native-To-ASCII Converter 927 Naughton, Patrick 73 navigator, JavaScript-Objekt 808 NCSA 61 NegativeArraySizeException 986 net.socketException: errno = 10047 115 Netscape Server API 854 Network Information Center 65 Netzwerkidentifikator 66 Netzwerkoperationen, API 989 Netzwerkzugriffe 870 new, Vergleich Java zu C/C++ 781 next() Datenbanknavigation 891 Methode 604 nextElement() 377 Nextstep 520 nextToken() 717 Nichtstandardoptionen, JDK 119 NoClassDefFoundError 987 non-modal 533 Non-Standard-Options 52 JDK 119 NoSuchFieldError 987 NoSuchFieldException 986 NoSuchMethodError 987 NoSuchMethodException 680, 986 Not a Number 179 NSAPI 854 NSF 59 NullPointerException 986 Number, JavaScript-Objekt 808 NumberFormatException 986 O Object Application Kernel 74 Object Application Kernel Siehe OAK Object Request Broker Siehe ORB Object Serialization 44, 937
Java 2 Kompendium
Stichwortverzeichnis ObjectInput 699, 715 Objective-C, Ahn von Java 79 Object-Klasse 169, 278 ObjectOutput 699, 715 ObjectOutputStream 715 Objektdeklaration 263 Objekte, allgemeine Erklärung 153 Objektklasse 160 Objektmethoden 153, 305 Objektorientierte Analyse Siehe OOA Objektorientierte Programmierung Siehe OOP Objektorientiertes Design Siehe OOD Objektorientiertheit, Vergleich Java zu C/C++ 784 Objektorientierung 151 von Java 169 Objektströme 715 Objektvariable 326 ODBC 44, 883 Datenbank registrieren 892 Öffentliche (public-) Schnittstellen 318 Öffentliche Klassen 280 Öffentliche Methoden 304 Offscreen-Puffer 507 Oktalrechnung 1092 oldjava 41, 130 OLE 767 OOA 167 OOA-Schichtenmodell 168 OOD 168 OOP 152 opcode 175 Open Database Connectivity Siehe ODBC OpenStep 520 openStream() 873 Operandenanzahl 249 Operanden-Stack 177 Operationen mit Booleschen Variablen 226 mit ganzzahligen Variablen 232 mit Gleitkommazahlen 230 mit Zeichenvariablen 227 Operationscode Siehe opcode Operatorassoziativität 246 Operatoren 201, 248 binäre 249 dyadische 249
Java 2 Kompendium
JavaScript 802 monadische 249 Postfixoperatoren 249 Präfixoperatoren 249 tenärer 249 triadischer 249 Vergleich Java zu C/C++ 782 Operatorvorrang 247 Optionsfelder, AWT 545 optop 176 ORB 845 org.omg.CORBA 845 out, System 713 OutOfMemoryError 987 OutputStream 698 Overflow 232 Overloading 311 Overriding 164 P package, Vergleich Java zu C/C++ 781 Packages 331 Pageable, Drucken 748 pageDialog(), Drucken 749 paint() 419 paint-Modus 450 Paket 331 anonymes 336 Panels AWT 526 Swing 643 Parameterliste von Methoden 310 pc 176 Perl 854 Persistent 831 PGP 41, 1089 Pipe 697 PipedInputStream 699, 714 PipedOutputStream 699, 714 Plattformunabhängigkeit auf Quellebene 180 binär 173 play() 511 Plug-In, Java 35 plugin, JavaScript-Objekt 808 PlugIn-Tag 358
1119
Stichwortverzeichnis Pointer Sicherheit 759 Vergleich Java zu C/C++ 777 Policy-Tool 935 Polygone 427 Polymorphismus 164 Position des Applets in der Webseite 353 Post-Dekrement 259 postEvent(), Methode 606 Post-Inkrement 259 Präprozessor, Vergleich Java zu C/C++ 783 Pre-Dekrement 259 Pre-Inkrement 259 PreparedStatement 901 Pretty Good Privacy Siehe PGP previous() Datenbanknavigation 891 Methode 604 Primitiver Datentyp 223 konsistente Größ e 180 print, Drucken 748 print() Drucken 745, 749 PrintStream 713 Printable, Drucken 748 printAll(), Drucken 745 printDialog(), Drucken 749 PrinterGraphics, Drucken 748 PrinterJob, Drucken 748 PrintJob, Drucken 744 println(), PrintStream 714 PrintStream 713 Priorität von Operatoren 221 Private Methoden 305 Program Counter Siehe PC Programmzähler Siehe PC Progressbar, Swing 645 Proxy, Reflection 830 Prozess vom Java-Sourcecode zum Java-Programm 174 Public-Key-Verschlüsselung 41 Punktnotation 331 PushbackInputStream 717
1120
Q Quickinfos für Komponenten 645 R Radiobutton, Swing 631 RandomAccessFile 710, 722 Beispiel 726 Dateizugriffe 698 read(), Einlesen von Datenströmen 701 readBoolean() 711 readByte( 711 readByte(), Beispiel 699, 724 readChar() 711 Beispiel 706 readDouble() 711 readFloat() 711 readFully() 711 readInt() 711 readLine() 711 readLong() 711 readObject() 715 readShort() 711 readUnsignedByte() 711 readUnsignedShort() 711 readUTF() 711 Rechteck zeichnen 422 Rectangle2D.Double 485 Reference Objects 47 Referenzierung eines Java-Applets 349 Referenztypen 236 Reflection 829, 988 ReflectPermission, Reflection 830 RegExp, JavaScript-Objekt 808 Relationale Operatoren 214 Remote Method Invocation Interfaces Siehe RMI Remote Method Invocation Siehe RMI Remote Object Registry 937 Remote Procedure Call Siehe RPC Remote-Prozedurenaufruf Siehe RPC renameTo() 720 Rendering 499 rendering pipeline 499 repaint() 419 replaceItem(), Methode 562 replaceText(), Methode 571 reset(), Daten einlesen 703
Java 2 Kompendium
Stichwortverzeichnis resize(), Methode 528 ResponseStream, Servlets 863 return-Anweisung 274 RGB, Farbraum 506 RGB-Modell 434 RMI 44, 843, 937 RMI Activation System Daemon 937 RMI Stub Converter 936 rmic 936 rmid 937 RMI-IIOP 1008 rmiregistry 937 Router 66 RPC 844 RSA 1090 rt.jar 51, 93 Rückgabewerte, Methoden 308 run() 394 RuntimeError, Klasse 680 RuntimeException 986 RUNTIME-Modul 93 S Sandbox 761 Sandkasten, Java-Sicherheit 761 Schaltflächen, AWT 538 Schieber, AWT 572 Schleifenlokale Variablen 272 Schlüssel, Datenbanken 882 Schlüsselworte 190 Java 190 Schnittstelle 317 Erstellung 318 Implementierung 322 Vergleich Java zu C/C++ 779 Verwendung 323 Schnittstellendeklaration 263, 318 Schutzanweisung 260, 276 Schwarze Witwen 773 screen, JavaScript-Objekt 808 Scrollbar, Klasse 572 ScrollPane, Klasse 577 SDK 87 Second Level Domain 68 SecurityException 986 SecurityManager 125, 756, 763, 874 seek() 723 Java 2 Kompendium
selbstextrahierenden Programme 1082 select(), Methode 555, 563, 569 selectAll(), Methode 570 Selektor 165 SequenceInputStream 716 Serial Version Command 937 Serialization 829 serialver 937 Server Side Includes Siehe SSI Server-Parsing 867 Server-Skeletons, CORBA 847 ServerSocket 795, 874 service(), Servlets 864 ServletContext 862 ServletException 864 ServletInputStream 866 ServletOutputStream 866 Servlets 46, 853 setAlignment(), Methode 544, 594 setBackground() 438 setCheckboxGroup(), Methode 549 setColor() 436, 502 setColumns(), Methode 595 setComposite() 488 setCopies(), Drucken 749 setCurrent(), Methode 549 setCursor(), Methode 530 setDaemon() 411 setEchoCharacter(), Methode 571 setEditable(), Methode 570 setEnabled(), Methode 539 setFont() 447 setForeground() 438 setIcon() 645 setLabel(), Methode 538 setLayout(), Methode 592 setLineIncrement(), Methode 574 setLineNumber() 716 setLookAndFeel(), Swing 627 setMaxPriority() 406 setMenuBar(), Methode 580 setMultipleSelections(), Methode 564 setName(), Threads 400 setPageable(), Drucken 749 setPaint() 485, 502 setPriority() 401 setRenderingHints() 501 1121
Stichwortverzeichnis setResizable(), Methode 531 setRows(), Methode 595 setSize(), Methode 528 setState(), Methode 548 setStub() 378 Setter-Methoden, Java Beans 839 setText(), Methode 543, 569 setTitle(), Methode 530 setToolTipText() 645 setVisible(), Methode 529 setXORMode() 450 SFX-Archive 1082 Shape 485 Sheridan, Mike 73 shiftDown() 386 Short-Circuit-Evaluation 219 show(), Methode 529, 604 showDocument() 376 showStatus(String msg) 370 Sicherheitskonzept 755 Sicherheitsmanager 763 Sicherheitsschnittstelle, Erweiterung 40 Sicherheitstools 929 Signers 930 Single Inheritance 162 Skeletons, CORBA 847 skip(), Daten einlesen 703 skipBytes() 712 Slider, Swing 644 Small Talk, Ahn von Java 79 Socket 795, 844, 874 Datagram 878 serverseitige 876 Software Development Kit Siehe SDK Sound & Töne 510 Spätes Binden 166 Speicherbereinigung 178 in Java chronologische Ablauf 298 Speichermanagement 296 Vergleich Java zu C/C++ 779 Sprunganweisungen 260, 272 SQL 881 API 999 SQL-3-Datentypen 44 Src.jar 93 src.jar 51, 93 1122
src.zip 93 SRC_OVER 503 sRGB 506 SSI 867 Stack 176 StackOverflowError 987 Standard-Adapter, Eventhandling 1.1 632 Standardoptionen, JDK 119 stark typisiert 82 start() 140 Threads 394 static 305 statusAll(), MediaTracker 456 statusID(), MediaTracker 456 stop() 140, 511 Threads 396 StreamTokenizer 699, 717 String, JavaScript-Objekt 809 StringBufferInputStream 699, 708 StringIndexOutOfBoundsException 986 Strings, Vergleich Java zu C/C++ 778 StringTokenizer 699 stringWidth() 450 Ströme gefilterte 708 gepufferte 709 Stroking 502 Strom 697 Structured Query Language Siehe SQL Stub-Dateien 909 Stubs, CORBA 847 Style, JavaScript-Objekt 809 Subklasse 159, 278 super 172, 314 Superklasse 278, 285 allgemeine Erklärung 159 Swing 49, 1009 absolute Positionierung 634 anonyme Klassen zum Eventhandling 643 Applets 629 Applikation auf dem Bildschirm zentrieren 645 Beispiel eines Taschenrechners 662 Bildlaufleisten 644 Button 631 Checkboxen 655 Dialogfenster 650 Eigenständige Applikation 638 Java 2 Kompendium
Stichwortverzeichnis JButton 632 JCheckBox 655 JComboBox 655 JDialog 650 JFrame 638 JLabel 643 JMenu 644 JMenuBar 644 JMenuItem 644 JPanel 643 JPopupMenu 655 JProgressBar 644 JRadioButton 632 JScrollBar 644 JSlider 644 JTabbedPane 655 JTextArea 655 JTextField 634 JToggleButton 655 JToolBar 644 Label 643 Listenfelder 655 Look and Feel umschalten 627 Menü 645 Panel 643 Popup-Menüs 655 Progressbar 645 Radiobutton 631 Registerblätter 655 Schablone einer eigenständigen Applikation 639 setLookAndFeel() 627 Slider 644 Textfelder 634, 655 Togglebuttons 655 Toolbar 645 Swing-Eventhandling 1014 switch-Anweisung 267 Symboltabellen, Sicherheit 761 Synchronisationsanweisung 260, 276 Synchronisierte Blöcke, Multithreading 414 synchronized 413 System Error during Decompression 115 System.err 713 System.exit() 529 System.in 713 System.loadLibrary() 786, 791
Java 2 Kompendium
System.out 713 Systeme, verteilte 843 T Tags 344 Tastaturereignisse 384 TCP, erstes Auftreten 60 TCP/IP 60 TextArea, Klasse 566 Textausgabe, Zeichen-Modus 445 Textbereiche, AWT 566 TextComponent, Klasse 566 Texte, 2D Java 503 Textfelder, AWT 566 TextField, Klasse 566 TextListener, Schnittstelle 614 TexturePaint 502 textValueChanged(), Methode 614 The Fractal Geometry of Nature 439 this 299 This program cannot be run in DOS mode 115 Thread 393f. Priorität verändern 401 ThreadDeath 987 ThreadGroup 406 Thread-Gruppe 406 Thread-sichere Zugriffe, Multithreading 415 throw 677 Exceptions 687 Throwable, Ausnahmebehandlung 677 throw-Anweisung 275 throws 678 toByteArray() 708 Token 183 Tomcat 859 Toolbar, Swing 645 Toolkit, Drucken 744 Top Level Domain 68 Ländercodes 70 Listen der wichtigsten 69 Traditionelle Kommentare 222 Transmission Control Protocol Siehe TCP Transparenz, Graphikeffekte 503 Trennzeichen 200 try 276, 681 Typen 223
1123
Stichwortverzeichnis Typenzwang, Casting 254 Typkonvertierungen 250 Typzustand 761 U UDP 879 Überladen von Methoden 170, 311 von Operatoren 170, 311 Vergleich Java zu C/C++ 783 Überlauf 232 Überschatten 172 Überschreiben 164, 171, 313 von Schnittstellenmethoden 322 UIMangager, Swing 627 Umgebungsvariablen 105 Unable to initialize threads 112 Unbekannte Fehler 116 Undefined variable ... 315 Unerreichbare Anweisung 260, 277 Ungültiger Befehl oder Dateiname 104 Unicode, Vergleich Java zu C/C++ 781 Unicode-Zeichensatz 185 Programm zur Ausgabe 186 Uniform Resource Locator Siehe URL Unix-Debugger 915 UnknownError 987 Unmarshalling, ORB 846 unread() 717 Unreliable Datagram Protocol Siehe UDP UnsatisfiedLinkError 988 Unsupported version of Windows Socket API 115 UnsupportedClassVersionError 988 UnsupportedOperationException 986 Unterschied zwischen prozeduraler und objektorientierter Denkweise 156 Update 418 update() 419 URL 71 URL-Codierung, CGI 855 URLconnection 874 UTF-8-Codierung 188 V valid() 722 Variablen 325
1124
in Schnittstellen 320 JavaScript 800 schleifenlokal 329 vars 176 VBScript 796 Zugriff auf Java 825 Vector 244, 716 Vektoren 716 Verbindung Java/C, konventionelle Technik 785 Vererbung 161 Vergleich Java zu C/C++ 779 Vergleichsoperatoren 201, 213 Verifier 761 VerifyError 988 Verschachtelte Arrays 241 Verschlüsselung 41 in Java 41 Verteilte Systeme 842 Verwendung von Paketen 331 Verzeichnis erstellen 720 Inhalt auslesen 720 Vigenere-Chiffre 1088 Viren, Java-Sicherheit 760 Virtual Reality Modeling Language Siehe VRML VirtualMachineError 988 Virtuellen Maschine Siehe JVM Virtueller Computer Siehe JVM Virtueller Speicher 177 Vordergrundfarben 438 VRML 826 W W3C 65, 343 waitForAll(), MediaTracker 456 waitForID(int id), MediaTracker 456 WAP 859 while-Anweisung 269 Wiederholungsanweisungen 269 winding rule 485 Window, Klasse 527 window, JavaScript-Objekt 809 WINDOW_DEICONIFY 538 WINDOW_DESTROY 537 WINDOW_EXPOSE 537 WINDOW_ICONIFY 538
Java 2 Kompendium
Stichwortverzeichnis WINDOW_MOVED 538 WindowListener, Eventhandling 1.1 666 Wireless Application Protocol 859 Wireless Markup Language 859 WML 859 World Wide Web-Consortium Siehe W3C Wrapper-Klassen 256 Wrapper-Objekte 169 write() Daten schreiben 705 PrintStream 713 writeBoolean() 712 writeByte() 712 Beispiel 724 writeBytes() 712 writeChar() 712 Beispiel 706 writeChars() 712 writeDouble() 712 writeFloat() 712 writeInt() 712 writeLong() 712 writeObject() 715 writeShort() 712 writeTo(), Daten schreiben 708 writeUTF() 712 WWW, Ursprung 60 WWW_HOME 116 X X.509 v3-Zertifikat 40 X.509-Zertifikate 932
Java 2 Kompendium
X/Open SQL CLI 883 Xerox 85 XHTML 859 XML 859 XOR-Modus 450 Z Zeichenbereiche, AWT 578 Zeichenkettenliterale 198 Zeichenliterale 196 Zeichnen 418 von Bildern 451 von Bögen 433 von gefüllten Bögen 434 von gefüllten Kreisen und Ellipsen 432 von gefüllten Polygonen 430 von Kreisen und Ellipsen 431 von Polygonen 427 Zeichnenoperationen 419 Zertifikate 932 exportieren javakey 933 importieren javakey 933 Zugreifen auf Elemente von Datenfeldern 239 Zuordnung 259 Zuweisungsausdruck 259 Zuweisungsoperatoren 201 Zweierkomplement 1095 Zweierkomplement-Repräsentation 230
1125
Sun Microsystems, Inc. Binary Code License Agreement READ THE TERMS OF THIS AGREEMENT AND ANY PROVIDED SUPPLEMENTAL LICENSE TERMS (COLLECTIVELY "AGREEMENT") CAREFULLY BEFORE OPENING THE SOFTWARE MEDIA PACKAGE. BY OPENING THE SOFTWARE MEDIA PACKAGE, YOU AGREE TO THE TERMS OF THIS AGREEMENT. IF YOU ARE ACCESSING THE SOFTWARE ELECTRONICALLY, INDICATE YOUR ACCEPTANCE OF THESE TERMS BY SELECTING THE "ACCEPT" BUTTON AT THE END OF THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL THESE TERMS, PROMPTLY RETURN THE UNUSED SOFTWARE TO YOUR PLACE OF PURCHASE OR, IF THE SOFTWARE IS ACCESSED ELECTRONICALLY, SELECT THE "DECLINE" BUTTON AT THE END OF THIS AGREEMENT. 1. LICENSE TO USE. Sun grants you a non-exclusive and non-transferable license for the internal use only of the accompanying software and documentation and any error corrections provided by Sun (collectively "Software"), by the number of users and the class of computer hardware for which the corresponding fee has been paid. 2. RESTRICTIONS Software is confidential and copyrighted. Title to Software and all associated intellectual property rights is retained by Sun and/or its licensors. Except as specifically authorized in any Supplemental License Terms, you may not make copies of Software, other than a single copy of Software for archival purposes. Unless enforcement is prohibited by applicable law, you may not modify, decompile, or reverse engineer Software. You acknowledge that Software is not designed, licensed or intended for use in the design, construction, operation or maintenance of any nuclear facility. Sun disclaims any express or implied warranty of fitness for such uses. No right, title or interest in or to any trademark, service mark, logo or trade name of Sun or its licensors is granted under this Agreement. 3. LIMITED WARRANTY. Sun warrants to you that for a period of ninety (90) days from the date of purchase, as evidenced by a copy of the receipt, the media on which Software is furnished (if any) will be free of defects in materials and workmanship under normal use. Except for the foregoing, Software is provided "AS IS". Your exclusive remedy and Sun's entire liability under this limited warranty will be at Sun's option to replace Software media or refund the fee paid for Software.
4. DISCLAIMER OF WARRANTY. UNLESS SPECIFIED IN THIS AGREEMENT, ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 5. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In no event will Sun's liability to you, whether in contract, tort (including negligence), or otherwise, exceed the amount paid by you for Software under this Agreement. The foregoing limitations will apply even if the above stated warranty fails of its essential purpose. 6. Termination. This Agreement is effective until terminated. You may terminate this Agreement at any time by destroying all copies of Software. This Agreement will terminate immediately without notice from Sun if you fail to comply with any provision of this Agreement. Upon Termination, you must destroy all copies of Software. 7. Export Regulations. All Software and technical data delivered under this Agreement are subject to US export control laws and may be subject to export or import regulations in other countries. You agree to comply strictly with all such laws and regulations and acknowledge that you have the responsibility to obtain such licenses to export, re-export, or import as may be required after delivery to you. 8. U.S. Government Restricted Rights. If Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in Software and accompanying documentation will be only as set forth in this Agreement; this is in accordance with 48 CFR 227.7201 through 227.7202-4 (for Department of Defense (DOD) acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD acquisitions). 9. Governing Law. Any action related to this Agreement will be governed by California law and controlling U.S. federal law. No choice of law rules of any jurisdiction will apply.
10. Severability. If any provision of this Agreement is held to be unenforceable, this Agreement will remain in effect with the provision omitted, unless omission would frustrate the intent of the parties, in which case this Agreement will immediately terminate. 11. Integration. This Agreement is the entire agreement between you and Sun relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification of this Agreement will be binding, unless in writing and signed by an authorized representative of each party. For inquiries please contact: Sun Microsystems, Inc. 901 San Antonio Road Palo Alto, California 94303 U.S.A. JAVA 2 SOFTWARE DEVELOPMENT KIT STANDARD EDITION VERSION 1.3 SUPPLEMENTAL LICENSE TERMS These supplemental license terms ("Supplemental Terms") add to or modify the terms of the Binary Code License Agreement (collectively, the "Agreement"). Capitalized terms not defined in these Supplemental Terms shall have the same meanings ascribed to them in the Agreement. These Supplemental Terms shall supersede any inconsistent or conflicting terms in the Agreement, or in any license contained within the Software. 1. Internal Use and Development License Grant. Subject to the terms and conditions of this Agreement, including, but not limited to, Section 2 (Redistributables) and Section 4 (Java Technology Restrictions) of these Supplemental Terms, Sun grants you a non-exclusive, non-transferable, limited license to reproduce the Software for internal use only for the sole purpose of development of your JavaTM applet and application ("Program"), provided that you do not redistribute the Software in whole or in part, either separately or included with any Program. 2. Redistributables. In addition to the license granted in Paragraph 1 above, Sun grants you a non-exclusive, non-transferable, limited license to reproduce and distribute, only as part of your separate copy of JAVA(TM) 2 RUNTIME ENVIRONMENT STANDARD EDITION VERSION 1.3 software, those files specifically identified as redistributable in the JAVA(TM) 2 RUNTIME ENVIRONMENT STANDARD EDITION VERSION 1.3
"README" file (the "Redistributables") provided that: (a) you distribute the Redistributables complete and unmodified (unless otherwise specified in the applicable README file), and only bundled as part of the JavaTM applets and applications that you develop (the "Programs:); (b) you do not distribute additional software intended to supersede any component(s) of the Redistributables; (c) you do not remove or alter any proprietary legends or notices contained in or on the Redistributables; (d) you only distribute the Redistributables pursuant to a license agreement that protects ! Sun's interests consistent with the terms contained in the Agreement, and (e) you agree to defend and indemnify Sun and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Programs and/or Software. 3. Separate Distribution License Required. You understand and agree that you must first obtain a separate license from Sun prior to reproducing or modifying any portion of the Software other than as provided with respect to Redistributables in Paragraph 2 above. 4. Java Technology Restrictions. You may not modify the Java Platform Interface ("JPI", identified as classes contained within the "java" package or any subpackages of the "java" package), by creating additional classes within the JPI or otherwise causing the addition to or modification of the classes in the JPI. In the event that you create an additional class and associated API(s) which (i) extends the functionality of a Java environment, and (ii) is exposed to third party software developers for the purpose of developing additional software which invokes such additional API, you must promptly publish broadly an accurate specification for such API for free use by all developers. You may not create, or authorize your licensees to create additional classes, interfaces, or subpackages that are in any way identified as "java", "javax", "sun" or similar convention as specified by Sun in any class file naming convention. Refer to the appropriate version of the Java Runtime Environment binary code license (currently located at http:// www.java.sun.com/jdk/index.html) for the availability of runtime code which may be distributed with Java applets and applications. 5. Trademarks and Logos. You acknowledge and agree as between you and Sun that Sun owns the Java trademark and all Java-related trademarks, service marks, logos and other brand designations including the Coffee Cup logo and Duke logo ("Java Marks"), and you agree to comply with the Sun Trademark and Logo Usage Requirements currently located at http:// www.sun.com/policies/trademarks. Any use you make of the Java Marks inures to Sun's benefit.
6. Source Code. Software may contain source code that is provided solely for reference purposes pursuant to the terms of this Agreement. 7. Termination. Sun may terminate this Agreement immediately should any Software become, or in Sun's opinion be likely to become, the subject of a claim of infringement of a patent, trade secret, copyright or other intellectual property right.