Programmieren in Java - LSW
Programmieren in Java - LSW
Programmieren in Java - LSW
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK I – JV – 000 – 00 – TH – 08<br />
------------------------------------------------------------------------------------<br />
<strong>Programmieren</strong><br />
<strong>in</strong> <strong>Java</strong><br />
Unterlagen zur Lehrveranstaltung "<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong>"<br />
R. Thomas<br />
(Stand : WS 2010/11)
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK I – JV – 001 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel-Überblick<br />
0. Grundkonzepte der Objektorientierten Programmierung V-JV-000<br />
1. E<strong>in</strong>führung V-JV-100<br />
2. Grundlegende Eigenschaften von <strong>Java</strong> V-JV-200<br />
3. Elementare Programmfunktionalitäten V-JV-300<br />
4. Nähere Betrachtung von Klassen und Interfaces V-JV-400<br />
5. Graphische Benutzeroberflächen V-JV-500<br />
6. Applets V-JV-600<br />
7. Multithread<strong>in</strong>g V-JV-700<br />
8. <strong>Java</strong> <strong>in</strong> verteilten Systemen V-JV-800<br />
A. Anhang : Modellierung von OOP-Programmen V-JV-A00
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK I - JV - 002 - 00 - TH – 06<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Überblick<br />
0. Grundkonzepte der Objektorientierten Programmierung<br />
1. E<strong>in</strong>führung<br />
1.1. Entwicklung von <strong>Java</strong><br />
1.2. Nichtimplementierte C++-Eigenschaften<br />
1.3. Schlüsselworte und Identifier<br />
1.4. Operatoren<br />
1.5. Wesentliche neue mit dem JDK 5.0 e<strong>in</strong>geführte Eigenschaften (Überblick)<br />
2. Grundlegende Eigenschaften von <strong>Java</strong><br />
2.1. Programmiersprache und Ausführungsplattform<br />
2.2. Klassen und Programmstruktur<br />
2.3. Programm-Erzeugung und -Start<br />
2.4. Packages<br />
2.5. Standard-Bibliothek<br />
2.6. Datentypen<br />
2.7. Str<strong>in</strong>gs<br />
2.8. Arrays<br />
2.9. Die Klasse Object<br />
2.10. Aufzählungstypen<br />
2.11. Generische Programmierung<br />
3. Elementare Programmfunktionalitäten<br />
3.1. Zugriff zu Programmparametern<br />
3.2. Standard-E<strong>in</strong>- und Ausgabe<br />
3.3. Interaktion mit dem Laufzeitsystem<br />
3.4. Exceptions<br />
3.5. Dateizugriff<br />
4. Klassen und Interfaces<br />
4.1. Def<strong>in</strong>ition von Klassen<br />
4.2. Datenkomponenten<br />
4.3. Memberfunktionen<br />
4.4. Objekterzeugung<br />
4.5. Konstruktoren und Initialisierungsblöcke<br />
4.6. Vererbung<br />
4.7. Interfaces<br />
4.8. E<strong>in</strong>gebettete Klassen und Interfaces<br />
4.9. Generische Klassen, Interfaces und Funktionen<br />
5. Graphische Benutzeroberflächen<br />
5.1. Grundpr<strong>in</strong>zip<br />
5.2. <strong>Java</strong> Foundation Classes - Überblick<br />
5.3. Basisklassen der JFC-Hierarchie<br />
5.4. Erstellung e<strong>in</strong>er GUI-Anwendung<br />
5.5. Bee<strong>in</strong>flussung des Ersche<strong>in</strong>ungsbildes<br />
5.6. Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen<br />
5.7. Ereignisverarbeitung<br />
6. Applets<br />
6.1. Aufbau und Funktionsweise<br />
6.2 Applet-Tag im HTML-Code<br />
6.3. <strong>Java</strong>-Applet-API<br />
6.4. Sicherheitsbeschränkungen<br />
7. Multithread<strong>in</strong>g<br />
7.1. Erzeugung von Threads<br />
7.2. Beenden von Threads<br />
7.3. Synchronisation von Threads<br />
7.4. Thread-Kommunikation über Pipes<br />
8. <strong>Java</strong> <strong>in</strong> verteilten Systemen<br />
8.1. Socket-basierte Kommunikation<br />
8.2. Remote Method Invocation (RMI)<br />
A. Anhang : Modellierung von OOP-Programmen
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK I - JV - 003 - 00 - TH – 07<br />
------------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Literaturh<strong>in</strong>weise<br />
( 1) Ken Arnold, James Gosl<strong>in</strong>g, David Holmes<br />
The <strong>Java</strong> Programm<strong>in</strong>g Language (<strong>Java</strong> 5.0)<br />
Addison Wesley Publish<strong>in</strong>g Company<br />
( 2) James Gosl<strong>in</strong>g u.a.<br />
The <strong>Java</strong> Language specification (<strong>Java</strong> 5.0)<br />
Addison Wesley<br />
( 3) Re<strong>in</strong>hard Schiedermeier<br />
<strong>Programmieren</strong> mit <strong>Java</strong> (<strong>Java</strong> 5.0)<br />
Pearson Studium<br />
( 4) Y. Daniel Liang<br />
Introduction to <strong>Java</strong> Programm<strong>in</strong>g (<strong>Java</strong> 5.0)<br />
Pearson Prentice Hall<br />
( 5) J. Lewis / W. Loftus<br />
<strong>Java</strong> Software Solutions (<strong>Java</strong> 5.0)<br />
Pearson Addison Wesley<br />
( 6) Dietmar Ratz u.a.<br />
Grundkurs <strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong> (<strong>Java</strong> 5.0)<br />
Band 1 und 2<br />
Hanser-Verlag<br />
( 7) Fritz Jobst<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong> (<strong>Java</strong> 5.0)<br />
Hanser-verlag<br />
( 8) D.S. Malik<br />
<strong>Java</strong> Programm<strong>in</strong>g (<strong>Java</strong> 5.0)<br />
Course Technology, Cengage Learn<strong>in</strong>g<br />
( 9) K.A. Mugal, T. Hamre, R.W. Rasmussen<br />
<strong>Java</strong> actually – A comprehensive Primer <strong>in</strong> Programm<strong>in</strong>g (<strong>Java</strong> 5.0)<br />
Course Technology, Cengage Learn<strong>in</strong>g<br />
( 10) H.M. Deitel / P.J. Deitel<br />
<strong>Java</strong> How to Program<br />
Prentice Hall<br />
(11) H.M. Deitel / P.J. Deitel<br />
Advanced <strong>Java</strong> 2 Platform How to Program<br />
Prentice Hall<br />
(12) Guido Krüger<br />
Handbuch der <strong>Java</strong>-Programmierung<br />
Addison Wesley<br />
(13) Ian F. Darw<strong>in</strong><br />
<strong>Java</strong> Cookbook<br />
deutsch : <strong>Java</strong> Kochbuch<br />
O'Reilly<br />
(14) Albrecht We<strong>in</strong>ert<br />
<strong>Java</strong> für Ingenieure<br />
Fachbuchverlag Leipzig<br />
(15) Stefan Middendorf u.a.<br />
<strong>Java</strong> Programmierhandbuch und Referenz<br />
dpunkt Verlag
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 000 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> JAVA<br />
Kapitel 0<br />
0. Grundkonzepte der Objektorientierten Programmierung<br />
0.1. Objekte und Klassen<br />
0.2. Kapselung<br />
0.3. Vererbung<br />
0.4. Polymorphie
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 001 – 00 – TH – 07<br />
-----------------------------------------------------------------------------------<br />
Grundkonzepte der Objektorientierten Programmierung (OOP) : Grundgedanke<br />
• Grundgedanke :<br />
OOP ist e<strong>in</strong>e Softwareentwicklungsmethodik, deren Grundidee aus der Simulationstechnik stammt :<br />
In dieser werden die Objekte der realen Welt sowie deren Beziehungen durch entsprechende Strukturen im Rechner<br />
abgebildet.<br />
In der OOP wird dieses Pr<strong>in</strong>zip auf alle Arten von Informationen und Abläufen – auch auf solche abstrakter Natur –<br />
angewendet.<br />
Der Aufgabenbereich e<strong>in</strong>es zu lösenden Problems wird <strong>in</strong> Objekte und die zwischen ihnen bestehenden Beziehungen<br />
zerlegt. Diese werden <strong>in</strong> e<strong>in</strong>em das entsprechende Problem lösenden Programm nachgebildet.<br />
E<strong>in</strong> OOP-Programm besteht somit im wesentlichen aus e<strong>in</strong>er Anzahl mite<strong>in</strong>ander <strong>in</strong> Beziehung stehender Objekte.<br />
Diese Denk- und Vorgehensweise ermöglicht es, auch sehr umfangreiche und komplexe Aufgaben auf e<strong>in</strong>em relativ<br />
hohem Abstraktionsniveau erfolgreich zu bearbeiten.<br />
Sie nutzt die <strong>in</strong>tellektuellen Fähigkeiten, die der Mensch zur Bewältigung der ihn umgebenden Komplexität entwickelt<br />
hat, aus.<br />
Dies s<strong>in</strong>d im wesentlichen die Fähigkeiten des Abstrahierens, des Klassifizierens und des Generalisierens<br />
Auf ihnen beruhen die Grundkonzepte der OOP :<br />
◈ Bildung von Objekten<br />
◈ Abstraktion der Objekte durch Klassen<br />
◈ Kapselung<br />
◈ Vererbung<br />
◈ Polymorphie
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 011 – 01 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
Grundkonzepte der Objektorientierten Programmierung (OOP) : Objekte und Klassen (1)<br />
• Konkrete Objekte:<br />
◇ Objekte s<strong>in</strong>d <strong>in</strong> e<strong>in</strong>em bestimmten S<strong>in</strong>n abgeschlossene E<strong>in</strong>heiten, die durch zwei Aspekte gekennzeichnet s<strong>in</strong>d :<br />
▻ Sie besitzen e<strong>in</strong>en (<strong>in</strong>neren) Zustand<br />
▻ und sie verfügen über Fähigkeiten, d.h. sie können bestimmte Operationen – aktiv oder passiv – ausführen<br />
Diese Fähigkeiten und damit das dadurch bestimmte Verhalten können von außen angefordert, aktiviert werden.<br />
Die Aktivierung der Fähigkeiten kann e<strong>in</strong>e Zustandsänderung bewirken.<br />
◇ Beispiel :<br />
• Objekte <strong>in</strong> der OOP<br />
Willies Uhr<br />
Zustand : aktuelle Zeit<br />
Fähigkeiten : Uhr stellen<br />
Zeit fortschalten (ticken)<br />
Zeit darstellen<br />
◇ In der OOP stehen Objekte im Vordergrund.<br />
Sie bilden die grundlegenden Strukturierungse<strong>in</strong>heiten e<strong>in</strong>es OOP-Programmms<br />
Dabei kann e<strong>in</strong> Objekt sehr konkret aber auch beliebig abstrakt se<strong>in</strong>, es kann e<strong>in</strong> statisches Gebilde (z.B. e<strong>in</strong> Auto),<br />
oder e<strong>in</strong>en dynamischen Ablauf (Vorgang) beschreiben (z.B. e<strong>in</strong> Tennisspiel).<br />
Der (<strong>in</strong>nere) Zustand des Objekts wird durch Datenstrukturen (Datenkomponenten), se<strong>in</strong>e Fähigkeiten – die von<br />
ihm ausführbaren Operationen – werden durch Funktionen (Prozeduren) beschrieben.<br />
Die Datenkomponenten werden auch als Attribute, die Funktionen (Memberfunktionen) als Methoden bezeichnet.<br />
◇ E<strong>in</strong> Objekt verb<strong>in</strong>det also Daten und die zu ihrer Bearbeitung dienenden Funktionen (Code !) zu e<strong>in</strong>er E<strong>in</strong>heit.<br />
Die von e<strong>in</strong>em Objekt ausführbaren Methoden (= Funktionen) s<strong>in</strong>d Bestandteil des Objekts und nur als solche<br />
relevant.<br />
Dies steht im Gegensatz zur konventionellen (prozeduralen, imperativen) Programmierung, bei der Daten und Code<br />
getrennt s<strong>in</strong>d, wobei der Code (Prozeduren, Funktionen) eigenständig ist und im Vordergrund steht :<br />
Code wird auf Daten angewendet.<br />
◇ In der OOP wird e<strong>in</strong>e Methode für e<strong>in</strong> Objekt aufgerufen, <strong>in</strong> dem an das Objekt – i.a. durch e<strong>in</strong> anderes Objekt –<br />
e<strong>in</strong>e entsprechende Nachricht (Botschaft) geschickt wird : Das Objekt <strong>in</strong>terpretiert die Nachricht und reagiert mit<br />
der Ausführung e<strong>in</strong>er zugeordneten Operation (Methode).<br />
Zwischen den Objekten bestehen also Kommunikationsbeziehungen.<br />
E<strong>in</strong> OOP-Programm besteht im wesentlichen aus e<strong>in</strong>er Ansammlung mite<strong>in</strong>ander kommunizierender und<br />
dadurch <strong>in</strong>teragierender Objekte.<br />
◇ Der OOP-Ansatz erfordert e<strong>in</strong>e andere Vorgehensweise bei der Problemlösung :<br />
Statt e<strong>in</strong>er Top-Down-Zerlegung des Problems ( hierarchische Modularisierung) müssen die relevanten Objekte<br />
(Aufbau und Verhalten) des Problems und die zwischen ihnen bestehenden Beziehungen ermittelt werden ( auf-<br />
gaben- und kommunikationsorientierte Zerlegung)
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 011 – 02 – TH – 06<br />
-----------------------------------------------------------------------------------<br />
Grundkonzepte der Objektorientierten Programmierung (OOP) : Objekte und Klassen (2)<br />
• Klassen<br />
◇ Der Aufbau, die Eigenschaften und Fähigkeiten von Objekten werden durch Klassen beschrieben.<br />
◇ E<strong>in</strong>e Klasse legt die Datenkomponenten (Datenstruktur) und die Methoden zur Bearbeitung der Daten (Memberfunk-<br />
tionen) für e<strong>in</strong>e Menge von gleichartigen Objekten – d.h. Objekten mit geme<strong>in</strong>samen Merkmalen und gleichen<br />
Fähigkeiten, die diese von anderen Objekten unterscheiden – fest.<br />
◇ E<strong>in</strong> spezielles Objekt der durch e<strong>in</strong>e Klasse def<strong>in</strong>ierten Objektmenge wird auch Instanz genannt.<br />
Es unterscheidet sich von e<strong>in</strong>em anderen Objekt (e<strong>in</strong>er anderen Instanz) der gleichen Klasse nur durch se<strong>in</strong>en jewei-<br />
ligen Zustand, d.h. den Werten se<strong>in</strong>er Datenkomponenten.<br />
⇒ Die Klasse entspricht dem Datentyp prozeduraler Programmiersprachen,<br />
während e<strong>in</strong>e Instanz (e<strong>in</strong> spezielles Objekt dieser Klasse) e<strong>in</strong>er Variablen entspricht.<br />
◇ E<strong>in</strong>e Klasse ist mit e<strong>in</strong>em Verbund-Datentyp (Structure <strong>in</strong> C, Record <strong>in</strong> Pascal) vergleichbar.<br />
Gegenüber e<strong>in</strong>em nur aus Datenkomponenten bestehenden Verbund ist e<strong>in</strong>e Klasse um Funktionskomponenten er-<br />
weitert.<br />
◇ Beispiel : Klasse Uhr<br />
◇ Jedes Objekt (Instanz) e<strong>in</strong>er Klasse hat e<strong>in</strong>en eigenen (<strong>in</strong>neren) Zustand<br />
Die Datenkomponenten existieren für jedes Objekt (Unterschied zu Modulen der prozeduralen Programmierung).<br />
Sie werden erst geschaffen, wenn das Objekt generiert wird ( "Variablendef<strong>in</strong>ition").<br />
◇ Die Methoden (Funktionen) existieren dagegen nur e<strong>in</strong>mal pro Klasse. Sie s<strong>in</strong>d an die Klasse gebunden.<br />
Sie werden durch die Def<strong>in</strong>ition der Klasse ( "Typdef<strong>in</strong>ition") geschaffen.<br />
Auch wenn es gar ke<strong>in</strong>e Objekte dieser Klasse gibt, existieren die Methoden.<br />
Jedes Objekt e<strong>in</strong>er Klasse arbeitet mit demselben Code ( Code Shar<strong>in</strong>g)<br />
Uhr<br />
Datenkomp : actTime<br />
Funktionskomp : setTime(...)<br />
tick()<br />
displayClock()
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 021 – 00 – TH – 08<br />
-----------------------------------------------------------------------------------<br />
Grundkonzepte der Objektorientierten Programmierung (OOP) : Kapselung<br />
• Kapselung (Encapsulation):<br />
◇ Der Benutzer e<strong>in</strong>es Objekts (allg. : Anwenderprogramm, speziell : anderes Objekt) braucht se<strong>in</strong>en genauen Aufbau<br />
nicht zu kennen.<br />
Ihm müssen lediglich die Methoden, die er für e<strong>in</strong>e Interaktion mit dem Objekt benötigt, d.h. über die er die Fähig-<br />
keiten des Objekts aktivieren und dessen Zustand verändern kann, bekannt zu se<strong>in</strong>.<br />
Von der <strong>in</strong>ternen Darstellung der den jeweiligen Objektzustand festlegenden Daten braucht er dagegen ke<strong>in</strong>erlei<br />
Kenntnis zu haben.<br />
◇ Nur die Funktionen (= Methoden) e<strong>in</strong>es Objekts, die zu se<strong>in</strong>er Verwendung tatsächlich benötigt werden, werden<br />
allgeme<strong>in</strong> zugänglich, d.h. öffentlich (public), gemacht.<br />
Sie bilden das Interface (Protokoll), über das zu dem Objekt kontrolliert zugegriffen werden kann, d.h. sie bilden<br />
se<strong>in</strong>e Schnittstelle zur "Außenwelt".<br />
Die Daten (u. gegebenenfalls re<strong>in</strong>e Hilfs- und Verwaltungsfunktionen) s<strong>in</strong>d nur Komponenten des Objekts selbst<br />
zugänglich, d.h. privat (private). Der "Außenwelt" gegenüber bleiben sie verborgen Sie s<strong>in</strong>d nach außen gekapselt.<br />
Hierdurch wird sichergestellt, daß zu e<strong>in</strong>em Objekt nur über e<strong>in</strong>e wohldef<strong>in</strong>ierte Schnittstelle zugegriffen werden<br />
kann. Klassen-Schnittstelle<br />
Zugriffe zu Interna, die nur zur <strong>in</strong>ternen Realisierung und Verwaltung des Objekts dienen, s<strong>in</strong>d nicht möglich<br />
Vermeidung von Fehlern durch Verh<strong>in</strong>derung e<strong>in</strong>es direkten und unkontrollierten Zugriffs<br />
⇒ Trennung von Interface (Schnittstelle) und Implementierung.<br />
Methoden<br />
Daten<br />
Methoden<br />
◇ Die Kapselung bewirkt außerdem e<strong>in</strong>e Datenabstraktion (data abstraction) :<br />
E<strong>in</strong>e Datenstruktur ist - nach außen - nicht mehr an e<strong>in</strong>e bestimmte Implementierung gebunden, sondern wird alle<strong>in</strong><br />
über die auf sie anwendbaren Operationen (Methoden, Funktionen) def<strong>in</strong>iert. ( abstrakter Datentyp, ADT)<br />
E<strong>in</strong>e Änderung der Implementierung - bei gleichbleibendem Interface – hat ke<strong>in</strong>en E<strong>in</strong>fluß auf den<br />
Anwendungscode.<br />
◇ Anmerkung :<br />
Manchmal wird die Kapselung als Verbergen von Informationen (<strong>in</strong>formation hid<strong>in</strong>g) bezeichnet :<br />
Nur die Eigenschaften e<strong>in</strong>es Objekts s<strong>in</strong>d nach außen bekannt, die Realisierung bleibt dagegen verborgen.<br />
Streng genommen ist das für die Programmiersprache C++ nicht ganz zutreffend : Die pr<strong>in</strong>zipielle Realisierung<br />
(Struktur – auch der privaten – Datenkomponenten) ist durchaus bekannt (Klassendef<strong>in</strong>ition <strong>in</strong> Headerdatei), nur der<br />
Zugriff zu den <strong>in</strong>ternen (privaten) Daten und Funktionen ist gesperrt.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 031 – 00 – TH – 06<br />
-----------------------------------------------------------------------------------<br />
Grundkonzepte der Objektorientierten Programmierung (OOP) : Vererbung<br />
• Vererbung (Inheritance) :<br />
◇ Weitergabe von Eigenschaften (Daten und Funktionen) e<strong>in</strong>es Objekts an e<strong>in</strong> anderes Objekt.<br />
Zusätzlich zu den ererbten Eigenschaften kann e<strong>in</strong> Objekt neue spezifische Eigenschaften (Daten und Funktionen)<br />
besitzen bzw. bestimmte Eigenschaften modifizieren.<br />
Schaffung e<strong>in</strong>er neuen Art von Objekten durch Erweiterung e<strong>in</strong>er bestehenden Art von Objekten.<br />
◇ Die Vererbung führt zum Aufbau von Klassenhierarchien :<br />
E<strong>in</strong>e neue Klasse wird aus e<strong>in</strong>er - oder mehreren - bereits def<strong>in</strong>ierten Klasse(n) abgeleitet.<br />
vorhandenene Klasse : Basisklasse, Elternklasse, Oberklasse<br />
neue Klasse : abgeleitete Klasse, K<strong>in</strong>dklasse, Unterklasse<br />
Die abgeleitete Klasse erbt die Daten und Methoden der Basisklasse(n).<br />
Dabei können geerbete Methoden abgeändert ("überschrieben") werden.<br />
Zusätzlich kann sie neue Daten und Methoden besitzen.<br />
Abänderung und Ergänzung im S<strong>in</strong>ne e<strong>in</strong>er weiteren Spezialisierung<br />
◇ Beispiel : Ableitung der Klasse UhrMitDatum von der Klasse Uhr<br />
neue Datenkomponenten : actDate<br />
neue Funktionskomponenten : setDate(), setClock()<br />
geänderte Funktionskomponenten : tick(), displayClock()<br />
◇ E<strong>in</strong> Objekt e<strong>in</strong>er abgeleiteteten Klasse kann immer auch als – spezielles - Objekt der Basisklasse(n) betrachtet<br />
werden : z.B. ist jede UhrMitDatum auch e<strong>in</strong>e Uhr.<br />
◇ E<strong>in</strong>fache Vererbung : Ableitung e<strong>in</strong>er Klasse von nur e<strong>in</strong>er Basisklasse.<br />
Mehrfachvererbung : Ableitung e<strong>in</strong>er Klasse von mehreren Basisklassen<br />
(nicht von allen OOP-Sprachen unterstützt)<br />
◇ Durch Vererbung übertragene Methoden (Funktionen) existieren nur e<strong>in</strong>mal ( Code Shar<strong>in</strong>g).<br />
Dies erleichtert Änderungen und Erweiterungen an bestehenden Klassenhierarchien.<br />
Uhr<br />
Datenkomp : actTime<br />
Funktionskomp : setTime(...)<br />
tick()<br />
displayClock()<br />
UhrMitDatum<br />
neue Datenkomp : actDate<br />
neue Funkt.komp : setDate(...)<br />
setClock(...)<br />
modifiz. Funkt.komp : tick()<br />
displayClock()
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 041 – 00 – TH – 07<br />
-----------------------------------------------------------------------------------<br />
Grundkonzepte der Objektorientierten Programmierung (OOP) : Polymorphie<br />
• Polymorphie (Polymorphism) :<br />
◇ Verwendung des gleichen Namens für unterschiedliche - aber mite<strong>in</strong>ander verwandte - D<strong>in</strong>ge.<br />
(griech. : Vielgestaltigkeit)<br />
◇ Polymorphie <strong>in</strong> der OOP ermöglicht, daß verschiedenartige Objekte (unterschiedlicher aber von e<strong>in</strong>er geme<strong>in</strong>samen<br />
Basisklasse abgeleiteter Klassen) unter e<strong>in</strong>em geme<strong>in</strong>samen Oberbegriff (Basisklasse) betrachtet und bearbeitet<br />
werden können.( Generalisierung)<br />
Beispiel : Sowohl Objekte der Klasse Uhr als auch Objekte der Klasse UhrMitDatum lassen sich als Uhr-Objekte<br />
behandeln.<br />
◇ Für verschiedenartige Objekte werden unterschiedliche - aber meist ähnliche - Methoden mit dem gleichen Namen<br />
und gleichem Interface (gleicher Signatur) def<strong>in</strong>iert ( Überschreiben von Funktionen, virtuelle Funktionen).<br />
Der gleiche Name kann damit zur Spezifizierung e<strong>in</strong>er Gruppe ähnlicher - aber doch unterschiedlicher - Operationen<br />
(Methoden) verwendet werden.<br />
. Die gleiche durch den Namen ausgedrückte Botschaft wird - an unterschiedliche Objekte gerichtet - zum Aufruf<br />
unterschiedlicher Methoden führen.<br />
Die <strong>in</strong> e<strong>in</strong>em konkreten Fall ausgeführte Operation (Methode) hängt von der tatsächlichen Klasse des Objekts ab, an<br />
das die Botschaft gerichtet ist ( "E<strong>in</strong> Interface - mehrere Methoden").<br />
Also nicht die Botschaft, d.h. der Aufruf, bestimmt, welche Methode (Funktion) ausgeführt wird, sondern der Empfän-<br />
ger der Botschaft.<br />
Beispiel : Die Botschaft "displayClock()" an e<strong>in</strong> UhrMitDatum-Objekt gerichtet bewirkt die Ausgabe der<br />
Uhrzeit und des Datums, während sie bei e<strong>in</strong>em Uhr-Objekt nur zur Ausgabe der Uhrzeit führt.<br />
◇ Wenn die Zuordnung e<strong>in</strong>er Methode zu e<strong>in</strong>er Botschaft erst zur Laufzeit vorgenommen wird, spricht man von<br />
"später B<strong>in</strong>dung" ("late b<strong>in</strong>d<strong>in</strong>g").<br />
Die Zuordnung bereits zur Compilezeit wird mit "früher B<strong>in</strong>dung" ("early b<strong>in</strong>d<strong>in</strong>g") bezeichnet.<br />
⇒<br />
Polymorphie erlaubt durch die Schaffung e<strong>in</strong>es Standard<strong>in</strong>terfaces die e<strong>in</strong>heitliche<br />
Verarbeitung unterschiedlicher Objekte, die über geme<strong>in</strong>same Grundfähigkeiten verfügen.<br />
Dadurch wird die Beherrschung e<strong>in</strong>er größeren Komplexität ermöglicht.<br />
◇ Polymorphie ermöglicht auch - nicht nur <strong>in</strong> der OOP – das Überladen von Funktionen (Methoden) und Operatoren :<br />
▷ Überladen von Funktionen (Function Overload<strong>in</strong>g) :<br />
Mehrere Funktionen, die mit verschiedenen Datentypen arbeiten, können den gleichen Namen besitzen, sofern<br />
ihre Parameterliste (Signatur) unterschiedlich ist.<br />
Durch den gleichen Namen wird auch hier e<strong>in</strong>e Art Standard-Interface (das sich aber nicht auf die Parameter<br />
erstreckt) bereitgestellt, über das sich mehrere unterschiedliche aber meist mite<strong>in</strong>ander verwandte Methoden<br />
aufrufen lassen.<br />
Die speziell angewandte Methode hängt hier von den beim Aufruf übergebenen Daten (Parametern) ab.<br />
▷ Überladen von Operatoren (Operator Overload<strong>in</strong>g) :<br />
Operatoren können zur Anwendung auf unterschiedliche Datentypen umdef<strong>in</strong>iert werden.<br />
E<strong>in</strong> überladener Operator bewirkt den Aufruf e<strong>in</strong>er speziellen - vom Benutzer erstellten - Funktion.<br />
Rückführung auf Überladen von Funktionen.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 100 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
1. E<strong>in</strong>führung<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
1.1. Entwicklung von <strong>Java</strong><br />
Kapitel 1<br />
1.2. Nichtimplementierte C/C++-Eigenschaften<br />
1.3. Schlüsselworte und Identifier<br />
1.4. Operatoren<br />
1.5. Wesentliche neue mit dem JDK 5.0 e<strong>in</strong>geführte Eigenschaften (Überblick)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 111 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Der Weg zu <strong>Java</strong><br />
Entwicklung von <strong>Java</strong><br />
► 1990 (Dez.)<br />
Patrick Naugthon, Fa SUN Microsystems, kritisiert die von se<strong>in</strong>er Fa e<strong>in</strong>gesetzte und vertriebene Hard- und Software<br />
als nicht mehr zeitgemäss.<br />
Als Folge wird e<strong>in</strong>e Arbeitsgruppe e<strong>in</strong>gesetzt, die zukünftige Entwicklungstrends <strong>in</strong> Hard- und Software erkennen,<br />
untersuchen und realisieren sollte. späterer Name Green Project<br />
Mitglieder waren – neben Patrick Naughton – James Gosl<strong>in</strong>g und Mike Sheridan<br />
Entwicklung e<strong>in</strong>es Prototypen zur Steuerung und Integration von Haushaltgeräten<br />
► 1991 (Juni)<br />
James Gosl<strong>in</strong>g beg<strong>in</strong>nt im Rahmen des Green Projects die Arbeit an der portablen Interpretersprache Oak, die später<br />
<strong>in</strong> <strong>Java</strong> umbenannt wird<br />
► 1992<br />
Vorstellung des entwickelten Geräts (*7, Star Seven), das e<strong>in</strong>em heutigen Palm-Computer glich.<br />
Hauptbestandteile : neben diversen Hardwarekomponenten e<strong>in</strong> Betriebssystem (Green-OS), die Interpretersprache Oak<br />
und e<strong>in</strong> Graphiksubsystem (Aspen).<br />
In der Folgezeit wird versucht, das Gerät zur Serienreife zu entwickeln (Gründung der Fa. First Person Inc)<br />
1994<br />
Der Versuch zur kommerziellen Verwendung von Star Seven scheitert endgültig.<br />
E<strong>in</strong>satz der neuen Programmiersprache Oak (<strong>Java</strong>) zur Entwicklung von Applets und e<strong>in</strong>es WEB-Browsers zum<br />
Herunterladen und Ausführen derselben (WebRunner, später umbenannt <strong>in</strong> Hot<strong>Java</strong>)<br />
Arthur van Hoff (seit Sept. 1993 im Green Project tätig) implementiert e<strong>in</strong>en <strong>Java</strong>-Compiler <strong>in</strong> <strong>Java</strong>.<br />
► 23.5.1995<br />
Vorstellung von <strong>Java</strong> und Hot<strong>Java</strong> auf der SunWorld '95<br />
Offizieller Geburtstag der Sprache <strong>Java</strong>.<br />
Ankündigung von Netscape, <strong>Java</strong> für den E<strong>in</strong>satz <strong>in</strong> se<strong>in</strong>em Browser zu lizenzieren.<br />
• <strong>Java</strong>-Development Kits<br />
Werden von Sun als "offizielle <strong>Java</strong>-Versionen" zum Download bereitgestellt.<br />
Enthalten Compiler, Interpreter (<strong>Java</strong> Virtual Mach<strong>in</strong>e, JVM), weitere Dienstprogramme und Standard-Bibliothek<br />
► 1996 (Jan.) Freigabe des <strong>Java</strong> Development Kits 1.0 (JDK 1.0)<br />
► 1997 JDK 1.1<br />
► 1998 JDK 1.2, kurze Zeit später umbenannt <strong>in</strong> <strong>Java</strong> 2 Platform<br />
► 2000 JDK 1.3 (Offizieller Name : <strong>Java</strong>2 System Development Kit 1.3 ,J2SDK 1.3)<br />
► 2002 JDK 1.4 (J2SDK 1.4)<br />
► 2004 JDK 1.5 (JDK 5.0)<br />
► 2006 JDK 1.6 (JDK 6.0)<br />
• <strong>Java</strong>2-Plattformen<br />
► <strong>Java</strong>2 Standard Edition (J2SE)<br />
► <strong>Java</strong>2 MicroEdition (J2ME), e<strong>in</strong>geschränkter Sprachstandard für den E<strong>in</strong>satz <strong>in</strong> Geräten wie Mobiltelefonen, PDAs usw<br />
► <strong>Java</strong>2 Enterprise Edition (J2EE), zusätzliche Komponenten zur Entwicklung unternehmensweiter verteilter<br />
Anwendungen (u.a. Enterprise <strong>Java</strong> Beans, EJB)<br />
• Wurzeln von <strong>Java</strong><br />
► C/C++<br />
► E<strong>in</strong>flüsse weiterer objektorientierter Programmiersprachen wie Oberon, Ada, Eiffel, Objective-C
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 121 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
In <strong>Java</strong> nicht implementierte C/C++-Eigenschaften<br />
• Syntax und Semantik von <strong>Java</strong> entsprechen weitgehend der Syntax und Semantik von C/C++.<br />
• Zahlreiche fehleranfällige oder redundante Bestandteile /Eigenschaften von C/C++ wurden jedoch nicht implementiert.<br />
Wo s<strong>in</strong>nvoll und erforderlich s<strong>in</strong>d diese durch "bessere" Konzepte ersetzt.<br />
Im wesentlichen fehlen :<br />
▻ Po<strong>in</strong>ter und Po<strong>in</strong>terarithmetik<br />
▻ Funktionspo<strong>in</strong>ter<br />
▻ Speicherklassen (auto, register, extern)<br />
▻ Globale Variable<br />
▻ freie Funktionen<br />
▻ <strong>in</strong>l<strong>in</strong>e-Funktionen<br />
▻ die strukturierten Typen struct und union<br />
▻ Bitfelder<br />
▻ Datentyp long double<br />
▻ vorzeichenlose Datentypen (ke<strong>in</strong> unsigned und damit auch ke<strong>in</strong> signed)<br />
▻ Äquivalenz zwischen logischen (bool) und ganzzahligen Werten (ke<strong>in</strong>e Konvertierung zwischen bool und <strong>in</strong>t)<br />
▻ E<strong>in</strong>führung neuer Typnamen mittels typedef<br />
▻ Sprunganweisung goto<br />
▻ sizeof-Operator<br />
▻ Komma-Operator<br />
▻ Preprozessoranweisungen (Textersatz (Makros), bed<strong>in</strong>gte Kompilierung)<br />
▻ Header-Dateien<br />
▻ Extern- und Vorwärtsreferenzen<br />
▻ Dynamische Allokation von Variablen e<strong>in</strong>facher Datentypen<br />
▻ Datentypen long long, _Bool, sowie komplexe und imag<strong>in</strong>äre Datentypen re<strong>in</strong>e C- Eigenschaft (C99)<br />
▻ Datentyp wchar_t (<strong>in</strong> C e<strong>in</strong> <strong>in</strong> Headerdateien ,mittels typedef def<strong>in</strong>ierter Typ)<br />
▻ Statische Allokation von Objekten<br />
▻ explizite Freigabe dynamisch allozierten Speichers (ke<strong>in</strong> delete-Operator)<br />
▻ Default-Parameter von Funktionen<br />
▻ Destruktoren<br />
▻ Explizites Überladen von Operatoren (Operatorfunktionen)<br />
▻ Mehrfachvererbung<br />
▻ Templates<br />
(ab JDK 5.0 gibt es zwar generische Datentypen und generische Methoden, die aber nicht<br />
100%ig C++-Klassen-(und Funktions-)Templates entsprechen)<br />
▻ Explizite Referenzen<br />
▻ Befreundete Funktionen und Klassen (ke<strong>in</strong> Schlüsselwort friend)<br />
• Die folgenden Eigenschaften von C/C++ wurden erst mit dem JDK 5.0 e<strong>in</strong>geführt :<br />
▻ Aufzählungstypen (enum),<br />
▻ Variable Parameterliste bei Funktionen<br />
re<strong>in</strong>e<br />
C++-Eigenschaften
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 131 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Schlüselworte (key words)<br />
re<strong>in</strong>e C-Schlüssel-<br />
worte<br />
C- u. C++-<br />
Schlüsselworte,<br />
die nicht <strong>in</strong> <strong>Java</strong><br />
enthalten s<strong>in</strong>d<br />
re<strong>in</strong>e C++-<br />
Schlüsselworte,<br />
die nicht <strong>in</strong> <strong>Java</strong><br />
enthalten s<strong>in</strong>d<br />
Schlüsselworte, die<br />
die <strong>in</strong> C++und<br />
<strong>Java</strong> enthalten<br />
s<strong>in</strong>d<br />
Schlüsselworte, die<br />
<strong>in</strong> C, C++und <strong>Java</strong><br />
enthalten s<strong>in</strong>d<br />
*) <strong>in</strong> <strong>Java</strong> reserviert,<br />
aber nicht<br />
verwendet<br />
neue<br />
Schlüsselworte<br />
von <strong>Java</strong><br />
• Identifier<br />
Vergleich der Schlüsselworte und Identitifier von <strong>Java</strong>, C und C++<br />
restrict _Complex _Imag<strong>in</strong>ary<br />
_Bool<br />
auto signed typedef<br />
extern sizeof union<br />
<strong>in</strong>l<strong>in</strong>e struct unsigned<br />
register<br />
asm friend typeid<br />
bool mutable typename<br />
const_class namespace us<strong>in</strong>g<br />
delete operator virtual<br />
dynamic_cast re<strong>in</strong>terpret_cast wchar_t<br />
explicit static_cast<br />
export template<br />
catch private throw<br />
class protected true **)<br />
false **) public try<br />
new this<br />
break else return<br />
case enum short<br />
char float static<br />
const *) for switch<br />
cont<strong>in</strong>ue goto *) void<br />
default if volatile<br />
do <strong>in</strong>t while<br />
double long<br />
abstract implements null **)<br />
assert import strictfp<br />
boolean <strong>in</strong>stanceof super<br />
byte <strong>in</strong>terface synchronized<br />
extends native throws<br />
f<strong>in</strong>al package transient<br />
f<strong>in</strong>ally<br />
**) genau genommen handelt es sich hierbei <strong>in</strong> <strong>Java</strong> nicht um e<strong>in</strong> Schlüsselwort,<br />
sondern um e<strong>in</strong>e Konstante (literal)<br />
◇ Identifier (Namen) <strong>in</strong> <strong>Java</strong> werden nach den gleichen Regeln wie <strong>in</strong> C gebildet :<br />
▻ Sie bestehen aus Buchstaben, dem Underscore ('_') und Ziffern<br />
▻ Sie müssen mit e<strong>in</strong>em Buchstaben oder dem Underscore ('_') beg<strong>in</strong>nen<br />
▻ Groß- und Kle<strong>in</strong>-Buchstaben s<strong>in</strong>d unterschiedlich<br />
▻ Sie dürfen nicht wie e<strong>in</strong> reserviertes Wort (e<strong>in</strong>schliesslich false, true und null) lauten<br />
◇ Zusätzlich dürfen <strong>Java</strong>-Identifier das Dollarzeichen ('$') enthalten.<br />
Dieses wird wie e<strong>in</strong> Buchstabe behandelt (Beg<strong>in</strong>n mit '$' ist zulässig)<br />
◇ Als Buchstaben s<strong>in</strong>d alle Unicode-Buchstaben (also auch andere als im late<strong>in</strong>ischen Alphabet) zulässig<br />
◇ <strong>Java</strong>-Identifier dürfen aus beliebig vielen Zeichen bestehen.<br />
<strong>Java</strong><br />
C<br />
C++<br />
C
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 141 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Operator-Hierarchie von <strong>Java</strong><br />
Operatoren von <strong>Java</strong><br />
Priorität Operator Operation Assoziativität<br />
1 [] Indizierung l r<br />
() Funktionsaufruf<br />
. Komponentenzugriff<br />
++ (Postfix) Increment<br />
-- (Postfix) Decrement<br />
2 ++ (Prefix) Increment l r<br />
-- (Prefix) Decrement<br />
+ Identität<br />
- Negation (arithmetisch)<br />
! Negation (logisch)<br />
~ bitweises Komplement<br />
3 new Objekterzeugung l r<br />
(type) Typkonvertierung (Cast)<br />
4 * / % Multiplikation / Division / Modulus l r<br />
5 + Addition bzw Konkatenation (Str<strong>in</strong>gs) l r<br />
- Subtraktion<br />
6 > Rechtsschieben, Nachschieben des Vorzeichens<br />
>>> Rechtsschieben, Nachschieben von 0<br />
7 < >= Vergleich (größer / größer gleich)<br />
<strong>in</strong>stanceof Typprüfung<br />
8 == != Vergleich (gleich / ungleich) l r<br />
9 & bitweises UND l r<br />
10 ^ bitweises EXOR l r<br />
11 | bitweises ODER l r<br />
12 && logisches UND l r<br />
13 || logisches ODER l r<br />
14 ?: bed<strong>in</strong>gte Auswertung l r<br />
15 = Zuweisung l r<br />
*= /= %= Zuweisung mit Verknüpfungsoperation<br />
+= -=<br />
= >>>=<br />
&= ^= |=
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 151 – 00 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Wesentliche neue mit dem JDK 5.0 e<strong>in</strong>geführte <strong>Java</strong>-Eigenschaften (Überblick)<br />
• Neue Spracheigenschaften<br />
▻ Generische Datentypen und Methoden (Generics)<br />
Sie erlauben e<strong>in</strong>e von konkreten Datentypen unabhängige Implementierung von Algorithmen (ähnlich den Klassen-<br />
und Funktions-Templates von C++)<br />
Sie werden vor allem im Zusammenhang mit der Conta<strong>in</strong>er-Bibliothek (collection framework) e<strong>in</strong>gesetzt.<br />
▻ Automatische Umwandlung zwischen e<strong>in</strong>fachen Datentypen und ihren Wrapper-Klassen<br />
(Autobox<strong>in</strong>g/-unbox<strong>in</strong>g)<br />
Dies ermöglicht die direkte Verwendung von Werten e<strong>in</strong>facher Datentypen <strong>in</strong> Situationen, <strong>in</strong> denen Objekte benötigt<br />
werden.<br />
▻ Vere<strong>in</strong>fachte for-Anweisung (Enhanced for Loop, For-Each Loop)<br />
Sie ermöglicht e<strong>in</strong>e e<strong>in</strong>fachere Iteration über alle Elemente e<strong>in</strong>es Arrays oder Conta<strong>in</strong>ers ohne den expliziten E<strong>in</strong>satz von<br />
Indexvariablen bzw Iteratoren.<br />
▻ Aufzählungstypen (Typesafe Enums)<br />
Sie dienen zur Def<strong>in</strong>ition von typsicheren Konstanten<br />
Aufzählungstypen s<strong>in</strong>d als besondere Klassen implementiert. Dadurch besitzen sie erweiterte Eigenschaften gegenüber<br />
den C/C++-Aufzählungstypen.<br />
▻ Variable Parameterliste bei Funktionen (Varargs)<br />
Funktionen lassen sich so def<strong>in</strong>ieren, dass sie mit e<strong>in</strong>er unterschiedlichen Anzahl von Parametern unterschiedlicher<br />
Typen aufgerufen werden können<br />
▻ Import aller statischen Komponenten e<strong>in</strong>er Klasse (Static Import)<br />
Hierdurch lassen sich statische Klassenkomponenten wesentlich e<strong>in</strong>facher verwenden (ohne Qualifikation mit dem<br />
Klassennamen)<br />
▻ Metadaten (Metadata, Annotations)<br />
Metadaten s<strong>in</strong>d zusätzliche Informationen, mit denen <strong>Java</strong>-Code versehen werden kann. Diese Informationen bee<strong>in</strong>-<br />
flussen die Semantik e<strong>in</strong>es Programms nicht direkt. Sie können aber von Codegeneratoren, anderen Tools und<br />
Bibliotheken ausge wertet werden und sich dadurch auf deren Arbeitsweise auswirken, was <strong>in</strong>direkt wieder Auswir-<br />
kungen auf die Semantik e<strong>in</strong>es laufenden Programms haben kann.<br />
• Verbesserungen an der Virtuellen Masch<strong>in</strong>e<br />
Die JVM (<strong>Java</strong> Virtual Mach<strong>in</strong>e) wurde mit e<strong>in</strong>e Reihe neuer Fähigkeiten versehen, die im wesentlichen e<strong>in</strong>e Beschleunigung<br />
der Programmabarbeitung bewirken sollen.<br />
• Ergänzungen/Neuerungen <strong>in</strong> der <strong>Java</strong>-Klassen-Bibliothek<br />
E<strong>in</strong>e Reihe von Klassen, die bereits <strong>in</strong> früheren JDK-Versionen vorhanden waren, wurden um zusätzliche Funktionali-<br />
täten erweitert.<br />
Darüberh<strong>in</strong>aus wurde die Bibliothek um zahlreiche neue Klassen und um weitere Teilbibliotheken ergänzt.<br />
E<strong>in</strong>zelheiten müssen der API-Dokumentation entnommen werden.<br />
E<strong>in</strong>ige Beispiele :<br />
▻ Formatierte Ausgabe analog zu C/C++ (Methode pr<strong>in</strong>tf(), Klasse java.util.Formatter)<br />
▻ Klasse zur Erleichterung der formatierten E<strong>in</strong>gabe (java.util.Scanner)<br />
▻ Verbesserungen/Erweiterungen durch E<strong>in</strong>satz der neuen Spracheigenschaften (vor allem Generics, Enhanced for Loop,<br />
Autobox<strong>in</strong>g/-unbox<strong>in</strong>g, Enums), <strong>in</strong>sbesondere <strong>in</strong> der Conta<strong>in</strong>er-Bibliothek (Collection Framework)<br />
▻ Bessere Unterstützung von Mulithread<strong>in</strong>g und Multiprocess<strong>in</strong>g (Teilbibliothek java.util.concurrency,<br />
Änderungen <strong>in</strong> der Klasse java.lang.Thread, neue Klasse java.lang.ProcessBuilder zur e<strong>in</strong>facheren<br />
Erzeugung von K<strong>in</strong>dprozessen)<br />
▻ Überarbeitung der Teilbibliotheken zur Programmierung graphischer Benutzeroberflächen
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 200 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel 2<br />
2. Grundlegende Eigenschaften von <strong>Java</strong><br />
2.1. Programmiersprache und Ausführungsplattform<br />
2.2. Klassen und Programmstruktur<br />
2.3. Programm-Erzeugung und –Start<br />
2.4. Packages<br />
2.5. Standard-Bibliothek<br />
2.6. Datentypen<br />
2.7. Str<strong>in</strong>gs<br />
2.8. Arrays und Array-Listen<br />
2.9. Die Klasse Object<br />
2.10. Aufzählungstypen<br />
2.11. Generische Programmierung
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 211 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong> als Programmiersprache und Ausführungsplattform (1)<br />
• <strong>Java</strong> ist mehr als e<strong>in</strong>e Programmiersprache<br />
◇ In e<strong>in</strong>em ihrer früheren Artikel charakterisiert die Fa. SUN <strong>Java</strong> wie folgt :<br />
<strong>Java</strong> : A simple, object-oriented, distributed, <strong>in</strong>terpreted, robust, secure, architecture neutral, portable,<br />
high-performance, multithreaded, and dynamic language<br />
◇ E<strong>in</strong>ige dieser Eigenschaften werden dadurch realisiert, dass <strong>Java</strong> auch e<strong>in</strong>e Plattform zur Ausführung von <strong>Java</strong>-Pro-<br />
grammen zur Verfügung stellt.<br />
<strong>Java</strong> ist sowohl e<strong>in</strong>e Programmiersprache als auch e<strong>in</strong>e Ausführungsplattform.<br />
◇ Mit <strong>Java</strong> untrennbar verbunden ist auch e<strong>in</strong>e Standardbibliothek, die <strong>in</strong> ihrem Kernbereich (<strong>Java</strong> Core API) wichtige<br />
Sprachkonzepte implementiert und damit verwendbar macht. Zum<strong>in</strong>dest dieser Kernbereich wird de facto als<br />
Bestandteil der Sprache betrachtet.<br />
• Elementare Charakteristika der Programmiersprache <strong>Java</strong><br />
◇ E<strong>in</strong>fachheit (simple)<br />
<strong>Java</strong> ist unter Berücksichtigung des KISS (Keep it Small and Simple) -Pr<strong>in</strong>zips <strong>in</strong> massgebenden Umfang aus der<br />
Sprache C++ entwickelt worden. Syntax und Semantik von <strong>Java</strong> weisen e<strong>in</strong>e große Ähnlichkeit mit C++ auf.<br />
Wesentliche Bestandteile von <strong>Java</strong> s<strong>in</strong>d damit C++-Programmierern vertraut, so dass <strong>Java</strong> für sie leicht erlernbar ist.<br />
Durch das Weglassen zahlreicher redundanter und fehleranfälliger Sprachelemente/-eigenschaften ist <strong>Java</strong> zudem<br />
schlanker, überschaubarer und leichter anwendbarer als C++. Gleichzeitig wird dadurch die Zuverlässigkeit der<br />
Sprache und der <strong>in</strong> ihr formulierten Programme erhöht.<br />
Zusätzlich s<strong>in</strong>d s<strong>in</strong>nvolle Konzepte anderer objektorientierter Sprachen, die der Klarheit und Effizienz dienen, <strong>in</strong> <strong>Java</strong><br />
<strong>in</strong>tegriert worden.<br />
◇ Objektorientiertheit (object-oriented)<br />
<strong>Java</strong> ist e<strong>in</strong>e re<strong>in</strong> objekttorientierte Sprache. Alle Funktionalität ist an Objekte bzw Klassen gebunden.<br />
Auch Arrays und Str<strong>in</strong>gs s<strong>in</strong>d als Klassen implementiert.<br />
Alle Klassen s<strong>in</strong>d – direkt oder <strong>in</strong>direkt – von der elementaren Basisklasse Object abgeleitet, die e<strong>in</strong>e allgeme<strong>in</strong>e<br />
Grundfunktionalität zur Verfügung stellt.<br />
◇ Unterstützung verteilter Anwendungen (distributed)<br />
<strong>Java</strong> und se<strong>in</strong>e Standardbibliothek stellen durch entsprechende Klassen e<strong>in</strong>e effiziente High-Level-Unterstützung zur<br />
Netzwerkkommunikation zur Verfügung.<br />
Das RMI (Remote Method Invocation) API ermöglicht den Aufruf von Methoden entfernter Objekte <strong>in</strong> genau der<br />
gleichen Art und Weise wie von lokalen Objekten.<br />
Ergänzt werden diese Möglichkeiten durch die Fähigkeit des dynamischen Ladens von Klassen (und damit auch die<br />
Ausführung ihres Codes), nicht nur vom lokalen Rechner sondern auch über e<strong>in</strong> Netzwerk von entfernten Rechnern.<br />
◇ Robustheit (robust)<br />
<strong>Java</strong> ist u.a. mit dem Ziel entworfen worden, sehr zuverlässige und robuste Software zu entwickeln. Viele – aber<br />
natürlich nicht alle – Arten von Programmierfehlern werden durch <strong>Java</strong> pr<strong>in</strong>zipiell verh<strong>in</strong>dert :<br />
▻ Das Fehlen e<strong>in</strong>es Preprozessors und des Überladens von Operatoren verh<strong>in</strong>dert, dass tatsächlich anderer Code als<br />
im Quellprogramm formuliert, ausgeführt wird.<br />
▻ <strong>Java</strong> ist e<strong>in</strong>e streng typsichere Sprache ("strongly typed language"). Durch den Compiler und zur Laufzeit werden<br />
ausgedehnte Überprüfungen der richtigen Verwendung des Typ-Systems durchgeführt (Funktionsparameter, Casts)<br />
▻ Das Fehlen von Po<strong>in</strong>tern und Po<strong>in</strong>terarithmetik verh<strong>in</strong>dert viele typische C/C++-Speicherzugriffsfehler<br />
▻ Array- und Str<strong>in</strong>ggrenzen werden beim Zugriff überprüft. Dies verh<strong>in</strong>dert entsprechende Speicher-Überlauf- und<br />
Überschreibungsfehler<br />
▻ Die <strong>in</strong> <strong>Java</strong> implementierte automatische Freigabe von dynamisch allokierten aber nicht mehr benötigten Speicher<br />
(Automatic Garbage Collection) erleichtert die Programmierung und verh<strong>in</strong>dert zahlreiche mit der Speicherallokation<br />
und Speicherdeallokation zusammenhängende Fehler.<br />
▻ Das <strong>Java</strong>-Laufzeitsystem und die Klassen der Standardbibliothek machen ausgiebigen Gebrauch vom Exception<br />
Handl<strong>in</strong>g. Dies erleichtert das Erkennen und Behandeln diverser Laufzeitfehler.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 212 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong> als Programmiersprache und Ausführungsplattform (2)<br />
• Elementare Charakteristika der Programmiersprache <strong>Java</strong>, Forts.<br />
◇ Sicherheit (secure)<br />
<strong>Java</strong> stellt mehrere Sicherheitsschichten zur Verfügung, die es ermöglichen, Code aus e<strong>in</strong>em a-priori unsicheren Netz-<br />
werk (wie z.B. das Internet) herunterzuladen und mit großer – wenn auch nicht 100%-iger Sicherheit – auszuführen<br />
(z.B. Applets, dynamisches Laden von Klassen).<br />
Im wesentlichen handelt es sich hierbei um :<br />
▻ <strong>Java</strong>-Programme können weder direkt zum Speicher zugreifen (ke<strong>in</strong>e Po<strong>in</strong>ter), noch Array- oder Str<strong>in</strong>ggrenzen<br />
verletzen. Dies stellt e<strong>in</strong>en wesentlichen Schutz gegen "bösartigen" Code dar.<br />
▻ Alle <strong>Java</strong>-Klassen werden beim Laden auf Richtigkeit und Zuverlässigkeit überprüft ("byte-code verification",<br />
z.B. Überprüfung auf Stack-Über- oder Unterlauf, illegale Byte-Codes usw)<br />
▻ Der Klassenlader sucht immer zuerst nach dem lokalen Vorhandense<strong>in</strong> e<strong>in</strong>er Klasse. Dies stellt e<strong>in</strong>en gewissen Schutz<br />
gegen das "Unterschieben" e<strong>in</strong>er manipulierten Klasse ("class spoof<strong>in</strong>g") dar<br />
▻ E<strong>in</strong>e weitere Sicherheitsschicht stellt das "Sandkasten-Modell" ("sandbox model") dar, das unsicherem Code sicher-<br />
heitsrelevante Zugriffe verweigert.<br />
Z.B. ist Applets jeglicher Zugriff zum lokalen Dateisystem verboten.<br />
Weiterh<strong>in</strong> benötigen alle Bibliotheksklassen, die sicherheitsrelevante Operationen ausführen (z.B. Dateizugriff oder<br />
Netzwerkzugriff), e<strong>in</strong> SecurityManager-Objekt, das sie vor e<strong>in</strong>em entsprechenden Zugriff um Erlaubnis fragen.<br />
Die von diesem freizugebenden Zugriffe werden durch e<strong>in</strong> Security Policy File festgelegt.<br />
◇ Unterstützung von Multithread<strong>in</strong>g (multithreaded)<br />
<strong>Java</strong> enthält Sprachmittel und Bibliotheksklassen zur e<strong>in</strong>fachen Realisierung von Threads.<br />
Dadurch ist es <strong>in</strong> <strong>Java</strong> sehr leicht, Multithreaded-Anwendungen zu realisieren.<br />
• Elementare Charakteristika der Ausführungsplattform <strong>Java</strong><br />
◇ Interpretierte Programmausführung (<strong>in</strong>terpreted)<br />
Der <strong>Java</strong>-Compiler erzeugt ke<strong>in</strong>en Masch<strong>in</strong>encode sondern sogenannten Byte-Code, der zur Ausführung von e<strong>in</strong>em<br />
Interpreter, der <strong>Java</strong> Virtuellen Masch<strong>in</strong>e (<strong>Java</strong> Virtual Mach<strong>in</strong>e, JVM), abgearbeitet wird. Die JVM bildet die von<br />
<strong>Java</strong> zur Verfügung gestellte Ausführungsplattform. Zur Abarbeitung e<strong>in</strong>es <strong>Java</strong>-Programms muß diese Ausführungs-<br />
plattform, also die JVM, gestartet werden. Dieser wird der – <strong>in</strong> e<strong>in</strong>er Datei enthaltene – Byte-Code der Start-Klasse als<br />
Parameter übergeben. Die Byte-Codes der weiteren Klassen des Programm werden jeweils bei Bedarf von der JVM<br />
geladen. Der Byte-Code kann als "Mach<strong>in</strong>encode" der JVM aufgefasst werden.<br />
◇ Architektur-Neutralität und Portabilität (architecture neutral and portable)<br />
E<strong>in</strong> <strong>Java</strong>-Programm ist auf jedem System lauffähig, das e<strong>in</strong>e <strong>Java</strong> Virtuelle Masch<strong>in</strong>e zur Verfügung stellt.<br />
Der vom Compiler erzeugte Byte-Code ist architektur-neutral. Er enthält ke<strong>in</strong>e implementierungsabhängigen<br />
Elemente. Auch die Sprache <strong>Java</strong> selbst ist vollkommen implementierungsunabhängig. U.a. legt <strong>Java</strong> die Größe der<br />
e<strong>in</strong>fachen Datentypen exakt fest. Damit ist – sogar e<strong>in</strong> übersetztes – <strong>Java</strong>-Programm 100% portabel.<br />
Suns Motto für <strong>Java</strong> lautet deswegen :<br />
Write Once, Run Anywhere<br />
◇ Dynamisches Verhalten (dynamic)<br />
Jede <strong>Java</strong>-Klasse kann zu jeder Zeit <strong>in</strong> e<strong>in</strong>e laufende Virtuelle Masch<strong>in</strong>e geladen werden. E<strong>in</strong>e derart dynamisch gelade-<br />
ne Klasse kann dann dynamisch <strong>in</strong>stantiiert werden. Jede geladene Klasse wird durch e<strong>in</strong> Objekt der Klasse Class<br />
repräsentiert. Dies ermöglicht die Ermittlung von Informationen über e<strong>in</strong>e Klasse zu Laufzeit (Reflection API)<br />
◇ Hohe Leistungsfähigkeit (high-performance)<br />
Interpretierter Code ist zwar pr<strong>in</strong>zipiell immer langsamer als direkt ausgeführter Masch<strong>in</strong>encode, Sun unternimmt aber<br />
große Anstrengungen, die JVM so effizient und schnell wie möglich zu realisieren. Heutige JVMs enthalten "just <strong>in</strong> time"<br />
Compiler (JIT), die Byte-Code vor der ersten Ausführung <strong>in</strong> Masch<strong>in</strong>en-Code übersetzen. Ergänzt wird dieses Konzept<br />
durch adaptive Entscheidungsalgorithmen, die zur Laufzeit den Code bezüglich Leistungsengpässen analysieren und<br />
wenig verwendeten Code nicht übersetzen, laufzeit-kritischen dagegen bestmöglich optimieren ("Hot Spot" JVM).<br />
Darüberh<strong>in</strong>aus kann besonders zeitkritischer Programm-Code <strong>in</strong> e<strong>in</strong>er <strong>in</strong> Masch<strong>in</strong>en-Code direkt übersetzbaren<br />
Sprache formuliert, <strong>in</strong> nativen Masch<strong>in</strong>en-Code übersetzt und mittels des <strong>Java</strong> Native Interfaces (JNI) von der JVM<br />
aufgerufen werden.<br />
All diese Maßnahmen ermöglichen es, dass <strong>Java</strong>-Programme bezüglich der Ausführungsgeschw<strong>in</strong>digkeit zunehmend<br />
mit compilierten C/C++-Programmen konkurieren können.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 220 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Grundlegendes<br />
Klassen <strong>in</strong> <strong>Java</strong> - E<strong>in</strong>führung<br />
◇ Klassen s<strong>in</strong>d die elementaren Bestandteile jedes <strong>Java</strong>-Programms.<br />
Sämtlicher Code e<strong>in</strong>es <strong>Java</strong>-Programms bef<strong>in</strong>det sich <strong>in</strong>nerhalb von Klassen.<br />
E<strong>in</strong> Programm kann aus beliebig vielen Klassen bestehen.<br />
◇ E<strong>in</strong>e Klasse def<strong>in</strong>iert die Eigenschaften (den Aufbau) und das Verhalten (die Funktionalität) der von ihr <strong>in</strong>stanzierbaren<br />
Objekte. Sie ist aus Klassenkomponenten aufgebaut.<br />
Klassenkomponenten können se<strong>in</strong> :<br />
- Datenkomponenten (Membervariable) Variablendef<strong>in</strong>itionen<br />
Die Gesamtheit der Datenkomponenten beschreibt den Aufbau und – mit ihren jeweiligen konkreten Werten <strong>in</strong><br />
e<strong>in</strong>em Objekt – den Zustand der Objekte ( Objektvariable).<br />
- Funktionskomponenten (Memberfunktionen) Funktionsdef<strong>in</strong>itionen<br />
Diese legen das Verhalten, die Fähigkeiten der Objekte fest ( Objektfunktionen).<br />
◇ E<strong>in</strong>e Klasse kann auch Komponenten (sowohl Daten- als auch Funktionskomponenten) enthalten, die nicht objekt-<br />
spezifisch s<strong>in</strong>d, sondern den Zustand und das Verhalten der Klasse selbst beschreiben.<br />
Sie s<strong>in</strong>d durch den Modifizierer static gekennzeichnet.<br />
statische Datenkomponenten (Klassenvariable) bzw statische Funktionskomponenten (Klassenfunktionen)<br />
◇ Zusätzlich kann e<strong>in</strong>e Klassendef<strong>in</strong>ition<br />
- Konstruktoren enthalten<br />
Konstruktoren s<strong>in</strong>d spezielle klassenspezifische Funktionen, die bei der Objekterzeugung aufgerufen werden.<br />
Sie tragen immer den Klassennamen und besitzen ke<strong>in</strong>en Rückgabetyp (auch nicht void)<br />
Sie werden <strong>in</strong> <strong>Java</strong> nicht zu den Klassenkomponenten gerechnet.<br />
Ihre primäre Aufgabe besteht <strong>in</strong> der Initialisierung der Datenkomponenten des erzeugten Objekts.<br />
Falls e<strong>in</strong>e Klassendef<strong>in</strong>ition ke<strong>in</strong>en Konstruktor enthält, wird vom Compiler implizit e<strong>in</strong> Default-Konstruktor<br />
bereitgestellt.<br />
◇ E<strong>in</strong>e Klassendef<strong>in</strong>ition kann noch weitere Bestandteile enthalten (s. später, Kapitel 4)<br />
◇ Für den Zugriff zu den Klassenkomponenten als auch zu e<strong>in</strong>er Klasse selbst können Zugriffsberechtigungen<br />
festgelegt werden. Dies erfolgt durch die Angabe von Zugriffs-Modifizierern. Wird ke<strong>in</strong> Zugriffs-Modifizierer<br />
angegeben, so besteht Zugriff nur von <strong>in</strong>nerhalb des Packages, <strong>in</strong> dem die Klasse def<strong>in</strong>iert ist.<br />
Soll e<strong>in</strong> Zugriff von überall her möglich se<strong>in</strong> (öffentlicher Zugriff), so muß die Klasse bzw die entsprechende<br />
Komponente durch den vorangestellten Zugriffs-Modifizierer public gekennzeichnet werden.<br />
Für Klassenkomponenten existieren noch die Zugriffs-Modifizierer private (Zugriff nur von <strong>in</strong>nerhalb der Klasse)<br />
und protected (Zugriff beschränkt auf die Klasse selbst, abgeleitete Klassen und das Package) ( Kapselung !)<br />
• Vere<strong>in</strong>fachte Syntax der Klassendef<strong>in</strong>ition<br />
(vollständiges Syntax-Diagramm s. Kapitel 4)<br />
public<br />
class Klassen-Name<br />
◇ E<strong>in</strong>fachste Klassendef<strong>in</strong>ition : class Simple<br />
{ ;<br />
}<br />
◇ E<strong>in</strong> etwas s<strong>in</strong>nvolleres Beispiel : class Uhr<br />
{ private long actTime; // Datenkomponente<br />
}<br />
void setTime(long time)<br />
{ actTime = time; }<br />
long tick() // Funktionskomponenten<br />
{ ++actTime; }<br />
void displayClock()<br />
{ /* ... */ };<br />
{<br />
Komponentendef<strong>in</strong>ition<br />
Konstruktordef<strong>in</strong>ition<br />
;<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 221 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Modulkonzept<br />
◇ E<strong>in</strong> <strong>Java</strong>-Programm besteht nur aus Klassen.<br />
Struktur von <strong>Java</strong>-Programmen (1)<br />
◇ Jede Klasse muß <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zigen Quelldatei vollständig def<strong>in</strong>iert und implementiert werden.<br />
E<strong>in</strong>e Aufteilung <strong>in</strong> Def<strong>in</strong>itionsdatei (Headerdatei) und Implementierungsdatei wie <strong>in</strong> C++ existiert <strong>in</strong> <strong>Java</strong> nicht.<br />
<strong>Java</strong>-Quelldateien erhalten die Extension .java<br />
◇ Jede Klasse ist <strong>in</strong> e<strong>in</strong>er eigenen Quelldatei zu def<strong>in</strong>ieren.<br />
Ausnahme : e<strong>in</strong>gebettete Klassen (nested classes).<br />
Der Quelldatei-Hauptname muß wie der (Haupt-)Klassenname lauten.<br />
Beispiel : Klasse Welcome Quelldate<strong>in</strong>ame : Welcome.java<br />
◇ E<strong>in</strong>e Quelldatei ist die Übersetzungse<strong>in</strong>heit (Übersetzungs-Modul).<br />
Für jede enthaltene Klasse wird vom Compiler e<strong>in</strong>e eigene Byte-Code-Datei erzeugt.<br />
Die Byte-Code-Datei für die (Haupt-)Klasse bekommt den Hauptnamen der Quellcode-Datei und die<br />
Extension .class<br />
Beispiel : Aus Welcome.java erzeugt der Compiler Welcome.class<br />
Die Hauptnamen der übrigen Byte-Code-Dateien s<strong>in</strong>d aus den Namen der Haupt-Klasse und der e<strong>in</strong>gebetteten Klassen<br />
zusammengesetzt.<br />
• Programmstruktur<br />
◇ E<strong>in</strong> L<strong>in</strong>ken der getrennt übersetzten Module (Klassen-Dateien) zu e<strong>in</strong>er – ausführbaren – Programm-Datei f<strong>in</strong>det <strong>in</strong> <strong>Java</strong><br />
nicht statt.<br />
◇ E<strong>in</strong> <strong>Java</strong>-Programm ist damit nicht <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zigen Datei zusammengefasst.<br />
Vielmehr besteht es – entsprechend den im Programm e<strong>in</strong>gesetzten Klassen – aus e<strong>in</strong>er oder mehreren Dateien.<br />
◇ E<strong>in</strong>e dieser Dateien enthält die Start-Klasse des Programms.<br />
◇ Ausgehend von der Start-Klasse werden die übrigen Klassen des Programms referiert.<br />
• Programmarten<br />
◇ Es werden zwei <strong>Java</strong>-Programmarten unterschieden :<br />
▻ Applikations-Programme<br />
▻ Applets<br />
◇ Applikationsprogramme<br />
"Normale" <strong>Java</strong>-Programme. Sie werden durch direkten Start der Virtuellen Masch<strong>in</strong>e (JVM) ausgeführt.<br />
Hierfür ist dieser beim Start die Start-Klasse des Programms als Parameter zu übergeben<br />
◇ Applets<br />
Diese Programme werden <strong>in</strong>nerhalb e<strong>in</strong>es <strong>Java</strong>-fähigen Web-Browsers (oder im Kontext e<strong>in</strong>es anderen "applet<br />
viewers") ausgeführt. E<strong>in</strong> derartiger Browser (bzw "applet viewer") enthält e<strong>in</strong>e – gegebenenfalls über e<strong>in</strong> Plug-In<br />
e<strong>in</strong>gebundene – JVM. Der Applet-Code bef<strong>in</strong>det sich üblicherweise auf e<strong>in</strong>em Server und wird durch e<strong>in</strong> -<br />
Tag im HTML-Code e<strong>in</strong>er Web-Seite referiert. Stößt der Browser beim Interpretieren des HTML-Codes auf e<strong>in</strong> derar-<br />
tiges -Tag, startet er se<strong>in</strong>e JVM. Diese lädt von der angegebenen URL den Byte-Code der Start-Klasse des<br />
Applets und führt ihn aus.<br />
Applets s<strong>in</strong>d damit – i.a. kle<strong>in</strong>e – Programme, die <strong>in</strong> e<strong>in</strong>facher Art und Weise über das Internet verteilt werden können.<br />
Da Applets pr<strong>in</strong>zipiell unzuverlässigen Code enthalten können, unterliegt ihre Ausführung strengen Sicherheits-<br />
restriktionen.<br />
Der Start und die Ausführung e<strong>in</strong>es Applets unterscheidet sich aber erheblich von Start und Ausführung e<strong>in</strong>es<br />
Applikations-Programms.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 222 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Start-Klasse e<strong>in</strong>es <strong>Java</strong>-Applikations-Programms<br />
Struktur von <strong>Java</strong>-Programmen (2)<br />
◇ Die der JVM beim Start zu übergebene Klasse muß – neben möglicherweise beliebig vielen anderen Methoden – e<strong>in</strong>e<br />
statische ma<strong>in</strong>()-Methode besitzen.<br />
Diese ma<strong>in</strong>()-Methode muß öffentlich zugänglich (public) und vom Typ void se<strong>in</strong>.<br />
Als formalen Parameter muß sie e<strong>in</strong> Str<strong>in</strong>g-Array besitzen.<br />
Sie stellt den Startpunkt der Programmausführung dar.<br />
◇ Beispiel für e<strong>in</strong> m<strong>in</strong>imales <strong>Java</strong>-Programm :<br />
// Welcome.java<br />
public class Welcome<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
System.out.pr<strong>in</strong>tln("Welcome to the world of <strong>Java</strong>");<br />
}<br />
}<br />
◇ I.a. ist e<strong>in</strong> <strong>Java</strong>-Programm nicht klassenorientiert sondern objekttorientiert. D.h. im Programm werden Objekte<br />
erzeugt, die mite<strong>in</strong>ander kommunizieren.<br />
Die Erzeugung des "ersten" Objekts erfolgt dann <strong>in</strong> der ma<strong>in</strong>()-Methode der Start-Klasse :<br />
▻ Entweder durch Instantiierung e<strong>in</strong>er anderen Klasse (Start-Klasse dient nur zum Programmstart)<br />
▻ oder durch Instantiierung der eigenen Klasse (Start-Klasse enthält auch spezifische Programmfunktionalität)<br />
◇ Ausgehend vom ersten Objekt werden dann die weiteren Objekte erzeugt.<br />
◇ Beispiel für e<strong>in</strong> m<strong>in</strong>imales <strong>Java</strong>-Programm mit Objekterzeugung :<br />
// Willkommen.java<br />
public class Willkommen<br />
{<br />
Willkommen() // Konstruktor<br />
{<br />
// nur zur Demonstration<br />
}<br />
}<br />
void begruessung() // Memberfunktion<br />
{<br />
System.out.pr<strong>in</strong>tln("Willkommen bei <strong>Java</strong>");<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Willkommen gruss = new Willkommen(); // Erzeugung e<strong>in</strong>es Objekts<br />
grus.begruessung();<br />
}<br />
◇ Anmerkung :<br />
Häufig wird auch bei Klassen, die <strong>in</strong> der späteren Verwendung nicht als Start-Klassen dienen sollen, e<strong>in</strong>e statische<br />
ma<strong>in</strong>()-Methode vorgesehen. Diese Methode enthält dann i.a. Code, der das – weitgehend isolierte – Testen der<br />
Klasse ermöglicht.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 231 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Vom Quellprogramm zur Programmausführung<br />
Erzeugung und Start von <strong>Java</strong>-Programmen<br />
weitere<br />
Byte-Code-Dateien<br />
• Aufruf des <strong>Java</strong>-Compilers (Kommandozeilen-Tool javac des JDK)<br />
◇ Der Compiler sucht die zu übersetzende Quelldatei ausgehend vom aktuellen Arbeitsdirectory.<br />
Bef<strong>in</strong>det sich die Datei <strong>in</strong> e<strong>in</strong>em anderen Directory, ist e<strong>in</strong> entsprechender Zugriffspfad anzugeben.<br />
◇ Der Name der zu übersetzenden Quelldatei ist e<strong>in</strong>schließlich der Extension .java anzugeben.<br />
◇ Beispiel : Quelldatei Welcome.java im Directory E:\<strong>Java</strong>\Vorl<br />
E:\<strong>Java</strong>\Vorl>javac Welcome.java<br />
◇ Der Compiler erzeugt – bei Fehlerfreiheit – e<strong>in</strong>e Byte-Code-Datei (hier : Welcome.class) im Verzeichnis der<br />
Quelldatei.<br />
◇ Fehler werden zusammen mit der Zeilennummer und dem Quelldate<strong>in</strong>amen gemeldet.<br />
◇ Werden <strong>in</strong> e<strong>in</strong>er Quelldatei weitere Klassen referiert und f<strong>in</strong>det der Compiler ke<strong>in</strong>e entsprechenden .class-Dateien,<br />
versucht er diese durch zusätzliches Übersetzen der entsprechenden .java-Dateien zu erzeugen.<br />
(Ausnahme : Klassen der Standardbibliothek)<br />
• Aufruf des <strong>Java</strong>-Interpreters (Kommandozeilen-Tool java des JDK)<br />
◇ Dem <strong>Java</strong>-Interpreter ist der Klassenname (nicht der Date<strong>in</strong>ame, d.h. ke<strong>in</strong>e Extension !) der Start-Klasse als<br />
Kommandozeilenparameter zu übergeben.<br />
◇ Der <strong>Java</strong>-Interpreter sucht nach der Byte-Code-Datei der Start-Klasse im aktuellen Directory und – falls dort nicht<br />
vorhanden – <strong>in</strong> den Directories, die <strong>in</strong> der Environment-Variablen CLASSPATH enthalten s<strong>in</strong>d.<br />
◇ Beispiel : Byte-Code-Datei Welcome.class (mit Klasse Welcome) im Verzeichnis E:\<strong>Java</strong>\Vorl<br />
CLASSPATH-Variable ist nicht gesetzt.<br />
E:\<strong>Java</strong>\Vorl>java Welcome<br />
Quell-Datei<br />
(z.B.Welcome.java)<br />
<strong>Java</strong>-Compiler<br />
Byte-Code-Datei<br />
(z.B.Welcome.class)<br />
<strong>Java</strong>-Interpreter<br />
(<strong>Java</strong> Virtual Mach<strong>in</strong>e)<br />
javac<br />
java<br />
◇ Werden von der Start-Klasse weitere Klassen benötigt, sucht der Interpreter die entsprechenden Byte-Code-Dateien im<br />
aktuellen Directory bzw <strong>in</strong> den Directories der CLASSPATH-Variablen (Ausnahme : Klassen der Standardbibliothek)<br />
◇ Wird e<strong>in</strong>e benötigte Byte-Code-Datei nicht gefunden, wird die Exception NoClassDefFoundError erzeugt.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHISCHE INFORMATIK V – JV – 232 – 01 – TH – 01<br />
------------------------------------------------------------------------------------<br />
• Grundsätzliches<br />
<strong>Java</strong>-Archiv-(JAR-) Dateien (1)<br />
◇ Das JAR-Dateiformat ermöglicht die Zusammenfassung von mehreren Dateien <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zigen Datei<br />
( JAR-Archiv). Es ist plattform-unabhängig und basiert auf dem ZIP-Dateiformat.<br />
◇ Es dient im wesentlichen zur Zusammenfassung<br />
▻ von mehreren class-Dateien <strong>in</strong> e<strong>in</strong>em e<strong>in</strong>zigen Bibliotheks-Archiv<br />
▻ von den zu e<strong>in</strong>er <strong>Java</strong>-Applikation (oder e<strong>in</strong>em Applet) gehörenden Dateien (class-Dateien und sonstige<br />
Dateien, wie benötigte Daten-Dateien usw) zu e<strong>in</strong>er e<strong>in</strong>zigen Datei.<br />
◇ E<strong>in</strong>e JAR-Datei enthält neben den zusammengefassten Dateien im allgeme<strong>in</strong>en auch Meta-Informationen über<br />
bestimmte Eigenschaften und die Verwendung des Archivs.<br />
Diese bef<strong>in</strong>den sich <strong>in</strong> Dateien, die <strong>in</strong> dem bei der Archiverzeugung – automatisch – h<strong>in</strong>zugefügten Directory<br />
META-INF angelegt werden. Die wichtigste dieser Meta-Informations-Dateien ist die Manifest-Datei MANIFEST.MF.<br />
U.a. enthält diese den CLASSPATH für zu verwendende Bibliotheken (außer Standard-Bibliothek)<br />
(E<strong>in</strong>trag Class-Path:)sowie die Startklasse bei Applikations-Archiven (E<strong>in</strong>trag Ma<strong>in</strong>-Class:)<br />
Anmerkung : Die Erzeugung des Directories META-INF und der Datei MANIFEST.MF kann unterdrückt werden.<br />
• Erzeugung und Manipulation von JAR-Dateien<br />
◇ Hierfür ist im JDK das Programm jar (<strong>Java</strong> Archive Tool) enthalten<br />
◇ Die Arbeitsweise dieses Programms wird durch Kommando-Optionen gesteuert.<br />
◇ Überblick über e<strong>in</strong>ige wichtige mit dem Programm jar ausführbare Operationen :<br />
Erzeugung e<strong>in</strong>er jar-Datei jar cf jar-file <strong>in</strong>put-file(s)<br />
Erzeugung e<strong>in</strong>er jar-Datei für e<strong>in</strong>e jar cfe jar-file startklasse <strong>in</strong>put-file(s)<br />
<strong>Java</strong>-Anwendung<br />
(gleichzeitige Festlegung der Startklasse) (Angabe des vollqualifizierten Klassennamens für die Startklasse)<br />
Update e<strong>in</strong>er existierenden jar-Datei jar uf jar-file <strong>in</strong>put-file(s)<br />
(H<strong>in</strong>zufügen weiterer Dateien,<br />
Überschreiben vorhandener Dateien)<br />
Ausgabe des Inhalts e<strong>in</strong>er jar-Datei jar tf jar-file<br />
Extraktion des Inhalts e<strong>in</strong>er jar-Datei jar xf jar-file<br />
Anmerkungen : Für die <strong>in</strong> e<strong>in</strong> JAR-Archiv aufzunehmenden Dateien (<strong>in</strong>put-file(s)) gilt :<br />
- Mehrere Datei-Angaben s<strong>in</strong>d durch Blanks zu trennen<br />
- Gegebenenfalls ist der jeweilige Zugriffspfad anzugeben.<br />
Insbesondere trifft dies für class-Dateien <strong>in</strong> e<strong>in</strong>er Package-Struktur zu.<br />
- Die Angabe des Wildcard-Zeichens * ist zulässig<br />
- Die Angabe von Directories ist zulässig. Es werden die Directories sowie alle Dateien, die sich <strong>in</strong><br />
dem Directory und den darunterliegenden Directories bef<strong>in</strong>den, e<strong>in</strong>gebunden<br />
◇ Beispiel : JAR-Datei PkDemo.jar soll zusammenfassen (Dateipfade beziehen sich auf das aktuelle Directory) :<br />
- Klasse vrl.pk1.PkDem1 (Datei-Pfad : vrl\pk1\PkDem1.class)<br />
- Klasse vrl.pk2.PkDemUse (Datei-Pfad : vrl\pk2\PkDemUse.class)<br />
Klasse vrl.pk2.PkDemUse ist Startklasse<br />
jar cfe PkDem.jar vrl.pk2.PackDemUse vrl\pk1\PkDem1.class vrl\pk2\PkDemUse.class
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHISCHE INFORMATIK V – JV – 232 – 02 – TH – 01<br />
------------------------------------------------------------------------------------<br />
<strong>Java</strong>-Archiv-(JAR-) Dateien (2)<br />
• Start e<strong>in</strong>er <strong>Java</strong>-Applikation, die sich <strong>in</strong> e<strong>in</strong>er JAR-Datei bef<strong>in</strong>det<br />
◇ durch Aufruf des <strong>Java</strong>-Interpreters mit der jar-Option.<br />
Statt der Startklasse ist dem Interpreter die JAR.Datei, die die Startklasse enthält, zu übergeben.<br />
Programmparameter können – wie bei der direkten Angabe e<strong>in</strong>er Startklasse – zusätzlich übergeben werden.<br />
◇ Beispiel : Start der <strong>in</strong> PkDem.jar enthaltenen Applikation.<br />
Der Applikation ist die Datei daten.txt als Programmparameter zu übergeben<br />
<br />
• Aufnahme von CLASSPATH-Info <strong>in</strong> e<strong>in</strong>e JAR-Datei<br />
◇ Es gibt Situationen bei denen e<strong>in</strong>e <strong>in</strong> e<strong>in</strong>er JAR-Datei zusammengefasste Applikation (oder Applet) Klassen benötigt,<br />
die weder <strong>in</strong> der JAR-Datei enthalten noch über die aktuelle CLASSPATH-Variable zugänglich s<strong>in</strong>d (Klassen <strong>in</strong> e<strong>in</strong>er<br />
speziellen Bibliothek).<br />
◇ Die für den Zugriff zu diesen Klassen notwendige – temporäre – Ergänzung des Klassenpfades kann durch Aufnahme<br />
entsprechender Informationen <strong>in</strong> die Manifest-Datei des JAR-Archivs erreicht werden.<br />
◇ Dies wird folgendermaßen ermöglicht :<br />
▻ Die zusätzlich benötigten Bibliotheksklassen müssen <strong>in</strong> e<strong>in</strong>er oder mehreren weiteren JAR-Dateien zusammenge-<br />
fasst se<strong>in</strong>.<br />
▻ Diese JAR-Dateien dürfen nicht <strong>in</strong> der sie benutzenden JAR-Datei enthalten se<strong>in</strong>.<br />
▻ Erstellung e<strong>in</strong>er Text-Datei, die den <strong>in</strong> die Manifest-Datei aufzunehmenden Class-Path –Header enthält :<br />
Class-Path: jar-file(s) (Angabe der Zugriffspfade, mehrere durch Leerzeichen getrennt)<br />
Diese Textdatei muss mit e<strong>in</strong>em Zeilenende-Zeichen abgeschlossen se<strong>in</strong>.<br />
▻ Bei der Erzeugung des JAR-Archivs ist zusätzlich die Option m sowie die Manifest-Text-Datei anzugeben :<br />
jar cfem jar-file startklasse manifest-text-file <strong>in</strong>put-file(s)<br />
◇ Beispiel : Im Directory AppTest s<strong>in</strong>d die beiden Directories MyLib und MyApp e<strong>in</strong>getragen.<br />
Das Directory MyLib enthält die JAR-Datei MyUtil.jar. Diese fasst e<strong>in</strong>ige Utility-Klassen, die von<br />
mehreren Applikationen benötigt werden, zusammen.<br />
E<strong>in</strong>e dieser Applikationen wird durch die Klassen App1 und AppHelp1 gebildet.<br />
Ihre Klassendateien bef<strong>in</strong>den sich im Directory MyApp <strong>in</strong> e<strong>in</strong>er Directory-Struktur, die ihre Package-<br />
Struktur nachbildet : hm\ee\jvpr1\App1.class bzw hm\ee\jvpr1\AppHelp1.class.<br />
Startklasse sei die Klasse App1.<br />
Für die Applikation soll im Verzeichnis MyApp die JAR-Datei App1.jar erzeugt werden :<br />
<br />
java –jar PkDem.jar daten.txt<br />
Erzeugung der Text-Datei Manifest.txt mit dem Inhalt (im Directory MyApp) :<br />
Class-Path: ..\MyLib\MyUtil.jar<br />
Erzeugung der JAR-Datei App1.jar:<br />
jar cfem App1.jar hm.ee.jvpr1.App1 Manifest.txt hm\ee\jvpr1\*.class
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 241 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Packages als Namensräume<br />
Packages <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Klassen lassen sich <strong>in</strong> <strong>Java</strong> <strong>in</strong> Paketen (Packages) zusammenfassen.<br />
Packages s<strong>in</strong>d die <strong>Java</strong>-Entsprechung der Namensräume (name spaces) von C++.<br />
◇ Packages haben e<strong>in</strong>en Namen und können hierarchisch strukturiert (Package Unter-Package) se<strong>in</strong>.<br />
Package-Namen können aus mehreren Bestandteilen bestehen, die durch e<strong>in</strong>en Punkt (.) vone<strong>in</strong>ander getrennt s<strong>in</strong>d.<br />
◇ Damit lässt sich e<strong>in</strong>e Klasse über e<strong>in</strong>en vollständigen (voll-qualifizierten) Klassennamen ansprechen.<br />
Dieser besteht aus dem eigentlichen Klassennamen, dem der durch e<strong>in</strong>en Punkt (.) abgetrennte Package-Name<br />
vorangestellt ist.<br />
Beispiel : Klasse Date im Package java.util<br />
voll-qualifizierter Klassenname : java.util.Date<br />
◇ Mittels Packages lassen sich Namenskonflikte, <strong>in</strong>sbesondere zwischen Klassen unterschiedlicher Hersteller (Biblio-<br />
theken), weitgehend vermeiden.<br />
◇ Empfohlene Konvention zur Vergabe von Package-Namen :<br />
Beg<strong>in</strong>n des Package-Namens mit dem <strong>in</strong>vertierten Internet-Doma<strong>in</strong>-Namen des Herstellers.<br />
Beispiel : Fa. SESA, Internet-Doma<strong>in</strong>-Name : sesa.com<br />
Package-Name : com.sesa.wmf<br />
Es ist auch üblich, aus Gründen der Übersichtlichkeit den Top-Level-Doma<strong>in</strong>-Namen wegzulassen.<br />
◇ Klassen, die explizit ke<strong>in</strong>em Package zugeordnet s<strong>in</strong>d, bef<strong>in</strong>den sich im namenlosen Package (unnamed package).<br />
Für die Verwendung <strong>in</strong> Bibliotheken s<strong>in</strong>d derartige Klassen nicht geeignet.<br />
• Packages als Directory-Struktur<br />
◇ E<strong>in</strong> strukturierter Package-Name wird <strong>in</strong> e<strong>in</strong>e entsprechende Directory-Struktur abgebildet.<br />
◇ Beispiel : Klassen-Dateien des Packages com.sesa.wmf bef<strong>in</strong>den sich im Verzeichnis com\sesa\wmf<br />
◇ Das Start-Verzeichnis e<strong>in</strong>er derartigen Directory-Struktur muss sich im aktuellen Verzeichnis oder <strong>in</strong> e<strong>in</strong>em über<br />
die CLASSPATH-Variable festgelegten Verzeichnis bef<strong>in</strong>den.<br />
◇ Package-Namen ermöglichen damit e<strong>in</strong>e strukturierte und dadurch übersichtliche Ablage von Klassen-Dateien.<br />
◇ Klassen-Dateien des namenlosen Package müssen direkt im aktuellen Directory bzw <strong>in</strong> e<strong>in</strong>em durch die CLASSPATH-<br />
Variable festgelegten Verzeichnis liegen.<br />
• Package-Zuordnung e<strong>in</strong>er Klasse<br />
◇ Hierzu dient die package-Vere<strong>in</strong>barung<br />
Beispiel : package fhm.ee.vorl;<br />
Package-Name . Klassenname<br />
package Package-Name ;<br />
◇ Die package-Vere<strong>in</strong>barung muss am Beg<strong>in</strong>n e<strong>in</strong>er Quelldatei (erste Vere<strong>in</strong>barung) stehen.<br />
Sie legt fest, dass die nachfolgend def<strong>in</strong>ierte Klasse zu dem angegebenen Package gehört.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 242 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Verwendung von Klassen des eigenen Packages<br />
Packages <strong>in</strong> <strong>Java</strong> (2)<br />
◇ E<strong>in</strong>e Klasse kann e<strong>in</strong>e andere Klasse ihres eigenen Packages alle<strong>in</strong> mit dem e<strong>in</strong>fachen Klassennamen verwenden.<br />
◇ Jede Klasse e<strong>in</strong>es Packages hat Zugriff zu den anderen Klassen desselben Packages, die nicht private s<strong>in</strong>d, auch<br />
wenn sie nicht explizit public deklariert s<strong>in</strong>d.<br />
• Verwendung von Klassen aus anderen Packages<br />
◇ E<strong>in</strong>e Klasse kann zu Klassen aus e<strong>in</strong>em anderen Package nur zugreifen, wenn diese explizit public deklariert s<strong>in</strong>d.<br />
◇ Für die Verwendung bestehen zwei unterschiedliche Möglichkeiten :<br />
▻ Verwendung des voll-qualifizierten Namens.<br />
▻ Importieren der Klassen und Verwendung der e<strong>in</strong>fachen Klassennamen<br />
◇ Verwendung des voll-qualifizierten Namens :<br />
Beispiel : Verwendung der Klasse Date aus dem Package java.util<br />
// Datum1.java<br />
public class Datum1<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ java.util.Date now = new java.util.Date();<br />
System.out.pr<strong>in</strong>tln(now);<br />
}<br />
}<br />
Nachteil : Klassennamen können sehr lang und damit unhandlich werden.<br />
• Importieren von Klassen aus anderen Packages<br />
◇ Hierzu dient die import-Deklaration. Diese existiert <strong>in</strong> zwei Formen :<br />
▻ Importieren e<strong>in</strong>er e<strong>in</strong>zelnen Klasse<br />
▻ Importieren aller Klassen e<strong>in</strong>es Packages (type import on demand), aber nicht von dessen Unter-Packages<br />
◇ Beispiel : Verwendung der Klasse Date aus dem Package java.util<br />
// Datum2.java<br />
import voll-qualifizierter Klassenname ;<br />
import Package-Name . * ;<br />
import java.util.Date; // oder : import java.util.*;<br />
public class Datum2<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Date now = new Date();<br />
System.out.pr<strong>in</strong>tln(now);<br />
}<br />
}<br />
◇ Anmerkung : Importieren bedeutet ke<strong>in</strong> E<strong>in</strong>b<strong>in</strong>den von Code anderer Klassen.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 243 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Zugriffsberechtigung "package"<br />
Packages <strong>in</strong> <strong>Java</strong> (3)<br />
◇ <strong>Java</strong> kennt neben den Zugriffsberechtigungen private, protected und public die weitere Zugriffsberechtigung<br />
package.<br />
◇ Diese Zugriffsberechtigung haben alle Klassenkomponenten e<strong>in</strong>er Klasse, die nicht explizit als public,<br />
protected oder private gekennzeichnet s<strong>in</strong>d.<br />
Default-Zugriffsberechtigung<br />
◇ Diese Zugriffsberechtigung erlaubt den Zugriff durch alle Klassen desselben Packages.<br />
◇ Die Zugriffsberechtigung durch e<strong>in</strong> Package erstreckt sich nicht auf dessen eventuelle Unter-Packages.<br />
Klassen aus Unter-Packages haben ke<strong>in</strong>en Zugriff zu package-Komponenten von Klassen ihres Ober-Packages.<br />
◇ Anmerkung zur Zugriffsberechtigung protected :<br />
Sie umfasst <strong>in</strong> <strong>Java</strong> auch die Zugriffsberechtigung package.<br />
Zu Klassenkomponenten mit der Zugriffsberechtigung protected können neben den abgeleiteten Klassen auch alle<br />
Klassen desselben Packages zugreifen.<br />
◇ Beispiel :<br />
package vorl.pack1;<br />
public class PackAccDemo<br />
{<br />
<strong>in</strong>t ipa; // Zugriffsberechtigung package<br />
protected <strong>in</strong>t ipo;<br />
public <strong>in</strong>t ipu;<br />
}<br />
// ...<br />
package vorl.pack1;<br />
class PackAccDemoUse1<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ PackAccDemo demo = new PackAccDemo();<br />
System.out.pr<strong>in</strong>tln("PackAckDemo.ipa (package) : " + demo.ipa);<br />
System.out.pr<strong>in</strong>tln("PackAckDemo.ipu (public) : " + demo.ipu);<br />
System.out.pr<strong>in</strong>tln("PackAckDemo.ipo (protected) : " + demo.ipo);<br />
}<br />
}<br />
package vorl.pack1.sub;<br />
import vorl.pack1.PackAccDemo;<br />
class PackAccDemoUse2<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ PackAccDemo demo = new PackAccDemo();<br />
//System.out.pr<strong>in</strong>tln("PackAckDemo.ipa (package) : " + demo.ipa);<br />
System.out.pr<strong>in</strong>tln("PackAckDemo.ipu (public) : " + demo.ipu);<br />
//System.out.pr<strong>in</strong>tln("PackAckDemo.ipo (protected) : " + demo.ipo);<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 251 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Die <strong>Java</strong> Standard-Bibliothek (1)<br />
◇ Die <strong>Java</strong>-Plattform stellt auch e<strong>in</strong>e Laufzeit-Bibliothek (API) zur Verfügung.<br />
◇ Diese sehr umfangreiche <strong>Java</strong> Standard-Bibliothek enthält zahlreiche nützliche Klassen für diverse Anwendungs-<br />
bereiche.<br />
E<strong>in</strong>e Reihe dieser Klassen implementieren wesentliche Spracheigenschaften und s<strong>in</strong>d damit sehr eng mit der Sprache<br />
selbst verknüpft.<br />
◇ Die Klassen der Standardbibibliothek s<strong>in</strong>d auf verschiedene APIs aufgeteilt und <strong>in</strong> Paketen (Packages) zusammen-<br />
gefasst. Dabei ist die Zuordnung der e<strong>in</strong>zelnen Klassen zu den verschiedenen Paketen nicht immer ganz stimmig,<br />
<strong>in</strong>sbesondere stimmen die API-Grenzen nicht immer mit den Paketgrenzen übere<strong>in</strong>.<br />
◇ Zu vielen der Haupt-Paketen existieren Unter-Pakete.<br />
◇ Die Pakete der im JDK enthaltenen <strong>Java</strong> Standard-Bibliothek lassen sich <strong>in</strong> drei Gruppen e<strong>in</strong>teilen :<br />
▻ Standard-Pakete. Sie gehören zu jeder <strong>Java</strong>-Plattform<br />
▻ Standard-Erweiterungs-Pakete. Sie stellen erweiterte und ergänzende Funktionalitäten zur Verfügung und<br />
müssen nicht unbed<strong>in</strong>gt auf jeder <strong>Java</strong>-Plattform zur Verfügung stehen<br />
▻ Ergänzende Pakete von Dritt-Herstellern. Sie ergänzen und erweitern ebenfalls die Funktionalität der Bibliothek.<br />
◇ Die <strong>Java</strong> Standard-Bibliothek ist ständig erweitert worden.<br />
(JDK 1.0 : 8 Pakete, JDK 1.4 über 130 Pakete, JDK 5.0 über 170 Pakete, JDK 6.0 203 Pakete)<br />
◇ Sun stellt <strong>in</strong> der das JDK begleitenden Dokumentation e<strong>in</strong>e ausführliche Beschreibung der Klassen zur Verfügung<br />
(<strong>Java</strong> Platform API Specification)<br />
• Überblick über die Standard-Pakete<br />
◇ Die Namen der Standard-Pakete beg<strong>in</strong>nen mit java.<br />
◇ Die folgende Tabelle gibt nur e<strong>in</strong>en Überblick über die Haupt-Pakete dieser Gruppe<br />
java.applet Applets<br />
java.awt Abstract W<strong>in</strong>dow<strong>in</strong>g Toolkit : Erzeugung von GUIs, mehrere Unter-Pakete<br />
java.beans <strong>Java</strong> Beans (Komponenten-Architektur von <strong>Java</strong>), e<strong>in</strong> Unter-Paket<br />
java.io E<strong>in</strong>-/Ausgabe mittels Streams, Dateien und Serialisierung<br />
java.lang Elementare Sprachunterstützung, fünf Unter-Pakete<br />
java.math Unterstützung von Ganzzahl- und Gleitpunkt-Arithmetik<br />
java.net Unterstützung von Netzwerkanwendungen<br />
java.nio New I/O Package, verbesserter I/O-Unterstützung, ab JDK 1.4, vier Unter-Pakete<br />
java.rmi Remote Method Invocation, Entfernte Objekt-Kommunikation, vier Unter-Pakete<br />
java.security Sicherheits-Framework, vier Unter-Pakete<br />
java.sql Datenbankzugriff<br />
java.text Erweiterte Textdarstellung und –bearbeitung, Internationalisierung, e<strong>in</strong> Unter-Paket<br />
java.util Utility-Klassen, Collection Framework, spezielle Datenstrukturen, neun Unter-Pakete
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 252 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
Die <strong>Java</strong> Standard-Bibliothek (2)<br />
• Überblick über die Standard-Erweiterungs-Pakete<br />
◇ Die Namen der Standard-Erweiterungs-Pakete beg<strong>in</strong>nt mit javax.<br />
◇ Die folgende Tabelle gibt nur e<strong>in</strong>en Überblick über die Haupt-Pakete dieser Gruppe (hier : Standard Edition)<br />
javax.accessibility Unterstützung spezieller I/O-Geräte (z.B. für Braille-Zeichen)<br />
javax.activation<br />
javax.activity spezielle Exception-Klassen im Zusammenhang mit der CORBA-Serialisierung<br />
javax.annotation Unterstützung von Annotations, e<strong>in</strong> Unter-Paket<br />
javax.crypto Unterstützung kryptographischer Operationen, zwei Unter-Pakete<br />
javax.imageio I/O von Bilddateien, mehrere Unter-Pakete<br />
javax.jws Unterstützung von Web Services, e<strong>in</strong> Unter-Paket<br />
javax.lang.model Unterstützung der Modellierung der Sprache <strong>Java</strong>, drei Unter-Pakete<br />
javax.management <strong>Java</strong> Management Erweiterungen, mehrere Unter-Pakete<br />
javax.nam<strong>in</strong>g Zugriff zu Namensdiensten, vier Unter-Pakete<br />
javax.net Ergänzung zur Netzwerkunterstützung, e<strong>in</strong> Unter-Paket<br />
javax.pr<strong>in</strong>t Pr<strong>in</strong>t Service API, Zugriff zu Pr<strong>in</strong>t Services, drei Unter-Pakete<br />
javax.rmi Ergänzung zum RMI-API, zwei Unter-Pakete<br />
javax.script Script<strong>in</strong>g API (Def<strong>in</strong>ition von <strong>Java</strong> Script<strong>in</strong>g Eng<strong>in</strong>es)<br />
javax.security Ergänzung zum Sicherheits-Framework, besteht nur aus Unter-Paketen<br />
javax.sound Sound API, besteht nur aus Unter-Paketen<br />
javax.sql Ergänzung zum Datenbankzugriffs-API (serverseitig), drei Unter-Pakete<br />
javax.sw<strong>in</strong>g Sw<strong>in</strong>g Toolkit, Erweiterungen zur GUI-Erzeugung, zahlreiche Unter-Pakete<br />
javax.tools Interfaces und Klassen für Tools zum Starten aus Programmen heraus<br />
javax.transaction Unterstützung von Transaktionen, e<strong>in</strong> Unter-Paket<br />
javax.xml Zugriff zu XML-Dateien, zahlreiche Unter-Pakete<br />
• Ergänzende Pakete von Drittherstellern<br />
◇ Hierzu gehören zahlreiche Pakete unterhalb der org.omg.-Hierarchie.<br />
Sie stellen im wesentlichen CORBA-Unterstützung zur Verfügung<br />
◇ Weitere Pakete bef<strong>in</strong>den sich unter den Hierachien org.w3c. und org.xml.<br />
Sie bieten Unterstützung für den Zugriff zu XML-Dateien.<br />
◇ Das Paket org.ietf.jgss stellt e<strong>in</strong> Framework zur Nutzung von Sicherheitsdiensten (Authentifizierung, Daten-<br />
Sicherheit, Daten-Integrität usw) unterschiedlichster Mechanismen (wie z.B. Kerberos) zur Verfügung<br />
• Verwendung der <strong>Java</strong> Standard-Bibliothek<br />
◇ Zur Verwendung von Komponenten der Standard-Bibliothek <strong>in</strong> eigenen Programmen werden entsprechende import-<br />
Vere<strong>in</strong>barungen benötigt, wenn nicht voll-qualifizierte Namen verwendet werden sollen.<br />
Ausnahme : Das Paket java.lang ist so eng mit der Sprache verknüpft, dass es automatisch durch den<br />
Compiler e<strong>in</strong>gebunden wird. E<strong>in</strong>e explizite import-Anweisung ist daher für Komponenten aus diesem Paket<br />
nicht erforderlich.<br />
◇ Der <strong>Java</strong>-Compiler und der <strong>Java</strong>-Interpreter f<strong>in</strong>den den Zugriffspfad zu den Bibliotheks-Dateien automatisch.<br />
Dieser muss daher nicht <strong>in</strong> die CLASSPATH-Variable aufgenommen werden (ab JDK 1.2).
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 261 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Datentypen <strong>in</strong> <strong>Java</strong> (1)<br />
◇ <strong>Java</strong> ist e<strong>in</strong>e streng typisierte Sprache.<br />
Das bedeutet, dass jede Variable und jeder Ausdruck e<strong>in</strong>en Typ hat, der zur Compilezeit bekannt se<strong>in</strong> muß.<br />
◇ In <strong>Java</strong> muß jede Variable immer e<strong>in</strong>en def<strong>in</strong>ierten Wert haben.<br />
Membervariable werden automatisch mit e<strong>in</strong>em Default-Wert <strong>in</strong>itialisiert, sofern ihnen nicht explizit e<strong>in</strong> Wert zuge-<br />
wiesen wird.<br />
Bei lokalen Variablen verh<strong>in</strong>dert der Compiler, dass sie ohne explizite Initialisierung bzw Wertzuweisung verwendet<br />
werden (Def<strong>in</strong>ite Assignment).<br />
◇ In <strong>Java</strong> gibt es zwei Kategorien von Datentypen :<br />
▻ e<strong>in</strong>fache (primitive) Datentypen (primitive types)<br />
▻ Referenz-Typen (reference types)<br />
• E<strong>in</strong>fache Datentypen<br />
◇ Variable e<strong>in</strong>es e<strong>in</strong>fachen Datentyps enthalten e<strong>in</strong>en Wert ihres jeweiligen Typs.<br />
◇ <strong>Java</strong> kennt acht e<strong>in</strong>fache Datentypen<br />
◇ Für jeden Datentyp ist der Wertebereich und damit die Größe des belegten Speicherplatzes e<strong>in</strong>deutig – unabhängig<br />
von der jeweiligen Plattform – festgelegt.<br />
◇ Zu jedem primitiven Datentyp ist <strong>in</strong> der Standard-Bibliothek e<strong>in</strong>e Wrapper-Klasse def<strong>in</strong>iert (Package java.lang).<br />
Dies ermöglicht die Anwendung objektorientierter Pr<strong>in</strong>zipien und Möglichkeiten auch auf die e<strong>in</strong>fachen Datentypen.<br />
◇ Überblick :<br />
Typname Größe Art des Typs Wertebereich Default-Wert Wrapper-<br />
Klasse<br />
byte 1 Byte vorzeichenbeh. ganze Zahl -128 ... +127 0 Byte<br />
short 2 Bytes vorzeichenbeh. ganze Zahl -2 15 ... +2 15 -1 0 Short<br />
<strong>in</strong>t 4 Bytes vorzeichenbeh. ganze Zahl -2 31 ... +2 31 -1 0 Integer<br />
long 8 Bytes vorzeichenbeh. ganze Zahl -2 63 ... +2 63 -1 0 Long<br />
char 2 Bytes Unicode-Zeichen alle Unicode-Zeichen '\u0000' Character<br />
float 4 Bytes Gleitpunktzahl (reelle Zahl) +/-3.4028...*10 38 0.0 Float<br />
double 8 Bytes Gleitpunktzahl (reelle Zahl) +/-1.7976...*10 308 0.0 Double<br />
boolean 1 Bit *) logischer Wert false, true false Boolean<br />
*) Die belegte Speichergröße ergibt sich durch die kle<strong>in</strong>ste adressierbare Speichere<strong>in</strong>heit (meist 1 Byte)<br />
◇ Der Datentyp float entspricht dem 32-Bit-IEEE-Format (s<strong>in</strong>gle precision, ANSI/IEEE Standard 754-1985)<br />
Der Datentyp double entspricht dem 64-Bit-IEEE-Format (double precision, ANSI/IEEE Standard 754-1985)<br />
◇ Der Datentyp char zählt (zusammen mit byte, short, <strong>in</strong>t und long) zu den ganzzahligen Datentypen.<br />
◇ Die ganzzahligen Datentypen bilden zusammen mit den Gleitpunkttypen (float und double) die numerischen<br />
Typen.<br />
◇ Der logische Datentyp boolean muß überall dort verwendet werden, wo e<strong>in</strong> logischer Operand erforderlich ist<br />
(logische Operatoren, Steuerausdrücke <strong>in</strong> den Steueranweisungen, erster Ausdruck im bed<strong>in</strong>gten Auswerte-Operator).<br />
E<strong>in</strong> Ersatz durch ganzzahlige Typen (Werte 0 und !=0) ist nicht zulässig.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 262 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
Datentypen <strong>in</strong> <strong>Java</strong> (2)<br />
• Darstellung der Werte der e<strong>in</strong>fachen Datentypen (Konstante, literals)<br />
◇ Die Wertedarstellung entspricht im wesentlichen der von C/C++<br />
◇ Datentypen byte, short, <strong>in</strong>t und long (ganzzahlige Datentypen ohne char)<br />
▻ Darstellung als Dezimalzahl : Ziffernfolge aus 0 bis 9, Beg<strong>in</strong>n nicht mit 0<br />
▻ Darstellung als Oktalzahl : Beg<strong>in</strong>n mit 0 (nur Ziffern 0 bis 7)<br />
▻ Darstellung als Sedezimalzahl : Beg<strong>in</strong>n mit 0x oder 0X (Ziffern 0 bis 9, a bis f, A bis F)<br />
▻ Ziffernfolgen s<strong>in</strong>d grundsätzlich (ohne Suffix) vom Typ <strong>in</strong>t.<br />
Allerd<strong>in</strong>gs muss der durch die Ziffernfolge dargestellte Wert <strong>in</strong>nerhalb des für <strong>in</strong>t zulässigen Bereichs liegen.<br />
▻ Ziffernfolgen mit dem Suffix l oder L s<strong>in</strong>d vom Typ long<br />
▻ Jede Ziffernfolge, die e<strong>in</strong>en ganzzahligen Wert darstellt, kann mit dem Vorzeichen – oder + versehen werden.<br />
◇ Datentypen float und double<br />
▻ Exponential- oder Dezimalbruchdarstellung<br />
▻ ohne Suffix oder mit Suffix d oder D : Datentyp double<br />
▻ mit Suffix f oder F : Datentyp float<br />
▻ Zusätzlich kann e<strong>in</strong>e Gleitpunktzahl mit dem Vorzeichen – oder + versehen werden.<br />
◇ Für alle numerischen Datentypen s<strong>in</strong>d <strong>in</strong> den entsprechenden Wrapper-Klassen (Package java.lang) die<br />
folgenden symbolischen Konstanten (als static public) def<strong>in</strong>iert :<br />
MAX_VALUE größter darstellbarer positiver Wert<br />
MIN_VALUE kle<strong>in</strong>ster darstellbarer positiver Wert<br />
Für die Datentypen float und double s<strong>in</strong>d <strong>in</strong> den Klassen Float und Double zusätzlich def<strong>in</strong>iert :<br />
NaN Not-a-Number (Repräsentation e<strong>in</strong>es ungültigen Werts, z.B. 0/0)<br />
NEGATIVE_INFINITY negativ unendlich<br />
POSITIVE_INFINITY positiv unendlich<br />
Verwendung dieser Konstanten immer nur zusammen mit dem jeweiligen Klassennamen (voll-qualifizierter Name) :<br />
z.B. : double dv = Double.MIN_VALUE;<br />
◇ Datentyp char<br />
▻ Darstellung e<strong>in</strong>es E<strong>in</strong>zelzeichens <strong>in</strong> e<strong>in</strong>fachen Hochkommata (s<strong>in</strong>gle quotes), z.B.: 'A', 'Π', ':'<br />
▻ Darstellung durch e<strong>in</strong>e C-kompatible Escape-Sequenz <strong>in</strong> e<strong>in</strong>fachen Hochkommata:<br />
'\b' Backspace (BS)<br />
'\t' Horizontaler Tabulator (Horizontal Tab, HT)<br />
'\n' Zeilenwechsel (Newl<strong>in</strong>e, L<strong>in</strong>efeed, LF)<br />
'\r' Carriage Return (CR)<br />
'\f' Seitenwechsel (Form Feed, FF)<br />
'\'' Ersatzdarstellung für e<strong>in</strong>faches Hochkomma (s<strong>in</strong>gle quote)<br />
'\"' Ersatzdarstellung für doppeltes Hochkomma (double quote)<br />
'\\' Ersatzdarstellung für Fluchtsysmbol \<br />
'\ooo' Oktal-Escape-Sequenz, 1 bis 3 Oktalziffern, maximaler Wert : 0377<br />
Anmerkung : Die C-Escape-Sequenzen '\v', '\a', '\?' und '\xhhh' s<strong>in</strong>d <strong>in</strong> <strong>Java</strong> nicht implementiert.<br />
▻ Darstellung durch e<strong>in</strong>e Unicode-Escape-Sequenz <strong>in</strong> e<strong>in</strong>fachen Hochkommata : '\uhhhh' (h Sedezimalziffer),<br />
z.B. : '\u0041' (== 'A'), '\u00dc' (== 'Ü'), '\uffff'
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 263 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Typkonvertierungen bei e<strong>in</strong>fachen Datentypen<br />
Datentypen <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Typkonvertierungen (Casts) zwischen allen ganzzahligen Typen (e<strong>in</strong>schließlich char) und den Gleitpunkt-<br />
Typen s<strong>in</strong>d grundsätzlich zulässig.<br />
◇ Implizite Typkonvertierungen bei typgemischten zweistelligen arithmetischen Operationen vor Ausführung der<br />
Operation (numeric promotion) :<br />
▻ Nur ganzzahlige Operanden (Integer-Operation), ke<strong>in</strong> Operand vom Typ long :<br />
Alle Nicht–<strong>in</strong>t-Operanden werden <strong>in</strong> den Typ <strong>in</strong>t umgewandelt.<br />
Die Operation wird als <strong>in</strong>t-Operation ausgeführt und liefert e<strong>in</strong> <strong>in</strong>t-Ergebnis<br />
▻ Nur ganzzahlige Operanden (Integer-Operation), e<strong>in</strong> Operand vom Typ long :<br />
Der andere Operand wird <strong>in</strong> den Typ long umgewandelt.<br />
Die Operation wird als long-Operation ausgeführt und liefert e<strong>in</strong> long-Ergebnis<br />
▻ E<strong>in</strong> Operand ist vom Typ double.<br />
Der andere Operand wird <strong>in</strong> den Typ double umgewandelt.<br />
Die Operation wird als double-Operation ausgeführt und liefert e<strong>in</strong> double-Ergebnis<br />
▻ E<strong>in</strong> Operand ist vom Typ float und der andere nicht vom Typ double.<br />
Der andere Operand wird <strong>in</strong> den Typ float umgewandelt.<br />
Die Operation wird als float-Operation ausgeführt und liefert e<strong>in</strong> float-Ergebnis<br />
◇ Implizite Typkonvertierungen zwischen numerischen Typen bei Wertzuweisungen (und Initialisierungen) :<br />
Nur zulässig, wenn sichergestellt ist, dass durch die Typkonvertierung ke<strong>in</strong>e Information verloren gehen kann :<br />
▻ Ganzzahl-Werte an Ganzzahl-Variable e<strong>in</strong>es größeren Typs.<br />
▻ Ganzzahl-Werte an Gleitpunkt-Variable<br />
▻ <strong>in</strong>t-Konstante an byte-, short- oder char-Variable, wenn die <strong>in</strong>t-Konstante sich auch als Wert des<br />
kle<strong>in</strong>eren Datentyps darstellen lässt.<br />
◇ Alle anderen Umwandlungen zwischen numerischen Typen, wenn also Information verloren gehen könnte, s<strong>in</strong>d<br />
nur explizit möglich (Cast-Operator !).<br />
◇ Zwischen dem Typ boolean und den numerischen Datentypen s<strong>in</strong>d ke<strong>in</strong>erlei Typkonvertierungen (auch nicht<br />
explizit) zulässig.<br />
◇ Werte e<strong>in</strong>es numerischen Datentyps lassen sich mit e<strong>in</strong>em Str<strong>in</strong>g-Operanden (Bibliotheks-Klasse Str<strong>in</strong>g)<br />
mittels des Konkatenations-Operators (+) vernüpfen. In e<strong>in</strong>em derartigen Fall wird der numerische Wert <strong>in</strong> se<strong>in</strong>e<br />
dezimale Text-Darstellung umgewandelt und mit dem Str<strong>in</strong>g-Operanden zu e<strong>in</strong>em neuen Str<strong>in</strong>g zusammen-<br />
gefasst.<br />
Beispiel : double dv = 74.25;<br />
System.out.pr<strong>in</strong>tln("Wert von dv : " + dv);<br />
Ausgabe : Wert von dv : 74.25<br />
◇ Analog lassen sich Werte des Typs boolean mit e<strong>in</strong>em Str<strong>in</strong>g-Operanden mittels des Konkatenations-<br />
Operators (+) verknüpfen. In e<strong>in</strong>em derartigen Fall wird der logische Wert <strong>in</strong> se<strong>in</strong>e Textdarstellung (entweder<br />
"true" oder "false") umgewandelt und mit dem Str<strong>in</strong>g-Operanden zu e<strong>in</strong>em neuen Str<strong>in</strong>g zusammen-<br />
gefasst.
HOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 264 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Referenz-Typen<br />
Datentypen <strong>in</strong> <strong>Java</strong> (4)<br />
◇ Sie referieren Objekte, d.h. Instanzen e<strong>in</strong>er Klasse.<br />
Objekte können <strong>in</strong> <strong>Java</strong> nicht direkt als Werte verwendet werden (z.B. als Funktions-Parameter), sondern nur über<br />
e<strong>in</strong>e Referenz.<br />
◇ Variable e<strong>in</strong>es Referenz-Typs (Referenz-Variable) werden i.a. als "Objekt-Variable" betrachtet.<br />
Tatsächlich s<strong>in</strong>d es aber Po<strong>in</strong>ter-Variable, die auf e<strong>in</strong> Objekt verweisen. Sie belegen nur den Speicherplatz zur Auf-<br />
nahme e<strong>in</strong>er Objekt-Adresse. Ihr Wert ist also e<strong>in</strong>e Speicheradresse.<br />
Bei ihrer Verwendung werden sie automatisch dereferenziert. (Anwendung des Punkt- (.) Operators zum Kompo-<br />
nentenzugriff).<br />
◇ E<strong>in</strong>e Referenz-Variable kann immer nur auf Objekte e<strong>in</strong>es bestimmten Typs bzw bestimmter Typen (Polymorphie !)<br />
zeigen.<br />
Formal werden drei Arten von Referenz-Variablen unterschieden :<br />
▻ Klassen-Typen (sie verweisen auf Objekte der entsprechenden Klasse oder auf Objekte davon abgeleiteter Klassen)<br />
▻ Interface-Typen (sie verweisen auf Objekte, die das jeweilige Interface implementieren)<br />
▻ Array-Typen (sie verweisen auf Arrays, Arrays s<strong>in</strong>d <strong>in</strong> <strong>Java</strong> ebenfalls – spezielle – Objekte)<br />
◇ Objekte werden grundsätzlich nur namenlos dynamisch auf dem Heap alloziert.<br />
Hierzu dient e<strong>in</strong> new-Ausdruck (new-Operator mit nachgestellten Konstruktor-Aufruf).<br />
Konstruktoren s<strong>in</strong>d spezielle klassenspezifische Funktionen, die zur Erzeugung e<strong>in</strong>es Objekts benötigt werden.<br />
Sie tragen i.a. den Namen der Klasse des zu erzeugenden Objekts (Ausnahme s. Arrays).<br />
Konstruktoren können Parameter besitzen.<br />
Der new-Ausdruck liefert die Adresse des erzeugten Objekts zurück, die dann e<strong>in</strong>er "Objekt-Variablen" als Wert<br />
zugewiesen werden kann.<br />
Beispiel : Str<strong>in</strong>g sv = new Str<strong>in</strong>g("Hallo !");<br />
◇ Die für Referenz-Variable def<strong>in</strong>ierten Vergleichs-Operatoren == und != beziehen sich auf die Referenzen<br />
(Adressen) und nicht auf die referierten Objekte.<br />
Gleiche Referenzen bedeuten natürlich auch Gleichheit der referierten Objekte.<br />
Ungleiche Referenzen bedeuten aber nicht, dass auch die referierten Objekte ungleich se<strong>in</strong> müssen.<br />
◇ Als spezielle Referenz-Konstante ist der Wert null def<strong>in</strong>iert.<br />
E<strong>in</strong>e Referenz-Variable mit diesem Wert zeigt auf nichts (also auf ke<strong>in</strong> Objekt).<br />
E<strong>in</strong>er lokalen Referenz-Variablen, die auf nichts zeigen soll, muss dieser Wert explizit zugewiesen werden.<br />
Beispiel : Str<strong>in</strong>g[] sa = null;<br />
// ...<br />
sa = new Str<strong>in</strong>g[10];<br />
Für Referenz-Variable, die Member-Variable s<strong>in</strong>d, ist null der ohne explizite Initialisierung zugewiesene Default-<br />
Wert.<br />
◇ Da <strong>Java</strong> über e<strong>in</strong>e im H<strong>in</strong>tergrund laufende automatische Garbage Collection verfügt, ist es weder notwendig noch i.a.<br />
s<strong>in</strong>nvoll und tatsächlich auch nicht möglich, dynamisch allozierten Speicher explizit freizugeben.<br />
In <strong>Java</strong> existiert daher ke<strong>in</strong> Speicherfreigabe-Operator (wie z.B. delete <strong>in</strong> C++).<br />
◇ Mit dem auf Referenz-Variable anwendbaren Operator <strong>in</strong>stanceof lässt sich überprüfen, ob das referierte<br />
Objekt von e<strong>in</strong>em bestimmten Typ ist.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 265 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Datentypen <strong>in</strong> <strong>Java</strong> (5)<br />
• Anmerkungen zu den Wrapper-Klassen für die e<strong>in</strong>fachen Datentypen<br />
◇ Die Wrapper-Klassen für die e<strong>in</strong>fachen Datentypen byte, short, <strong>in</strong>t, long, float und double<br />
s<strong>in</strong>d von der abstrakten Basisklasse Number abgeleitet :<br />
◇ Die Klasse Number deklariert die folgenden Methoden :<br />
▻<br />
▻<br />
▻<br />
▻<br />
▻<br />
▻<br />
Rückgabe des gespeicherten (gekapselten) Wertes typgewandelt als byte-Wert<br />
Rückgabe des gespeicherten (gekapselten) Wertes typgewandelt als short-Wert<br />
Rückgabe des gespeicherten (gekapselten) Wertes typgewandelt als <strong>in</strong>t-Wert<br />
Rückgabe des gespeicherten (gekapselten) Wertes typgewandelt als long-Wert<br />
Rückgabe des gespeicherten (gekapselten) Wertes typgewandelt als float-Wert<br />
Rückgabe des gespeicherten (gekapselten) Wertes typgewandelt als double-Wert<br />
Diese Methoden müssen von allen abgeleiteten Klassen jeweils implementiert werden ("Getter"-Methoden).<br />
◇ Analog def<strong>in</strong>iert die Wrapper-Klasse Character für den Datentyp char u.a. die folgenden Methode :<br />
▻<br />
Rückgabe des gespeicherten (gekapselten) char-Wertes<br />
◇ Analog def<strong>in</strong>iert die Wrapper-Klasse Boolean für den Datentyp boolean u.a. die folgenden Methode :<br />
▻<br />
Number<br />
Byte Short Integer Long Float Double<br />
public byte byteValue()<br />
public short shortValue()<br />
public abstract <strong>in</strong>t <strong>in</strong>tValue()<br />
public abstract long longValue()<br />
public abstract float floatValue()<br />
public abstract double doubleValue()<br />
public char charValue()<br />
public boolean booleanValue()<br />
Rückgabe des gespeicherten (gekapselten) boolean-Wertes
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 266 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Umwandlungen zwischen e<strong>in</strong>fachen <strong>Java</strong>-Datentypen und ihren Wrapper-Klassen<br />
• Verwendung von Werten e<strong>in</strong>facher Datentypen wie Objekte<br />
◇ Werte e<strong>in</strong>facher Datentypen und Objekte werden unterschiedlich dargestellt und referiert.<br />
Dadurch lassen sich Werte e<strong>in</strong>facher Datentypen nicht direkt <strong>in</strong> Situationen, <strong>in</strong> denen Objekte benötigt werden,<br />
verwenden (z.B. als Argument <strong>in</strong> vielen Methoden, aktueller Typ bei generischen Datentypen)<br />
◇ Um e<strong>in</strong>e derartiger Verwendung trotzdem zu ermöglichen, existieren Wrapper-Klassen für alle e<strong>in</strong>fachen Datentypen.<br />
E<strong>in</strong> Objekt e<strong>in</strong>er Wrapper-Klasse kapselt e<strong>in</strong>en Wert des korrespondierenden e<strong>in</strong>fachen Datentyps. Dieser Wert wird<br />
bei der Objekterzeugung festgelegt (Konstruktor-Parameter) und kann später nicht mehr geändert werden.<br />
◇ Zwischen Werten e<strong>in</strong>facher Datentypen ("primitive Werte") und den entsprechenden Objekten der jeweiligen Wrapper-<br />
Klasse s<strong>in</strong>d also Umwandlungen erforderlich.<br />
• Explizite Umwandlung<br />
◇ Wert Objekt : Mit dem Konstruktor der korrespondierenden Wrapper-Klasse.<br />
Beispiel 1 : <strong>in</strong>t iVal1 = 12;<br />
Integer iObj;<br />
iObj = new Integer(iVal1); // Erzeugung e<strong>in</strong>es neuen Integer-Objekts<br />
Beispiel 2 : Double dObj = new Double(0.75); // Erzeugung e<strong>in</strong>es neuen Double-Objekts<br />
◇ Objekt Wert : Mit e<strong>in</strong>er "Getter"-Methode der Wrapper-Klasse, z.B. <strong>in</strong>t <strong>in</strong>tValue() der Klasse Integer<br />
Beispiel 1 : <strong>in</strong>t iVal2 = iObj.<strong>in</strong>tValue(); // De-Wrapp<strong>in</strong>g<br />
Beispiel 2 : double dVal = dObj.doubleValue(); // De-Wrapp<strong>in</strong>g<br />
◇ Bis e<strong>in</strong>schliesslich dem JDK 1.4 mussten derartige Umwandlungen immer explizit codiert werden.<br />
• Implizite Umwandlung (Autobox<strong>in</strong>g/-unbox<strong>in</strong>g)<br />
◇ Mit dem JDK 5.0 e<strong>in</strong>geführt.<br />
◇ Obige Umwandlungen müssen nicht explizit codiert werden, sie werden automatisch vom Compiler erzeugt.<br />
Werte e<strong>in</strong>facher Datentypen und Wrapper-Objekte können völlig kompatibel zue<strong>in</strong>ander verwendet werden<br />
◇ Wert Objekt (Autobox<strong>in</strong>g) :<br />
Beispiel 1 : <strong>in</strong>t iVal1 = 12;<br />
Integer iObj;<br />
iObj = iVal1; // implizite Erzeugung e<strong>in</strong>es neuen Integer-Objekts<br />
Beispiel 2 : Double dObj = 0.75; // implizite Erzeugung e<strong>in</strong>es neuen Double-Objekts<br />
◇ Objekt Wert (Autounbox<strong>in</strong>g) :<br />
Beispiel 1 : <strong>in</strong>t iVal2 = iObj; // implizites De-Wrapp<strong>in</strong>g<br />
Beispiel 2 : double dVal = dObj; // implizites De-Wrapp<strong>in</strong>g<br />
◇ Autobox<strong>in</strong>g/-unbox<strong>in</strong>g f<strong>in</strong>det überall statt, wo Werte e<strong>in</strong>facher Datentypen bzw Wrapper-Objekte benötigt werden.<br />
Damit können z.B. mit Wrapper-Objekten auch "direkt" arithmetische Operationen vorgenommen werden.<br />
Beispiele : Integer iObj1 = 10;<br />
Integer iObj2 = iObj1 + 5;<br />
++iObj1;<br />
◇ Autobox<strong>in</strong>g f<strong>in</strong>det allerd<strong>in</strong>gs nur dann statt, wenn ke<strong>in</strong>e andere implizit mögliche Typkonvertierung anwendbar ist.<br />
Derartige Situationen können z.B. bei überladenen Funktionen auftreten.<br />
Beispiel : void func(double dv);<br />
void func(Integer io);<br />
. . .<br />
func(5) führt zum Aufruf der ersten Methode (func(5.0)) (<strong>in</strong>t double)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 271 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Darstellung von Str<strong>in</strong>gs<br />
Str<strong>in</strong>gs <strong>in</strong> <strong>Java</strong> - Allgeme<strong>in</strong>es<br />
◇ Str<strong>in</strong>gs <strong>in</strong> <strong>Java</strong> bestehen aus Unicode-Zeichen.<br />
Wie <strong>in</strong> C++ besteht e<strong>in</strong>e Str<strong>in</strong>g-Konstante (str<strong>in</strong>g literal) aus e<strong>in</strong>er Folge von 0 oder mehr Zeichen, die <strong>in</strong> doppelte<br />
Hochkommata (double qoutes) e<strong>in</strong>geschlossen se<strong>in</strong> müssen.<br />
Die Zeichen können auch durch Escape-Sequenzen dargestellt werden.<br />
Beispiele : "\n\"Hallo\""<br />
"\u00ea\u0256"<br />
◇ Str<strong>in</strong>gs s<strong>in</strong>d <strong>in</strong> <strong>Java</strong> Objekte.<br />
Str<strong>in</strong>g-Konstante werden durch Objekte der Bibliotheks-Klasse Str<strong>in</strong>g dargestellt.<br />
Der Inhalt derartiger Objekte ist unveränderlich.<br />
Zur Darstellung von veränderlichen Str<strong>in</strong>gs dienen die Bibliotheks-Klassen Str<strong>in</strong>gBuffer (thread-sicher) und<br />
Str<strong>in</strong>gBuilder (ab JDK 5.0, nicht thread-sicher, aber schneller, da ke<strong>in</strong>e Synchronisation erforderlich).<br />
◇ E<strong>in</strong>e Str<strong>in</strong>g-Variable ist – wie alle Objekt-Variablen <strong>in</strong> <strong>Java</strong> – e<strong>in</strong>e Referenz-Variable. Sie enthält e<strong>in</strong>e Referenz auf e<strong>in</strong><br />
Str<strong>in</strong>g- (bzw Str<strong>in</strong>gBuffer- bzw Str<strong>in</strong>gBuilder-) Objekt.<br />
E<strong>in</strong>e Zuweisung e<strong>in</strong>es neuen Str<strong>in</strong>gs an e<strong>in</strong>e Str<strong>in</strong>g-Variable ("Variable vom Typ Str<strong>in</strong>g") bedeutet nicht, dass<br />
das referierte Str<strong>in</strong>g-Objekt geändert wird, sondern dass die Str<strong>in</strong>g-Variable e<strong>in</strong> anderes Str<strong>in</strong>g-Objekt<br />
referiert.<br />
Beispiel : Str<strong>in</strong>g str = "Hausboot";<br />
// ...<br />
str = "Segelyacht"; // str zeigt auf e<strong>in</strong> anderes Objekt !<br />
• Direkte Sprachunterstützung für Str<strong>in</strong>gs<br />
◇ In der Sprache <strong>Java</strong> selbst s<strong>in</strong>d e<strong>in</strong>ige Mechanismen zur Erzeugung und Verwendung von Str<strong>in</strong>gs implementiert,<br />
die im Zusammenhang mit der Klasse Str<strong>in</strong>g zur Anwendung kommen<br />
◇ Beim Auftritt e<strong>in</strong>er Str<strong>in</strong>g-Konstanten im Quelltext erzeugt der Compiler e<strong>in</strong> Str<strong>in</strong>g-Objekt, das mit der Str<strong>in</strong>g-<br />
Konstanten <strong>in</strong>itialisiert wird.<br />
Beispiele : System.out.pr<strong>in</strong>tln("Schoene Gruesse !");<br />
Der Compiler erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt mit dem Inhalt "Schoene Gruesse !" und übergibt<br />
e<strong>in</strong>e Referenz (Adresse) auf dieses Objekt der Methode pr<strong>in</strong>tln(...)<br />
Str<strong>in</strong>g s1 = "Das alte Europa";<br />
Der Compiler erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt mit dem Inhalt " Das alte Europa" und weist der<br />
Variablen s1 e<strong>in</strong>e Referenz (Adresse) auf dieses Objekt zu<br />
◇ Für Str<strong>in</strong>g-Objekte ist der Operator + überladen als Konkatenations-Operator.<br />
Er erzeugt e<strong>in</strong> neues Str<strong>in</strong>g-Objekt, das aus den beiden Operanden zusammengesetzt ist.<br />
Beispiel : s1 = s1 + " hatte Recht !";<br />
◇ Der + -Operator wirkt auch dann als Konkatenations-Operator, wenn nur e<strong>in</strong> Operand vom Typ Str<strong>in</strong>g ist.<br />
In e<strong>in</strong>em derartigen Fall wird der andere Operand implizit <strong>in</strong> e<strong>in</strong> Str<strong>in</strong>g-Objekt umgewandelt und mit dem<br />
Str<strong>in</strong>g-Operanden zu e<strong>in</strong>em neuen Str<strong>in</strong>g-Objekt konkateniert.<br />
Die implizite Konvertierung <strong>in</strong> e<strong>in</strong> Str<strong>in</strong>g-Objekt (str<strong>in</strong>g conversion) f<strong>in</strong>det für jeden e<strong>in</strong>fachen Typ und für<br />
jeden Referenz-Typ (Klasse !) statt. Ist die <strong>in</strong> e<strong>in</strong>er Objekt-Variablen gespeicherte Referenz gleich null, wird<br />
der Str<strong>in</strong>g "null" erzeugt.<br />
Beispiel : System.out.pr<strong>in</strong>tln("Heute ist : " + new java.util.Date());<br />
E<strong>in</strong> neu erzeugtes namenloses Date-Objekt (Package java.util) wird <strong>in</strong> e<strong>in</strong> Str<strong>in</strong>g-Objekt<br />
(das das Datum als Text enthält) umgewandelt und mit dem Str<strong>in</strong>g-Objekt "Heute ist : "<br />
zu e<strong>in</strong>em neuen Str<strong>in</strong>g-Objekt zusammengefasst. E<strong>in</strong>e Referenz auf dieses Objekt wird der Methode<br />
pr<strong>in</strong>tln(...) als Parameter übergeben.<br />
◇ E<strong>in</strong>e Str<strong>in</strong>g-Konkatenation kann auch mit dem += -Operator realisiert werden. Wenn hier der rechte Operand<br />
ke<strong>in</strong> Str<strong>in</strong>g-Objekt ist, wird er implizit <strong>in</strong> e<strong>in</strong> solches konvertiert.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 272 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es zur Klasse Str<strong>in</strong>g<br />
Die Klasse Str<strong>in</strong>g <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Standard-Klasse zur Darstellung von nicht veränderlichen Str<strong>in</strong>gs.<br />
◇ Bestandteil des Package java.lang<br />
◇ Von der Klasse Str<strong>in</strong>g können ke<strong>in</strong>e anderen Klassen abgeleitet werden (Die Klasse ist f<strong>in</strong>al)<br />
◇ Die Klasse Str<strong>in</strong>g implementiert das Interface CharSequence<br />
◇ Die Klasse Str<strong>in</strong>g enthält zahlreiche Methoden zur Verwendung von Str<strong>in</strong>gs, u.a.<br />
- zur expliziten Erzeugung von Str<strong>in</strong>g-Objekten (Konstruktoren),<br />
- zur Ermittlung der Str<strong>in</strong>glänge<br />
- zum lesenden Zugriff zu Str<strong>in</strong>g-Elementen,<br />
- zum Str<strong>in</strong>g-Vergleich<br />
- zum Suchen <strong>in</strong> Str<strong>in</strong>gs<br />
- zur Extraktion von Teilstr<strong>in</strong>gs,<br />
- zum Kopieren von Str<strong>in</strong>gs mit Umwandlung aller Buchstaben <strong>in</strong> Großbuchstaben bzw Kle<strong>in</strong>buchstaben.<br />
• Konstruktoren der Klasse Str<strong>in</strong>g (Auswahl)<br />
public Str<strong>in</strong>g() Erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, das den Leerstr<strong>in</strong>g enthält<br />
public Str<strong>in</strong>g(Str<strong>in</strong>g str) Erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, das e<strong>in</strong>e Kopie des Inhalts von<br />
str enthält (Copy-Konstruktor)<br />
public Str<strong>in</strong>g(char[] acs) Erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, das die Zeichenfolge aus<br />
acs enthält.<br />
Die Zeichen werden <strong>in</strong> das neu erzeugte Objekt kopiert.<br />
public Str<strong>in</strong>g(byte[] abs) Erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, das mit der Zeichenfolge, die<br />
durch Decodierung der byte-Werte von abs entsteht,<br />
<strong>in</strong>itialisiert ist.<br />
Die Decodierung erfolgt für den Default-Zeichensatz der<br />
Implementierung<br />
public Str<strong>in</strong>g(Str<strong>in</strong>gBuffer buf) Erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, das mit der <strong>in</strong> buf enthal-<br />
tenen Zeichenfolge <strong>in</strong>itialisiert ist.<br />
Die Zeichen werden <strong>in</strong> das neu erzeugte Objekt kopiert.<br />
public Str<strong>in</strong>g(Str<strong>in</strong>gBuilder bld) Erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, das mit der <strong>in</strong> bld enthal-<br />
tenen Zeichenfolge <strong>in</strong>itialisiert ist.<br />
Die Zeichen werden <strong>in</strong> das neu erzeugte Objekt kopiert.<br />
◇ H<strong>in</strong>weis : Die explizite Erzeugung e<strong>in</strong>es Str<strong>in</strong>g-Objekts bei Initialisierung mit e<strong>in</strong>er Str<strong>in</strong>g-Konstanten<br />
ist <strong>in</strong>effizient .<br />
Str<strong>in</strong>g str = new Str<strong>in</strong>g("Wer rastet, der rostet");<br />
Dies führt zunächst zur impliziten Erzeugung e<strong>in</strong>es Str<strong>in</strong>g-Objektes das mit der Str<strong>in</strong>g-Konstanten<br />
"Wer rastet, der rostet" <strong>in</strong>itialisiert ist.<br />
Anschliessend wird zur expliziten Erzeugung e<strong>in</strong>es weiteren Str<strong>in</strong>g-Objekts der Copy-Konstruktor<br />
aufgerufen, dem e<strong>in</strong>e Referenz auf das zuerst erzeugte Objekt übergeben wird.<br />
E<strong>in</strong>e Referenz auf das explizit erzeugte zweite Objekt wird dann der Str<strong>in</strong>g-Variablen str<br />
zugewiesen.<br />
Vorzuziehen ist daher die direkte "Initialisierung" e<strong>in</strong>er Str<strong>in</strong>g-Variablen mit e<strong>in</strong>er Str<strong>in</strong>g-<br />
Konstanten. In diesem Fall wird nur e<strong>in</strong> Str<strong>in</strong>g-Objekt – implizit – erzeugt<br />
Str<strong>in</strong>g str = "Wer rastet, der rostet";<br />
Entsprechendes gilt für die Wertzuweisung an Str<strong>in</strong>g-Variable.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 273 – 01 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Memberfunktionen Klasse Str<strong>in</strong>g (Auswahl)<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public <strong>in</strong>t length()<br />
Die Klasse Str<strong>in</strong>g <strong>in</strong> <strong>Java</strong> (2)<br />
▻ Gibt die Länge e<strong>in</strong>es Str<strong>in</strong>g-Objekts (= die Anzahl der enthaltenen Unicode-Zeichen) als Funktionswert<br />
zurück<br />
public char charAt(<strong>in</strong>t <strong>in</strong>dex)<br />
▻ Liefert das Zeichen mit dem Index <strong>in</strong>dex als Funktionswert zurück.<br />
▻ Der zulässige Indexbereich reicht von 0 (erstes Zeichen) bis length()-1 (letztes Zeichen).<br />
▻ Erzeugung e<strong>in</strong>er IndexOutOfBoundsException, wenn e<strong>in</strong> unzulässiger Index übergeben wird.<br />
public boolean conta<strong>in</strong>s(CharSequence s) // ab dem JDK 5.0 vorhanden<br />
▻ Überprüfung, ob die Zeichenfolge s (z.B. Inhalt e<strong>in</strong>es Str<strong>in</strong>g-Objekts) im aktuellen Objket enthalten ist<br />
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false<br />
public <strong>in</strong>t <strong>in</strong>dexOf(<strong>in</strong>t ch)<br />
▻ Rückgabe des Index des ersten Auftritts des – als <strong>in</strong>t-Wert übergebenen – Zeichens ch als Funktionswert.<br />
▻ Falls das Zeichen ch nicht enthalten ist, wird der Wert –1 zurückgegeben.<br />
▻ Beispiel : "hamburger".<strong>in</strong>dexOf('r') liefert 5<br />
public <strong>in</strong>t <strong>in</strong>dexOf(<strong>in</strong>t ch, <strong>in</strong>t from)<br />
▻ Funktionalität wie <strong>in</strong>t <strong>in</strong>dexOf(<strong>in</strong>t ch), allerd<strong>in</strong>gs beg<strong>in</strong>nt die Suche am Index from<br />
▻ Beispiel : "hamburger".<strong>in</strong>dexOf('r', 6) liefert 8<br />
public <strong>in</strong>t <strong>in</strong>dexOf(Str<strong>in</strong>g str)<br />
▻ Rückgabe des Index des ersten Auftritts des Teilstr<strong>in</strong>gs str.<br />
▻ Der zurückgegebene Funktionswert ist der Index des ersten Zeichens des gefundenen Teilstr<strong>in</strong>gs.<br />
▻ Falls der Teilstr<strong>in</strong>g str nicht enthalten ist, wird der Wert –1 zurückgegeben.<br />
public <strong>in</strong>t <strong>in</strong>dexOf(Str<strong>in</strong>g str, <strong>in</strong>t from)<br />
▻ Funktionalität wie <strong>in</strong>t <strong>in</strong>dexOf(Str<strong>in</strong>g str), allerd<strong>in</strong>gs beg<strong>in</strong>nt die Suche am Index from<br />
public <strong>in</strong>t lastIndexOf(<strong>in</strong>t ch)<br />
public <strong>in</strong>t lastIndexOf(<strong>in</strong>t ch, <strong>in</strong>t from)<br />
public <strong>in</strong>t lastIndexOf(Str<strong>in</strong>g str)<br />
public <strong>in</strong>t lastIndexOf(Str<strong>in</strong>g str, <strong>in</strong>t from)<br />
▻ Ähnlich wie die Funktionen <strong>in</strong>dexOf(...).<br />
▻ Nur Ermittlung des Index des letzten Auftritts des Zeichens ch bzw des Teilsstr<strong>in</strong>gs str.<br />
▻ Beispiel : "hamburger".lastIndexOf("r<strong>in</strong>dfleisch") liefert -1
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 273 – 02 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
Die Klasse Str<strong>in</strong>g <strong>in</strong> <strong>Java</strong> (3)<br />
• Memberfunktionen Klasse Str<strong>in</strong>g (Auswahl), Forts.<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public boolean equals(Object obj)<br />
▻ Überprüfung, ob das übergebene Objekt e<strong>in</strong> Str<strong>in</strong>g-Objekt ist und gleiche Länge und gleichen Inhalt wie<br />
das aktuelle Objekt hat.<br />
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false<br />
public <strong>in</strong>t compareTo(Str<strong>in</strong>g str)<br />
▻ Durchführung e<strong>in</strong>es lexikographischen Vergleichs zwischen dem aktuellen Str<strong>in</strong>g-Objekt und dem Str<strong>in</strong>g-<br />
Objekt str<br />
▻ Der Vergleich wird mit den Codewerten der e<strong>in</strong>zelnen Zeichen bzw der Str<strong>in</strong>glänge ausgeführt<br />
▻ Funktionswert : - 0, wenn beide Str<strong>in</strong>g-Objekte gleich s<strong>in</strong>d<br />
- 0, wenn das aktuelle Objekt "größer" als str ist<br />
▻ Beispiel : "haben".compareTo("hat") liefert –18<br />
public boolean startsWith(Str<strong>in</strong>g prefix)<br />
▻ Überprüfung, ob das aktuelle Objekt mit dem Str<strong>in</strong>g prefix beg<strong>in</strong>nt.<br />
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false<br />
public Str<strong>in</strong>g substr<strong>in</strong>g(<strong>in</strong>t beg, <strong>in</strong>t end)<br />
▻ Rückgabe des Teilstr<strong>in</strong>gs, der am Index beg beg<strong>in</strong>nt und am Index end-1 endet, als neues Str<strong>in</strong>g-Objekt<br />
(genauer : als Referenz auf e<strong>in</strong> neu erzeugtes Str<strong>in</strong>g-Objekt mit dem entsprechenden Inhalt des Teilstr<strong>in</strong>gs).<br />
▻ Erzeugung e<strong>in</strong>er IndexOutOfBoundsException, falls wenigstens e<strong>in</strong>er der übergebenen Indizees<br />
unzulässig ist oder beg>end ist.<br />
▻ Beispiel : "hamburger".substr<strong>in</strong>g(4,8) liefert "urge"<br />
public Str<strong>in</strong>g toUpperCase()<br />
▻ Rückgabe e<strong>in</strong>es neuen Str<strong>in</strong>g-Objekts, <strong>in</strong> dem alle Buchstaben <strong>in</strong> Großbuchstaben konvertiert s<strong>in</strong>d<br />
public Str<strong>in</strong>g replace(char alt, char neu)<br />
▻ Rückgabe e<strong>in</strong>es neuen Str<strong>in</strong>g-Objekts, das aus dem aktuellen Objekt durch Ersatz aller Auftritte des<br />
Zeichens alt durch das Zeichen neu und der Übernahme alle übrigen Zeichen entsteht.<br />
▻ Ist das Zeichen alt überhaupt nicht im aktuellen Objekt enthalten, wird ke<strong>in</strong> neues Objekt erzeugt, sondern<br />
das aktuelle Objekt zurückgegeben.<br />
public Str<strong>in</strong>g trim()<br />
▻ Rückgabe e<strong>in</strong>er neu erzeugten Kopie des aktuellen Objekts, bei der alle führenden und endenden Blanks sowie<br />
ASCII-Steuerzeichen (Zeichencode '0u0020' besitzen, wird ke<strong>in</strong>e Kopie erzeugt, sondern das aktuelle Objekt zurückgegeben
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 274 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Die Klasse Str<strong>in</strong>g <strong>in</strong> <strong>Java</strong> (4)<br />
• Explizite Umwandlung <strong>in</strong> e<strong>in</strong>e Str<strong>in</strong>g-Darstellung<br />
◇ In der Klasse Str<strong>in</strong>g existiert e<strong>in</strong>e mehrfach überladene statische Memberfunktion zur Umwandlung von belie-<br />
bigen Werten der e<strong>in</strong>fachen Datentypen sowie von Objekten beliebiger Klassen <strong>in</strong> e<strong>in</strong>e Str<strong>in</strong>g-Darstellung :<br />
Beispiel für die Umwandlung von double-Werten :<br />
public static Str<strong>in</strong>g valueOf(double d)<br />
◇ Für jede Klasse ist <strong>in</strong> <strong>Java</strong> die folgende Memberfunktion def<strong>in</strong>iert, mit der e<strong>in</strong> Objekt der jeweiligen Klasse <strong>in</strong> e<strong>in</strong><br />
Str<strong>in</strong>g-Objekt (textuelle Repräsentation des Objekts !) umgewandelt wird :<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
• Demonstrationsbeispiel zur Klasse Str<strong>in</strong>g<br />
// Str<strong>in</strong>gDemo.java<br />
public class Str<strong>in</strong>gDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ System.out.pr<strong>in</strong>tln("Heute ist : " + new java.util.Date());<br />
Str<strong>in</strong>g str = "Aller Anfang";<br />
str = str + " ist";<br />
str += " schwer";<br />
System.out.pr<strong>in</strong>tln(str);<br />
<strong>in</strong>t len = str.length();<br />
System.out.pr<strong>in</strong>tln("Laenge des Str<strong>in</strong>gs : " + len);<br />
<strong>in</strong>t idx = 6;<br />
System.out.pr<strong>in</strong>tln(idx+1 + ". Zeichen : " + str.charAt(idx));<br />
System.out.pr<strong>in</strong>tln("Index von \"ist\" : " + str.<strong>in</strong>dexOf("ist"));<br />
char ch = 'r';<br />
System.out.pr<strong>in</strong>tln("letzter Index von " + ch + " : " + str.lastIndexOf(ch));<br />
<strong>in</strong>t ie = idx+6;<br />
System.out.pr<strong>in</strong>t("Teilstr<strong>in</strong>g (" + idx + ',' + ie + ") : ");<br />
System.out.pr<strong>in</strong>tln(str.substr<strong>in</strong>g(idx, ie));<br />
System.out.pr<strong>in</strong>tln(str.toUpperCase());<br />
if (str.equals("Aller Anfang ist schwer"))<br />
System.out.pr<strong>in</strong>tln("Str<strong>in</strong>gs s<strong>in</strong>d gleich !");<br />
else<br />
System.out.pr<strong>in</strong>tln("Str<strong>in</strong>gs s<strong>in</strong>d ungleich !");<br />
<strong>in</strong>t diff = "haben".compareTo("hat");<br />
System.out.pr<strong>in</strong>tln("Vergleich von \"haben\" und \"hat\" liefert : "+diff);<br />
}<br />
}<br />
Ausgabe des Programms<br />
Heute ist : Thu Sep 04 10:38:41 CEST 2003<br />
Aller Anfang ist schwer<br />
Laenge des Str<strong>in</strong>gs : 23<br />
7. Zeichen : A<br />
Index von "ist" : 13<br />
letzter Index von r : 22<br />
Teilstr<strong>in</strong>g (6,12) : Anfang<br />
ALLER ANFANG IST SCHWER<br />
Str<strong>in</strong>gs s<strong>in</strong>d gleich !<br />
Vergleich von "haben" und "hat" liefert : -18
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 275 – 00 – TH – 07<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es zur Klasse Str<strong>in</strong>gBuffer<br />
Die Klasse Str<strong>in</strong>gBuffer <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Thread-sichere Klasse zur Darstellung veränderlicher Str<strong>in</strong>gs.<br />
Die <strong>in</strong> Objekten dieser Klasse abgelegte Zeichenfolge kann sowohl bezüglich des Inhalts als auch h<strong>in</strong>sichtlich der<br />
Länge modifiziert werden.<br />
◇ Bestandteil des Package java.lang<br />
◇ Die Größe des <strong>in</strong> e<strong>in</strong>em Str<strong>in</strong>gBuffer-Objekt vorhandenen Zeichen-Puffers wird als Kapazität bezeichnet.<br />
Die Länge des enthaltenen Str<strong>in</strong>gs kann kle<strong>in</strong>er als die Kapazität se<strong>in</strong>.<br />
Übersteigt bei e<strong>in</strong>er Str<strong>in</strong>g-Verlängerung die neue Länge die Kapazität, wird automatisch e<strong>in</strong> neuer Puffer ausreichender<br />
Kapazität allokiert. Die Kapaziät kann auch explizit vergrößert (nicht jedoch verkle<strong>in</strong>ert) werden.<br />
◇ Viele der Memberfunktionen der Klasse Str<strong>in</strong>g existieren auch für die Klasse Str<strong>in</strong>gBuffer.<br />
Zusätzlich s<strong>in</strong>d zahlreiche Memberfunktionen zur Str<strong>in</strong>g-Manipulation implementiert.<br />
◇ Die Klassen Str<strong>in</strong>g und Str<strong>in</strong>gBuffer s<strong>in</strong>d nicht vone<strong>in</strong>ander abgeleitet.<br />
Beide implementieren aber das Interface CharSequence.<br />
Die Klasse Str<strong>in</strong>gBuffer implementiert darüberh<strong>in</strong>aus das Interface Appendable.<br />
◇ Die Klasse Str<strong>in</strong>gBuffer ist nicht ableitbar (Die Klasse ist f<strong>in</strong>al).<br />
• Konstruktoren der Klasse Str<strong>in</strong>gBuffer<br />
• Memberfunktionen zur Ermittlung und Änderung der Länge und Kapazität<br />
◇<br />
◇<br />
◇<br />
◇<br />
public Str<strong>in</strong>gBuffer() Erzeugt e<strong>in</strong> leeres Str<strong>in</strong>gBuffer-Objekt mit Kapazität von 16<br />
public Str<strong>in</strong>gBuffer(<strong>in</strong>t cap) Erzeugt e<strong>in</strong> leeres Str<strong>in</strong>gBuffer-Objekt, mit Kapazität = cap<br />
public Str<strong>in</strong>gBuffer(Str<strong>in</strong>g str) Erzeugt e<strong>in</strong> Str<strong>in</strong>gBuffer-Objekt, das mit dem Inhalt von str<br />
<strong>in</strong>itialisiert ist, mit Kapazität = 16 + str.length()<br />
public Str<strong>in</strong>gBuffer(CharSequence seq) Erzeugt e<strong>in</strong> Str<strong>in</strong>gBuffer-Objekt, das mit den <strong>in</strong> seq enthal-<br />
tenen Zeichen <strong>in</strong>itialisiert ist,<br />
(ab JDK 5.0) mit Kapazität = 16 + Anzahl Zeichen <strong>in</strong> seq<br />
public <strong>in</strong>t length()<br />
▻ Gibt die Länge des im Str<strong>in</strong>gBuffer-Objekt enthaltenen Str<strong>in</strong>gs als Funktionswert zurück<br />
public <strong>in</strong>t capacity()<br />
▻ Gibt die Kapazität des Str<strong>in</strong>gBuffer-Objekts als Funktionswert zurück<br />
public void setLength(<strong>in</strong>t neulen)<br />
▻ Setzen der Länge des im Str<strong>in</strong>gBuffer-Objekt enthaltenen Str<strong>in</strong>gs<br />
▻ Falls neulen < akt. Str<strong>in</strong>glänge ist, wird der Str<strong>in</strong>g entsprechend verkürzt (Kapazität bleibt gleich)<br />
▻ Falls neulen > akt. Str<strong>in</strong>glänge ist, wird der Str<strong>in</strong>g mit '\u0000'-Zeichen verlängert<br />
▻ Erzeugung e<strong>in</strong>er IndexOutOfBoundsException, wenn neulen= neucap ist (Kapazitätsverkle<strong>in</strong>erung nicht möglich)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 276 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
Die Klasse Str<strong>in</strong>gBuffer <strong>in</strong> <strong>Java</strong> (2)<br />
• Anmerkungen zu den Memberfunktionen zur Str<strong>in</strong>g-Modifikation<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public void setCharAt(<strong>in</strong>t idx, char ch)<br />
▻ Das Zeichen an der Position idx wird gleich dem Zeichen ch gesetzt.<br />
▻ Erzeugung e<strong>in</strong>er IndexOutOfBoundsException, wenn e<strong>in</strong> unzulässiger Index (idx=length()) übergeben wird.<br />
public Str<strong>in</strong>gBuffer replace(<strong>in</strong>t beg, <strong>in</strong>t end, Str<strong>in</strong>g str)<br />
▻ Der durch beg (erster Index) und end (letzter Index +1) festgelegte Teilstr<strong>in</strong>g wird durch str ersetzt.<br />
▻ Erzeugung e<strong>in</strong>er Str<strong>in</strong>gIndexOutOfBoundsException, wenn e<strong>in</strong> unzulässiger Index (beglength() oder beg>end) übergeben wird.<br />
▻ Funktionswert ist e<strong>in</strong>e Referenz auf das aktuelle Str<strong>in</strong>gBuffer-Objekt<br />
public Str<strong>in</strong>gBuffer deleteCharAt(<strong>in</strong>t idx)<br />
▻ Entfernen des Zeichens an der Position idx (Verkürzung der Str<strong>in</strong>glänge um 1)<br />
▻ Erzeugung e<strong>in</strong>er Str<strong>in</strong>gIndexOutOfBoundsException, wenn e<strong>in</strong>e unzulässige Position (idx=length()) übergeben wird.<br />
▻ Funktionswert ist e<strong>in</strong>e Referenz auf das aktuelle Str<strong>in</strong>gBuffer-Objekt<br />
public Str<strong>in</strong>gBuffer delete(<strong>in</strong>t beg, <strong>in</strong>t end)<br />
▻ Entfernen des durch beg (erster Index) und end (letzter Index +1) festgelegten Teilstr<strong>in</strong>gs<br />
▻ Erzeugung e<strong>in</strong>er Str<strong>in</strong>gIndexOutOfBoundsException, wenn e<strong>in</strong> unzulässiger Index (beglength() oder beg>end) übergeben wird.<br />
▻ Funktionswert ist e<strong>in</strong>e Referenz auf das aktuelle Str<strong>in</strong>gBuffer-Objekt<br />
public Str<strong>in</strong>gBuffer reverse()<br />
▻ Umkehrung der Zeichen-Reihenfolge des im Str<strong>in</strong>gBuffer-Objekt enthaltenen Str<strong>in</strong>gs<br />
▻ Funktionswert ist e<strong>in</strong>e Referenz auf das aktuelle Str<strong>in</strong>gBuffer-Objekt<br />
◇ Die meist verwendetsten Memberfunktionen zur Str<strong>in</strong>g-Modifikation s<strong>in</strong>d :<br />
public Str<strong>in</strong>gBuffer append(...)<br />
public Str<strong>in</strong>gBuffer <strong>in</strong>sert(<strong>in</strong>t pos, ...)<br />
▻ Beide Funktionen s<strong>in</strong>d für unterschiedliche Parametertypen vielfach überladen.<br />
▻ Sie wandeln den jeweiligen Parameter <strong>in</strong> se<strong>in</strong>e Str<strong>in</strong>g-Darstellung um und<br />
- hängen dann diesen Str<strong>in</strong>g an das aktuelle Objekt an ( append() ) bzw<br />
- fügen ihn an der angegebenen Stelle pos e<strong>in</strong> ( <strong>in</strong>sert() ).<br />
▻ Als Funktionswert geben diese Funktionen e<strong>in</strong>e Referenz auf das aktuelle Objekt zurück<br />
▻ Bei Übergabe e<strong>in</strong>er unzulässigen Position (pos=length()) erzeugen die <strong>in</strong>sert()-<br />
Funktionen e<strong>in</strong>e IndexOutOfBoundsException<br />
▻ Beispiel : Str<strong>in</strong>gBuffer strb = new Str<strong>in</strong>gBuffer("Ergebnis : ");<br />
<strong>in</strong>t i = 0x7c;<br />
strb.append(i); // Inhalt von strb : "Ergebnis : 124"
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 277 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
Die Klasse Str<strong>in</strong>gBuffer <strong>in</strong> <strong>Java</strong> (3)<br />
• Erzeugung e<strong>in</strong>es Str<strong>in</strong>g-Objekts aus e<strong>in</strong>em Str<strong>in</strong>gBuffer-Objekt<br />
◇ Mittels der Str<strong>in</strong>gBuffer-Memberfunktion :<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
▻ Sie erzeugt e<strong>in</strong> neues Str<strong>in</strong>g-Objekt, dass mit der aktuell im aktuellen Str<strong>in</strong>gBuffer-Objekt enthaltenen<br />
Zeichenfolge <strong>in</strong>itialisiert ist und gibt e<strong>in</strong>e Referenz auf dieses als Funktionswert zurück.<br />
▻ Dieses Str<strong>in</strong>g-Objekt ist die Str<strong>in</strong>g-Repräsentation des Str<strong>in</strong>gBuffer-Objekts<br />
▻ Beispiel : Str<strong>in</strong>gBuffer strb = new Str<strong>in</strong>gBuffer();<br />
// ... Manipulation von strb<br />
Str<strong>in</strong>g str1 = strb.toStr<strong>in</strong>g();<br />
◇ Mittels des Str<strong>in</strong>g-Konstruktors :<br />
public Str<strong>in</strong>g(Str<strong>in</strong>gBuffer buf)<br />
▻ Beispiel : // ...<br />
Str<strong>in</strong>g str2 = new Str<strong>in</strong>g(strb);<br />
◇ Mittels der statischen Str<strong>in</strong>g-Memberfunktion :<br />
public static Str<strong>in</strong>g valueOf(Object obj)<br />
▻ Dieser Funktion ist das Str<strong>in</strong>gBuffer-Objekt als Parameter zu übergeben.<br />
▻ Sie erzeugt e<strong>in</strong> neues Str<strong>in</strong>g-Objekt, dass mit der aktuell im übergebenen Str<strong>in</strong>gBuffer-Objekt enthaltenen<br />
Zeichenfolge <strong>in</strong>itialisiert ist und gibt e<strong>in</strong>e Referenz auf dieses als Funktionswert zurück.<br />
▻ Beispiel : // ...<br />
Str<strong>in</strong>g str3 = Str<strong>in</strong>g.valueOf(strb);<br />
• Verwendung der Klasse Str<strong>in</strong>gBuffer durch den Compiler<br />
◇ Der Compiler realisiert e<strong>in</strong>e mehrfache Str<strong>in</strong>g-Konkatenation unter Verwendung e<strong>in</strong>es temporären Str<strong>in</strong>gBuffer-<br />
Objekts.<br />
Beispiel : Str<strong>in</strong>g s1 = "Morgenstund";<br />
Str<strong>in</strong>g s2;<br />
s2 = '';<br />
Der Ausdruck s2 = '' wird vom Compiler umgesetzt <strong>in</strong> :<br />
s2 = new Str<strong>in</strong>gBuffer().append('').toStr<strong>in</strong>g()<br />
Hier wird nur e<strong>in</strong> temporär benötigtes Str<strong>in</strong>gBuffer-Objekt erzeugt. Da se<strong>in</strong> Inhalt veränderlich ist, können die<br />
zu konkatenierenden Str<strong>in</strong>gs bzw Str<strong>in</strong>grepräsentationen angehängt werden. E<strong>in</strong>e explizite Erzeugung von Str<strong>in</strong>g-<br />
Objekten für die Nicht-Str<strong>in</strong>g-Operanden ist nicht erforderlich.<br />
◇ Ohne das temporäre Str<strong>in</strong>gBuffer-Objekt müsste für jede Str<strong>in</strong>grepräsentation e<strong>in</strong>es Nicht-Str<strong>in</strong>g-Operanden<br />
e<strong>in</strong> neues Str<strong>in</strong>g-Objekt erzeugt werden. Ausserdem würde nach jedem Zwischenschritt (jeder ausgeführten<br />
Konkatenation) zusätzlich e<strong>in</strong> weiteres Str<strong>in</strong>g-Objekt erzeugt werden.<br />
Diese zusätzlichen Str<strong>in</strong>g-Objekte werden nach Abschluß der Gesamtoperation nicht mehr benötigt.<br />
unnötige Speicherallokationen (und danach wieder durchgeführte Speicherfreigaben).<br />
Im obigen Beispiel würden erzeugt werden :<br />
"
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 278 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es zur Klasse Str<strong>in</strong>gBuilder<br />
Die Klasse Str<strong>in</strong>gBuilder <strong>in</strong> <strong>Java</strong><br />
◇ Ab dem JDK 5.0 vorhandene alternative Klasse zur Darstellung veränderlicher Str<strong>in</strong>gs.<br />
Auch die <strong>in</strong> Objekten dieser Klasse abgelegte Zeichenfolge kann sowohl bezüglich des Inhalts als auch h<strong>in</strong>sicht-<br />
lich der Länge modifiziert werden.<br />
◇ Bestandteil des Package java.lang<br />
◇ Die Klasse Str<strong>in</strong>gBuilder stellt pr<strong>in</strong>zipiell die gleiche Funktionalität bei im wesentlichen gleichem Methoden-<br />
Interface wie die Klasse Str<strong>in</strong>gBuffer zur Verfügung.<br />
◇ Der wesentliche Unterschied zwischen den beiden Klassen besteht dar<strong>in</strong>, dass Str<strong>in</strong>gBuffer thread-sicher ist,<br />
während dies für Str<strong>in</strong>gBuilder nicht zutrifft.<br />
Andererseits arbeiten die Methoden der Klasse Str<strong>in</strong>gBuilder schneller, da <strong>in</strong> ihnen auf die für e<strong>in</strong>e Thread-<br />
Sicherheit notwendige Synchronisation verzichtet werden kann.<br />
Wenn sichergestellt ist, dass der veränderliche Str<strong>in</strong>g nur <strong>in</strong> e<strong>in</strong>em Thread verwendet werden wird, sollte der Klasse<br />
Str<strong>in</strong>gBuilder der Vorzug gegeben werden.<br />
◇ Die Klasse Str<strong>in</strong>gBuilder steht <strong>in</strong> ke<strong>in</strong>erlei Ableitungsbeziehungen zu den Klassen Str<strong>in</strong>gBuffer und<br />
Str<strong>in</strong>g.<br />
Allerd<strong>in</strong>gs implementiert sie ebenfalls die Interfaces CharSequence und Appendable.<br />
◇ Die Klasse Str<strong>in</strong>gBuilder ist ebenfalls f<strong>in</strong>al und damit nicht ableitbar.<br />
• Konstruktoren der Klasse Str<strong>in</strong>gBuilder (analog zur Klasse Str<strong>in</strong>gBuffer)<br />
public Str<strong>in</strong>gBuilder() Erzeugt e<strong>in</strong> leeres Str<strong>in</strong>gBuilder-Objekt mit Kapazität von 16<br />
public Str<strong>in</strong>gBuilder(<strong>in</strong>t cap) Erzeugt e<strong>in</strong> leeres Str<strong>in</strong>gBuilder-Objekt, mit Kapazität = cap<br />
public Str<strong>in</strong>gBuilder(Str<strong>in</strong>g str) Erzeugt e<strong>in</strong> Str<strong>in</strong>gBuilder-Objekt, das mit dem Inhalt von str<br />
<strong>in</strong>itialisiert ist, mit Kapazität = 16 + str.length()<br />
public Str<strong>in</strong>gBuilder(CharSequence seq) Erzeugt e<strong>in</strong> Str<strong>in</strong>gBuilder-Objekt, das mit den <strong>in</strong> seq enthal-<br />
tenen Zeichen <strong>in</strong>itialisiert ist,<br />
mit Kapazität = 16 + Anzahl Zeichen <strong>in</strong> seq<br />
• Memberfunktionen der Klasse Str<strong>in</strong>gBuilder<br />
Die Memberfunktionen entsprechen den Memberfunktionen der Klasse Str<strong>in</strong>gBuffer<br />
• Erzeugung e<strong>in</strong>es Str<strong>in</strong>g-Objekts aus e<strong>in</strong>em Str<strong>in</strong>gBuilder-Objekt<br />
Die Möglichkeiten entsprechen denen der Klasse Str<strong>in</strong>gBuffer<br />
◇ Mittels der Str<strong>in</strong>gBuilder-Memberfunktion :<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
◇ Mittels des Str<strong>in</strong>g-Konstruktors :<br />
public Str<strong>in</strong>g(Str<strong>in</strong>gBuilder bld)<br />
◇ Mittels der statischen Str<strong>in</strong>g-Memberfunktion :<br />
public static Str<strong>in</strong>g valueOf(Object obj)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 281 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>e Eigenschaften<br />
Arrays <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Arrays s<strong>in</strong>d e<strong>in</strong>e Zusammenfassung von Variablen, die <strong>in</strong> e<strong>in</strong>er Reihenfolge geordnet s<strong>in</strong>d und als Elemente<br />
bezeichnet werden.´<br />
Alle Array-Elemente müssen vom gleichen Typ se<strong>in</strong>.<br />
◇ Als Element-Typ ist jeder beliebige Typ (e<strong>in</strong>facher Datentyp oder Referenz-Typ) zulässig.<br />
◇ E<strong>in</strong> Array-Element wird über e<strong>in</strong>en Index, der vom Typ <strong>in</strong>t se<strong>in</strong> muß, ausgewählt.<br />
Der Index des ersten Elements hat den Wert 0.<br />
◇ Arrays s<strong>in</strong>d <strong>in</strong> <strong>Java</strong> Objekte.<br />
Array-Typen s<strong>in</strong>d – namenlose – Klassen.<br />
Von e<strong>in</strong>er Array-Klasse können ke<strong>in</strong>e weiteren Klassen abgeleitet werden.<br />
◇ Array-Variable s<strong>in</strong>d Referenz-Variable. Sie verweisen auf Array-Objekte.<br />
Die Def<strong>in</strong>ition e<strong>in</strong>er Array-Variablen erzeugt noch ke<strong>in</strong> Array-Objekt, d.h. sie alloziert ke<strong>in</strong>en Speicherplatz für<br />
die Array-Elemente.<br />
◇ E<strong>in</strong>e Array-Variable legt nur den Element-Typ , nicht aber die Länge e<strong>in</strong>es Arrays (d.h. die Anzahl se<strong>in</strong>er Elemente)<br />
fest. Sie kann daher auf Arrays beliebiger Länge zeigen.<br />
◇ Die Länge e<strong>in</strong>es Arrays wird dynamisch bei se<strong>in</strong>er Erzeugung (z.B. mittels e<strong>in</strong>es new-Ausdrucks) festgelegt.<br />
Anschliessend ist sie nicht mehr veränderbar.<br />
◇ E<strong>in</strong> Array kann auch die Länge 0 besitzen. E<strong>in</strong> derartiges Array ist e<strong>in</strong> echtes Array-Objekt.<br />
S<strong>in</strong>nvoll können derartige Arrays beispielsweise als Rückgabewert von Funktionen (genauer : Referenz darauf) auf-<br />
treten.<br />
◇ Jedes Array besitzt die öffentliche Datenkomponente<br />
public f<strong>in</strong>al <strong>in</strong>t length;<br />
Sie enthält die Länge des Arrays.<br />
◇ E<strong>in</strong> Array-Zugriff wird zur Laufzeit auf Zulässigkeit überprüft.<br />
Der Versuch des Zugriffs zu e<strong>in</strong>er nicht existierenden Array-Komponente (ungültiger Index) führt zum Werfen der<br />
Exception ArrayIndexOutOfBoundsException.<br />
• Vere<strong>in</strong>barung von Array-Variablen<br />
◇ Angabe e<strong>in</strong>es Array-Typs :<br />
Element-Typ []<br />
◇ Diese Typangabe ist bei der Vere<strong>in</strong>barung von Array-Variablen zu verwenden.<br />
Beispiele : <strong>in</strong>t[] ia; // ia kann auf Array-Objekte zeigen, deren Elemente <strong>in</strong>t-Werte s<strong>in</strong>d<br />
Str<strong>in</strong>g[] names; // names kann auf Array-Objekte zeigen, deren Elemente Referenzen<br />
// auf Str<strong>in</strong>g-Objekte s<strong>in</strong>d<br />
◇ Element-Typ e<strong>in</strong>es Arrays kann wiederum e<strong>in</strong> Array se<strong>in</strong> mehrdimensionale Arrays.<br />
Die Vere<strong>in</strong>barung mehrdimensionaler Arrays erfolgt analog zu e<strong>in</strong>dimensionalen Arrays.<br />
Beispiele : double[][] kmat; // kmat kann auf Array-Objekte zeigen, deren Elemente Referenzen auf<br />
// Array-Objekte s<strong>in</strong>d, die double-Werte enthalten<br />
Str<strong>in</strong>g[][] seite; // seite kann auf Array-Objekte zeigen, deren Elemente Referenzen<br />
// auf Array-Objekte s<strong>in</strong>d, die Referenzen auf Str<strong>in</strong>g-Objekte enthalten.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 282 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Def<strong>in</strong>ition von Array-Objekten<br />
Arrays <strong>in</strong> <strong>Java</strong> (2)<br />
◇ Def<strong>in</strong>ition von Array-Objekten mittels e<strong>in</strong>es new-Ausdrucks.<br />
Dabei ist die Länge des Arrays explizit anzugeben.<br />
Die e<strong>in</strong>zelnen Elemente werden mit ihrem Defaultwert <strong>in</strong>itialisiert.<br />
Beispiele : ia = new <strong>in</strong>t[10]; // Speicherallokation für e<strong>in</strong> Array-Objekt, das 10 <strong>in</strong>t-<br />
// Elemente hat. Alle Elemente s<strong>in</strong>d mit 0 <strong>in</strong>itialisiert.<br />
names = new Str<strong>in</strong>g[3]; // Speicherallokation für e<strong>in</strong> Array-Objekt, das 3 Elemente hat,<br />
// die Referenzen auf Str<strong>in</strong>g-Objekte s<strong>in</strong>d.<br />
// Alle Elemente s<strong>in</strong>d mit null <strong>in</strong>itialisiert.<br />
◇ Die Def<strong>in</strong>ition e<strong>in</strong>es Array-Objekts mittels e<strong>in</strong>es new-Ausdrucks kann natürlich auch zusammen mit der Vere<strong>in</strong>-<br />
barung e<strong>in</strong>er Array-Variablen erfolgen.<br />
Beispiel : float[] pol = new float[6]; // pol zeigt auf e<strong>in</strong> alloziertes float-Array mit<br />
// 6 Elementen (die alle mit 0.0 <strong>in</strong>itialisiert s<strong>in</strong>d)<br />
◇ Bei mehrdimensionalen Arrays kann im new-Ausdruck die Länge aller Dimensionen angegeben werden.<br />
Es reicht aber aus, nur die Länge der ersten (am weitesten l<strong>in</strong>ks stehenden) Dimension festzulegen. Die Längen der<br />
übrigen Dimensionen müssen dann später festgelegt werden.<br />
Beispiel : kmat = new double[5][4]; // Speicherallokation für e<strong>in</strong> Array-Objekt, das 5 Elemente hat,<br />
// die auf gleichzeitig allozierte double-Arrays, die alle<br />
// 4 Elemente haben, zeigen.<br />
// Die Elemente der double-Arrays s<strong>in</strong>d mit 0.0 <strong>in</strong>itialisiert<br />
Das obige Beispiel ist e<strong>in</strong>e abkürzende Schreibweise für die folgende ausführlichere Formulierung :<br />
kmat = new double[5][]; // Speicherallokation für e<strong>in</strong> Array-Objekt, das 5 Elemente hat,<br />
// die auf double-Arrays zeigen können, aber alle mit null<br />
// <strong>in</strong>itialisiert s<strong>in</strong>d.<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 283 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Arrays und Polymorphie<br />
Arrays <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Obwohl Array-Typen nicht ableitbar s<strong>in</strong>d, kann auf sie – sofern es sich um Arrays von Referenz-Typen handelt –<br />
Polymorphie angewendet werden.<br />
◇ Gegeben seien zwei Klassen X und Y.<br />
Die Klasse Y sei von der Klasse X abgeleitet.<br />
Die durch diese Vererbungsbeziehung def<strong>in</strong>ierte Polymorphie wird auch auf Arrays von Objekten dieser Klassen<br />
übertragen.<br />
Bezüglich der Polymorphie verhalten sich die Klassen Y[] und X[] also so, als ob sie vone<strong>in</strong>ander abgeleitet<br />
wären.<br />
X<br />
X[]<br />
E<strong>in</strong>er Array-Variablen vom Typ X[] kann dadurch auch die Referenz auf e<strong>in</strong> Y[]-Objekt zugewiesen werden.<br />
Beispiel : Y[] yArr = new Y[3];<br />
X[] xArr = yArr; // zulässig, da Y an X zuweisbar ist.<br />
◇ Achtung : Den Elementen e<strong>in</strong>es Referenz-Typ-Arrays dürfen nur Referenzen auf solche Objekte zugewiesen<br />
werden, die auch Variablen se<strong>in</strong>es tatsächlichen Element-Typs zugewiesen werden können.<br />
Im obigen Beispiel dürfen den Elementen von xArr daher nur Referenzen auf Y-Objekte zugewiesen werden.<br />
Beispiel : xArr[0] = new Y(); // zulässig, da e<strong>in</strong>er Y-Variablen e<strong>in</strong>e Referenz auf e<strong>in</strong> Y-Objekt<br />
// zugewiesen werden kann<br />
xArr[1] = new X(); // unzulässig, da e<strong>in</strong>er Y-Variablen ke<strong>in</strong>e Referenz auf e<strong>in</strong> X-Objekt<br />
// zugewiesen werden darf<br />
◇ Die Zulässigkeit der Zuweisung an Elemente e<strong>in</strong>es Referenz-Typ-Arrays wird zur Laufzeit überprüft.<br />
Beim Versuch e<strong>in</strong>er unzulässigen Zuweisung wird e<strong>in</strong>e Exception vom Typ ArrayStoreException geworfen.<br />
• Unterstützende Klassen der Standard-Bibliothek<br />
Y<br />
wirkt sich h<strong>in</strong>sichtlich e<strong>in</strong>er<br />
polymorphen Verwendung aus wie<br />
◇ In der <strong>Java</strong>-Standardbibliothek s<strong>in</strong>d zwei Klassen def<strong>in</strong>iert, die statische Memberfunktionen zur Unterstützung der<br />
Verwendung von Arrays zur Verfügung stellen<br />
Beide Klassen können nicht <strong>in</strong>stanziiert werden.<br />
◇ Klasse java.lang.reflect.Array<br />
Sie stellt statische Methoden zur dynamischen Erzeugung von und zum Zugriff zu Arrays zur Verfügung.<br />
◇ Klasse java.util.Arrays<br />
Sie stellt statische Methoden zur Bearbeitung von Arrays zur Verfügung.<br />
Im wesentlichen handelt es sich um Methoden<br />
- zum Suchen <strong>in</strong> Arrays<br />
- zum Sortieren von Array-Komponenten<br />
- zum Vergleich von Arrays<br />
- zur Zuweisung an Array-Bereiche<br />
◇ Die Klasse java.lang.System def<strong>in</strong>iert zum Kopieren von Arraybereichen die statische Methode<br />
public static void arraycopy(Object src, <strong>in</strong>t sPos, Object dest, <strong>in</strong>t dPos, <strong>in</strong>t len)<br />
Quell-Objekt (src) und Ziel-Objekt (dest) müssen Arrays se<strong>in</strong><br />
Y[]
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 284 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Quellcode des Programms (Klasse ArrayDemo)<br />
• Ausgabe des Programms<br />
Demonstrationsprogramm zu Arrays <strong>in</strong> <strong>Java</strong><br />
public class ArrayDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
<strong>in</strong>t[] ia;<br />
ia = new <strong>in</strong>t[6];<br />
System.out.pr<strong>in</strong>tln("<strong>in</strong>t-Array : " + ia);<br />
for (<strong>in</strong>t i=0; i
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 285 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Eigenschaften von Array-Listen<br />
Array-Listen <strong>in</strong> <strong>Java</strong><br />
◇ Array-Listen s<strong>in</strong>d Datenstrukturen, die die Eigenschaften von Listen und Arrays komb<strong>in</strong>ieren.<br />
◇ Sowohl <strong>in</strong> Listen als auch <strong>in</strong> Arrays s<strong>in</strong>d die Elemente alle vom gleichen Typ.<br />
In beiden Strukturarten s<strong>in</strong>d die Elemente <strong>in</strong> e<strong>in</strong>er l<strong>in</strong>earen Reihenfolge angeordnet und damit damit über e<strong>in</strong>e Positions-<br />
angabe referierbar.<br />
Der Zugriff zu e<strong>in</strong>em Array-Element erfolgt dabei mittels Indizierung, die Zugriffszeit ist unabhängig von der Position.<br />
Der Zugriff zu e<strong>in</strong>em Listen-Element erfolgt über e<strong>in</strong>e Zugriffsfunktion, der die Position (Index) zu übergeben ist.<br />
Die Zugriffszeit hängt i.a. von der Position ab.<br />
◇ Die Größe e<strong>in</strong>es Arrays (d.h. die Anzahl der enthaltenen Elemente) ist i.a. feststehend und nicht veränderbar,<br />
während die Größe e<strong>in</strong>er Liste variabel ist und jederzeit – durch das E<strong>in</strong>fügen oder Entfernen von Elementen – geändert<br />
werden kann.<br />
◇ Array-Listen implementieren im Pr<strong>in</strong>zip <strong>in</strong> der Größe veränderliche Arrays :<br />
- Bezüglich der Zugriffszeit zu e<strong>in</strong>em Element verhalten sie sich wie Arrays (unabhängig von der Position)<br />
- Bezüglich der Elementeanzahl verhalten sie sich wie Listen, d.h. es können Elemente entfernt und h<strong>in</strong>zugefügt<br />
werden<br />
- Die Elemente werden über e<strong>in</strong>en Index (<strong>in</strong>t-Wert) referiert, das erste Element hat den Index 0.<br />
Der Zugriff erfolgt über e<strong>in</strong>e Zugriffsfunktion.<br />
• Realisierung von Array-Listen <strong>in</strong> <strong>Java</strong><br />
◇ Array-Listen werden <strong>in</strong> <strong>Java</strong> durch Objekte der Klasse ArrayList realisiert.<br />
Für diese Klasse gelten – im Gegensatz zu Arrays (namenlose Klassen !) – ke<strong>in</strong>e syntaktischen Besonderheiten.<br />
Array-Listen-Objekte werden mittels e<strong>in</strong>es new-Ausdrucks erzeugt – mit gleicher Syntax wie für andere benamte<br />
Klassen.<br />
◇ Array-Listen-Objekte können sich – wie Array-Objekte – im Element-Typ unterscheiden.<br />
Es gibt unterschiedliche Array-Listen-Typen.<br />
Die Klasse ArrayList ist e<strong>in</strong>e generische Klasse (genaueres zu generischen Klassen s. später).<br />
Generische Klassen besitzen e<strong>in</strong>e (oder mehrere) Typ-Parameter.<br />
Bei der Verwendung e<strong>in</strong>er derartigen Klasse s<strong>in</strong>d i.a. e<strong>in</strong> aktuelle Typ-Parameter anzugeben. Dadurch wird jeweils<br />
e<strong>in</strong> parameterisierter Typ def<strong>in</strong>iert.<br />
Im vorliegenden Fall ist der Typ-Parameter der Typ der Array-Listen-Elemente.<br />
Die verschiedenen Array-Listen-Typen s<strong>in</strong>d also parameterisierte Typen, die durch die Klasse ArrayList<br />
def<strong>in</strong>iert werden.<br />
◇ Die exakte Klassenbezeichnung lautet ArrayList.<br />
E ist der formale Typ-Parameter.<br />
Bei der Verwendung der Klasse (z.B. zur Objekterzeugung) ist E durch den jeweiligen Element-Typ als aktueller<br />
Typ-Parameter zu ersetzen, dieser muss e<strong>in</strong> Referenz-Typ se<strong>in</strong> (Unterschied zu Arrays !)<br />
Beispiel :<br />
ArrayList salist = new ArrayList();<br />
ArrayList ist die Typ-Bezeichnung für "ArrayListe mit Str<strong>in</strong>g-Elementen"<br />
Erzeugung e<strong>in</strong>es Array-Listen-Objekts mit Str<strong>in</strong>g-Elementen<br />
◇ Anmerkung zur Implementierung :<br />
E<strong>in</strong> Array-Listen-Objekt kapselt e<strong>in</strong> Array se<strong>in</strong>es Element-Typs. Dieses Array besitzt e<strong>in</strong>e Größe, die größer gleich<br />
der Anzahl der Array-Listen-Elemente ist. Sie wird als Kapazität der Array-Liste bezeichnet.<br />
Solange die Anzahl der Array-Listen-Elemente kle<strong>in</strong>er als die Kapazität ist, können problemlos neue Elemente h<strong>in</strong>zu-<br />
gefügt werden. Reicht die Kapazität zur Aufnahme e<strong>in</strong>es neuen Elements nicht mehr aus, muss e<strong>in</strong> neues entsprechend<br />
größeres <strong>in</strong>ternes Array alloziert werden und der Inhalt des alten Arrays <strong>in</strong> das neue Array kopiert werden.<br />
Zeitaufwand ( sollte nicht zu häufig auftreten).
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 285 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Die Klasse ArrayList <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Die generische Klasse ArrayList bef<strong>in</strong>det sich im Package java.util.<br />
Sie ist Bestandteil des Collection Frameworks.<br />
◇ Sie dient zur Realisierung von Array-Listen<br />
◇ Sie ist von der Klasse AbstractList abgeleitet und implementiert die Interfaces List, Cloneable,<br />
Serializable. RandomAccess, Iterable und Collection.<br />
• Konstruktoren der Klasse ArrayList (Auswahl)<br />
• Memberfunktionen der Klasse ArrayList (Auswahl)<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public ArrayList Erzeugt e<strong>in</strong> leeres ArrayList-Objekt für Elemente des<br />
Typs E. Das Objekt hat e<strong>in</strong>e Anfangs-Kapazität von 10.<br />
public ArrayList(<strong>in</strong>t <strong>in</strong>itCap) Erzeugt e<strong>in</strong> leeres ArrayList-Objekt für Elemente des<br />
Typs E. Das Objekt hat e<strong>in</strong>e Anfangs-Kapazität von <strong>in</strong>itCap<br />
public boolean add(E elem)<br />
▻ E<strong>in</strong>fügen des Elements elem vom Typ E an das Ende der Array-Liste<br />
▻ Funktionswert : true<br />
public void add(<strong>in</strong>t <strong>in</strong>dex, E elem)<br />
▻ E<strong>in</strong>fügen des Elements elem vom Typ E an der Position <strong>in</strong>dex.<br />
▻ E<strong>in</strong> an der Position <strong>in</strong>dex vorhandenes Element und alle danach kommenden Elemente werden um e<strong>in</strong>e<br />
Position weitergeschoben<br />
▻ Liegt <strong>in</strong>dex ausserhalb der Liste, wird e<strong>in</strong>e IndexOutOfBoundsException geworfen<br />
public boolean remove(Object elem)<br />
▻ Entfernen des ersten Auftritts des Elements elem, dieses muß tatsächlich vom Typ E se<strong>in</strong> (Die Klasse Object<br />
ist Basisklasse für alle anderen Klassen <strong>in</strong> <strong>Java</strong>, jedes beliebige Element e<strong>in</strong>es Refernztyps – d.h. jedes beliebige<br />
Objekt – kann daher als Instanz der Klasse Object betrachtet werden).<br />
▻ Alle nach dem entfernten Element enthaltenen Elemente werden um e<strong>in</strong>e Position nach vorn geschoben.<br />
▻ Funktionswert : true, wenn das Element elem enthalten war,<br />
false, wenn das Element elem nicht enthalten war<br />
public E remove(<strong>in</strong>t <strong>in</strong>dex)<br />
▻ Entfernen des Elements an der Position <strong>in</strong>dex.<br />
▻ Alle nach dem entfernten Element enthaltenen Elemente werden um e<strong>in</strong>e Position nach vorn geschoben.<br />
▻ Funktionswert : das entfernte Element<br />
▻ Liegt <strong>in</strong>dex ausserhalb der Liste, wird e<strong>in</strong>e IndexOutOfBoundsException geworfen<br />
public void clear()<br />
▻ Entfernen aller Elemente aus der Liste, die Liste ist anschliessend leer.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 285 – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Die Klasse ArrayList <strong>in</strong> <strong>Java</strong> (2)<br />
• Memberfunktionen der Klasse ArrayList (Auswahl), Forts.<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public E get(<strong>in</strong>t <strong>in</strong>dex)<br />
▻ Auslesen des Elements an der Position <strong>in</strong>dex. (Die Liste bleibt unverändert)<br />
▻ Funktionswert : das Element an der Position <strong>in</strong>dex.<br />
▻ Liegt <strong>in</strong>dex ausserhalb der Liste, wird e<strong>in</strong>e IndexOutOfBoundsException geworfen<br />
public E set(<strong>in</strong>t <strong>in</strong>dex, E elem)<br />
▻ Ersetzen des an der Position <strong>in</strong>dex bef<strong>in</strong>dlichen Elements durch das Element elem.<br />
▻ Funktionswert : das Element, das sich zuvor an der Position <strong>in</strong>dex befunden hat..<br />
▻ Liegt <strong>in</strong>dex ausserhalb der Liste, wird e<strong>in</strong>e IndexOutOfBoundsException geworfen<br />
public void ensureCapacity(<strong>in</strong>t m<strong>in</strong>Cap)<br />
▻ Sicherstellung, dass die Kapazität m<strong>in</strong>destens m<strong>in</strong>Cap beträgt (falls erforderlich wird die Kapazität erhöht)<br />
public <strong>in</strong>t size()<br />
▻ Ermittlung der Array-Listen-Größe (== Anzahl der enthaltenen Elemente)<br />
▻ Funktionswert : Anzahl der enthaltenen Elemente<br />
public E[] toArray(E[] arr)<br />
▻ Übertragung des Listen<strong>in</strong>halts – unter Beibehaltung der Element-Reihenfolge – <strong>in</strong> e<strong>in</strong> Array.<br />
▻ Falls das als Parameter übergebene Array arr groß genug ist, wird der Listen<strong>in</strong>halt <strong>in</strong> dieses Array übertragen,<br />
falls es zu kle<strong>in</strong> ist, wird e<strong>in</strong> neues Array alloziert und als Ziel-Array verwendet.<br />
▻ Falls das als Parameter übergebene Array arr größer als die Array-Liste ist, werden die nicht belegten Array-<br />
Elemente gleich null gesetzt.<br />
▻ Funktionswert : Array, <strong>in</strong> das die Listenelemente übertragen wurden.<br />
public Object[] toArray()<br />
▻ Übertragung des Listen<strong>in</strong>halts – unter Beibehaltung der Element-Reihenfolge – <strong>in</strong> e<strong>in</strong> neu alloziertes Array,<br />
dessen Elementtyp tatsächlich E ist.<br />
▻ Funktionswert : Array, <strong>in</strong> das die Listenelemente übertragen wurden.<br />
• Vergleich der Verwendung von Arrays und Arry-Listen<br />
Array Array-Liste<br />
Variablen-Def<strong>in</strong>ition Str<strong>in</strong>g[] a; ArrayList a;<br />
Objekterzeugung a = new Str<strong>in</strong>g[50]; a = new ArrayList();<br />
Schreiben a[i] = "Muenchen"; a.set(i, "München");<br />
Lesen Str<strong>in</strong>g s = a[i]; Str<strong>in</strong>g s = a.get(i);<br />
Größenermittlung <strong>in</strong>t len = a.length; <strong>in</strong>t len = a.size();
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 285 – 04 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Demonstrationsprogramm zu ArrayListen <strong>in</strong> <strong>Java</strong><br />
• Quellcode des Programms (Klasse ArrayListDemo)<br />
// ArrayListDemo.java<br />
import java.util.*;<br />
public class ArrayListDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
ArrayList al = new ArrayList();<br />
System.out.pr<strong>in</strong>tln();<br />
System.out.pr<strong>in</strong>tln("ArrayListe erzeugt, Laenge : " + al.size());<br />
al.add("Muenchen");<br />
al.add("Hamburg");<br />
al.add("Berl<strong>in</strong>");<br />
al.add("Koeln");<br />
al.add("Stuttgart");<br />
System.out.pr<strong>in</strong>tln("ArrayListe gefuellt, Laenge : " + al.size());<br />
for (<strong>in</strong>t i=0; i
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 286 – 01 – TH – 04<br />
------------------------------------------------------------------------------------<br />
Die vere<strong>in</strong>fachte for-Anweisung <strong>in</strong> <strong>Java</strong><br />
• Iteration über alle Elemente e<strong>in</strong>es Arrays (und e<strong>in</strong>es Conta<strong>in</strong>ers)<br />
◇ Zum sequentiellen Durchlaufen der Elemente e<strong>in</strong>es Arrays wird üblicherweise die – auch aus C/C++ bekannte –<br />
(Standard-) for-Anweisung e<strong>in</strong>gesetzt.<br />
Zum Zugriff zu den Elementen erfordert sie die explizite Def<strong>in</strong>ition und Verwendung e<strong>in</strong>er "Laufvariablen".<br />
◇ Beispiel : double[] da;<br />
// ...<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 286 – 02 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Demonstrationsprogramm zur vere<strong>in</strong>fachten for-Anweisung <strong>in</strong> <strong>Java</strong><br />
• Quellcode des Programms (Klasse ForEachDemo)<br />
// ForEachDemo.java<br />
public class ForEachDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
double[] da;<br />
da = new double[6];<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 291 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• "Mutter" aller Klassen<br />
Die Klasse Object <strong>in</strong> <strong>Java</strong> (1)<br />
◇ In <strong>Java</strong> existiert nur e<strong>in</strong>e Klassenhierarchie.<br />
Wurzel dieser Hierarchie ist die Klasse Object.<br />
Alle Klassen haben – direkt oder <strong>in</strong>direkt – diese Klasse als Basisklasse.<br />
Auch Klassen, die sche<strong>in</strong>bar nicht abgeleitet s<strong>in</strong>d, d.h. die ohne Angabe e<strong>in</strong>er Basisklasse def<strong>in</strong>iert s<strong>in</strong>d, s<strong>in</strong>d tatsäch-<br />
lich implizit von Object abgeleitet.<br />
◇ Da e<strong>in</strong>e Variable e<strong>in</strong>es Klassen-Typs auch auf Objekte abgeleiteter Klassen zeigen kann (Laufzeit-Polymorphie !), kann<br />
e<strong>in</strong>e Variable vom Typ Object Objekte e<strong>in</strong>es beliebigen Klassen-Typs (e<strong>in</strong>schliesslich Array-Typs) referieren.<br />
◇ Die Klasse Object ist im Package java.lang enthalten.<br />
• Memberfunktionen der Klasse Object<br />
◇ Die Klasse Object def<strong>in</strong>iert <strong>in</strong>sgesamt elf Memberfunktionen, die wegen der Vererbung <strong>in</strong> allen Klassen zur Ver-<br />
fügung stehen.<br />
◇ Sechs dieser Memberfunktionen s<strong>in</strong>d nicht überschreibbar.<br />
Die übrigen lassen sich <strong>in</strong> abgeleiteten Klassen überschreiben. In Abhängigkeit von der jeweiligen Klasse kann für<br />
e<strong>in</strong>e s<strong>in</strong>nvolle Funktionalität e<strong>in</strong> Überschreiben notwendig se<strong>in</strong>.<br />
◇ Die Memberfunktionen von Object zerfallen <strong>in</strong> zwei Kategorien :<br />
- Allgeme<strong>in</strong>e Utility-Funktionen<br />
- Methoden zur Thread-Unterstützung<br />
Hier werden nur kurz die Utilility-Funktionen vorgestellt.<br />
Auf die Methoden zur Thread-Unterstützung wird später im Rahmen der Besprechung von Threads e<strong>in</strong>gegangen.<br />
◇<br />
◇<br />
public boolean equals(Object obj)<br />
▻ Die Funktion vergleicht das aktuelle Objekt mit dem durch obj referierten Objekt.<br />
Sie liefert true als Funktionswert, wenn Gleichheit vorliegt, andernfalls false.<br />
▻ Grundsätzlich ist die Funktion für e<strong>in</strong>e Überprüfung auf Wert-Gleichheit der Objekte vorgesehen.<br />
▻ Die Default-Implementierung <strong>in</strong> der Klasse Object geht davon aus, dass e<strong>in</strong> Objekt nur zu sich selbst gleich<br />
se<strong>in</strong> kann, d.h. sie setzt Wert-Gleichheit mit Referenz-Gleichheit (Identität) gleich.<br />
Sie liefert genau dann true, wenn obj das aktuelle Objekt referiert (obj==this).<br />
▻ Für die Implementierung e<strong>in</strong>er echten Wert-Gleichheit, die sich auf den Inhalt (Zustand) der referierten Objekte<br />
bezieht, muss die Methode <strong>in</strong> abgeleiteten Klassen geeignet überschrieben werden.<br />
Dies ist für zahlreiche Klassen der Standard-Bibliothek, u.a. auch für die Klasse Str<strong>in</strong>g, erfolgt.<br />
public <strong>in</strong>t hashCode()<br />
▻ Die Funktion liefert e<strong>in</strong>en Hash-Code für das aktuelle Objekt. Jedes Objekt besitzt e<strong>in</strong>en derartigen Hash-Code.<br />
Er ermöglicht die Speicherung von Objekten <strong>in</strong> Hash-Tabellen (z.B. Klasse java.util.Hashtable).<br />
▻ Der Hash-Code e<strong>in</strong>es Objekts darf sich während der Ausführung e<strong>in</strong>er <strong>Java</strong>-Applikation nicht ändern.<br />
Bei unterschiedlichen Ausführungen derselben Applikation kann er dagegen unterschiedlich se<strong>in</strong>.<br />
▻ Die Default-Implementierung <strong>in</strong> der Klasse Object liefert für unterschiedliche Objekte unterschiedliche<br />
Hash-Codes (Typischerweise ist dieser gleich der <strong>in</strong> e<strong>in</strong>en <strong>in</strong>t-Wert umgewandelten Speicheradresse des Objekts).<br />
▻ Wenn für die zwei durch x und y referierten Objekte x.equals(y) den Wert true liefert, muß der für die<br />
beiden Objekte erzeugte Hash-Code auch gleich se<strong>in</strong> (x.hashCode()==y.hashCode())<br />
▻ Daher ist es bei Überschreiben der Funktion equals() i.a. auch notwendig die Funktion hashCode()<br />
entsprechend zu überschreiben.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 292 – 00 – TH – 06<br />
------------------------------------------------------------------------------------<br />
• Memberfunktionen der Klasse Object, Forts.<br />
◇<br />
◇<br />
◇<br />
◇<br />
Die Klasse Object <strong>in</strong> <strong>Java</strong> (2)<br />
protected Object clone() throws CloneNotSupportedException<br />
▻ Die Funktion liefert e<strong>in</strong> neues Objekt, dass e<strong>in</strong> Clone (e<strong>in</strong>e Kopie) des aktuellen Objekts ist.<br />
▻ Die tatsächliche Klasse des aktuellen Objekts muß das Interface Cloneable implementieren.<br />
▻ Die Default-Implementierung <strong>in</strong> der Klasse Object prüft, ob für das aktuelle Objekt das Interface<br />
Cloneable implementiert ist.<br />
Ist das nicht der Fall, wird die Exception CloneNotSupportedException geworfen.<br />
Falls es implementiert ist, wird e<strong>in</strong> neues Objekt der Klasse erzeugt, dessen Datenkomponenten mit den Werten der<br />
entsprechenden Datenkomponenten des aktuellen Objekts <strong>in</strong>itialisiert werden. ("flache" Kopie, shallow copy)<br />
▻ Soll das neue Objekt als "tiefe" Kopie (deep copy) erzeugt werden, muss clone() geeignet überschrieben<br />
werden.<br />
▻ Die Klasse Object selbst implementiert das Interface Cloneable nicht.<br />
Das bedeutet, dass der Aufruf von clone() für e<strong>in</strong> Objekt der Klasse Object zum Werfen der Exception<br />
CloneNotSupportedException führt.<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
▻ Die Funktion liefert e<strong>in</strong>e Str<strong>in</strong>g-Repräsentation des aktuellen Objekts.<br />
▻ Die Default-Implementierung <strong>in</strong> der Klasse Object erzeugt e<strong>in</strong> Str<strong>in</strong>g-Objekt, dessen Inhalt aus dem<br />
Klassennamen des aktuellen Objekts, dem Zeichen '@' und der sedezimalen Darstellung se<strong>in</strong>es Hash-Codes<br />
zusammengesetzt ist.<br />
▻ Soll e<strong>in</strong>e andere das Objekt kennzeichnende Str<strong>in</strong>g-Darstellung erzeugt werden, muss die Methode toStr<strong>in</strong>g()<br />
geeignet überschrieben werden<br />
▻ Die Methode toStr<strong>in</strong>g() wird immer dann implizit aufgerufen, wenn e<strong>in</strong>e Objekt-Referenz <strong>in</strong> e<strong>in</strong>em Str<strong>in</strong>g-<br />
Konkatenations-Ausdruck auftritt.<br />
public f<strong>in</strong>al Class getClass()<br />
▻ Die Funktion liefert die Instanz der Klasse Class, die die tatsächliche Klasse des aktuellen Objekts<br />
beschreibt. Der Typ-Parameter T steht für die repräsentierte Klasse (allgeme<strong>in</strong> : für den repräsentiertenTyp)<br />
▻ Die Klasse Class ist e<strong>in</strong>e wesentliche Komponente der Reflection-Fähigkeit von <strong>Java</strong> (enthalten im Package<br />
java.lang). Objekte dieser Klasse repräsentieren andere Klassen (sowie Interfaces und die primitiven Datentypen)<br />
und stellen charakteristische Informationen über diese zur Verfügung.<br />
Sie können nicht explizit erzeugt werden (es gibt ke<strong>in</strong>en öffentlichen Konstruktor), sondern werden durch die JVM<br />
beim Laden e<strong>in</strong>er Klasse automatisch generiert.<br />
▻ U.a. stellt die Klasse Class die Memberfunktion public Str<strong>in</strong>g getName() zur Verfügung.<br />
Diese liefert den vollqualifizierten Namen der repräsentierten Klasse als Str<strong>in</strong>g zurück.<br />
▻ Die Methode getClass() kann nicht überschrieben werden.<br />
protected void f<strong>in</strong>alize() throws Throwable<br />
▻ Diese Funktion wird vom Garbage Collector für e<strong>in</strong> Objekt aufgerufen, für das ke<strong>in</strong>e Referenz mehr existiert und<br />
das anschliessend vernichtet werden soll.<br />
▻ Der Zweck dieser Funktion liegt <strong>in</strong> der Durchführung von Bere<strong>in</strong>igungsaufgaben vor der endgültigen Objekt-<br />
vernichtung (z.B. Freigabe von Resourcen, wie z.B. I/O-Verb<strong>in</strong>dungen oder Schließen von Dateien usw).<br />
Die Funktion kann somit als e<strong>in</strong>e Art Ersatz für e<strong>in</strong>en Destruktor aufgefasst werden.<br />
▻ Die Default-Implementierung <strong>in</strong> der Klasse Object führt ke<strong>in</strong>erlei Aktionen aus.<br />
▻ Sollen für Objekte e<strong>in</strong>er bestimmten Klasse spezielle Bere<strong>in</strong>igungsaktionen ausgeführt werden, muss die Funktion<br />
für diese Klasse überschrieben werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 293 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Die Klasse Object <strong>in</strong> <strong>Java</strong> (3)<br />
• Demonstrationsprogramm zu Memberfunktionen der Klasse Object<br />
// ObjTest.java<br />
public class ObjTest implements Cloneable<br />
{<br />
private Str<strong>in</strong>g name;<br />
}<br />
public ObjTest(Str<strong>in</strong>g str)<br />
{<br />
name=str;<br />
}<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
{<br />
return super.toStr<strong>in</strong>g()+" ("+name+")";<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
ObjTest o1 = new ObjTest("Test1");<br />
System.out.pr<strong>in</strong>tln("o1.toStr<strong>in</strong>g() : " + o1.toStr<strong>in</strong>g());<br />
Object o2 = new ObjTest("Test2");<br />
System.out.pr<strong>in</strong>tln("o2 : " + o2);<br />
System.out.pr<strong>in</strong>tln("o1.hashCode() : " + o1.hashCode());<br />
System.out.pr<strong>in</strong>tln("o2.hashCode() : " + o2.hashCode());<br />
System.out.pr<strong>in</strong>tln("o2.equals(o1) : " + o2.equals(o1));<br />
o2=o1;<br />
System.out.pr<strong>in</strong>tln("\nnach o2=o1 :");<br />
System.out.pr<strong>in</strong>tln("o2 : " + o2);<br />
System.out.pr<strong>in</strong>tln("o2.equals(o1) : " + o2.equals(o1));<br />
try<br />
{<br />
o2=o1.clone();<br />
}<br />
catch (CloneNotSupportedException e)<br />
{<br />
System.out.pr<strong>in</strong>tln(e.toStr<strong>in</strong>g());<br />
}<br />
System.out.pr<strong>in</strong>tln("\nnach o2=o1.clone() :");<br />
System.out.pr<strong>in</strong>tln("o2 : " + o2);<br />
System.out.pr<strong>in</strong>tln("o2.equals(o1) : " + o2.equals(o1));<br />
}<br />
• Ausgabe des Programms<br />
o1.toStr<strong>in</strong>g() : ObjTest@119c082 (Test1)<br />
o2 : ObjTest@1add2dd (Test2)<br />
o1.hashCode() : 18464898<br />
o2.hashCode() : 28168925<br />
o2.equals(o1) : false<br />
nach o2=o1 :<br />
o2 : ObjTest@119c082 (Test1)<br />
o2.equals(o1) : true<br />
nach o2=o1.clone() :<br />
o2 : ObjTest@eee36c (Test1)<br />
o2.equals(o1) : false
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2A1 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Aufzählungstypen <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Aufzählungstypen wurden mit dem JDK 5.0 <strong>in</strong> <strong>Java</strong> e<strong>in</strong>geführt<br />
◇ Sie ermöglichen die Def<strong>in</strong>ition von Wertemengen, die ke<strong>in</strong>en semantischen Bezug zu Zahlen oder logischen Werten<br />
haben.<br />
◇ Die e<strong>in</strong>zelnen Werte, aus denen e<strong>in</strong> Aufzählungstyp besteht (Enum-Werte), besitzen e<strong>in</strong>en bei der Typdef<strong>in</strong>ition<br />
festgelegten Namen.<br />
Ausserdem ist jedem Enum-Wert e<strong>in</strong>e durch die Def<strong>in</strong>itions-Reihenfolge festgelegte Ordnungszahl zugeordnet.<br />
Der erste Wert besitzt die Ordnungszahl 0, der zweite die Ordnungszahl 1 usw.<br />
◇ Werte <strong>in</strong> verschiedenen Aufzählungstypen können den gleichen Namen besitzen.<br />
◇ <strong>Java</strong>-Aufzählungstypen s<strong>in</strong>d – anders als C/C++-Aufzählungstypen – typsicher :<br />
Der Compiler stellt sicher, dass e<strong>in</strong>er Aufzählungstyp-Variablen nur gültige Werte ihres Aufzählungstyps zugewiesen<br />
werden können.<br />
◇ Anders als <strong>in</strong> C/C++ steht der Name e<strong>in</strong>es Enum-Werts auch zur Laufzeit zur Verfügung und kann z.B. ausgegeben<br />
werden.<br />
◇ Enum-Werte können als case-Label <strong>in</strong> switch-Anweisungen verwendet werden.<br />
• Def<strong>in</strong>ition<br />
◇ In der e<strong>in</strong>fachsten Form (elementare Def<strong>in</strong>ition) werden Aufzählungstypen wie <strong>in</strong> C/C++ def<strong>in</strong>iert.<br />
Beispiele ; enum Jahreszeit { WINTER, FRUEHLING, SOMMER, HERBST };<br />
enum Farbe { ROT, GRUEN, BLAU, GELB, GRAU };<br />
◇ Über die Möglichkeiten von C/C++ h<strong>in</strong>ausgehend können auch noch komplexere Formen der Typ-Def<strong>in</strong>ition verwendet<br />
werden.<br />
• Verwendung<br />
enum Typ-Name {<br />
Wert-Name } ;<br />
◇ Aufzählungstypen können wie andere Typen verwendet werden, z.B. zur Def<strong>in</strong>ition von Variablen<br />
Beispiele : Jahreszeit saison;<br />
Farbe anstrich;<br />
◇ Aufzählungstyp-Werte (Enum-Werte) werden mit ihrem vollqualifizierten Namen angesprochen :<br />
Typ-Name<br />
◇ Aufzählungstyp-Variablen können Aufzählungstyp-Werte zugewiesen werden.<br />
Beispiele : saison = Jahreszeit.SOMMER;<br />
anstrich = Farbe.GRUEN;<br />
.<br />
◇ Anders als <strong>in</strong> C/C++ s<strong>in</strong>d zwischen Enum-Werten und <strong>in</strong>t-Werten weder implizite noch explizite Typ-<br />
Konvertierungen möglich.<br />
,<br />
Wert-Name
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2A2 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Implementierung<br />
Aufzählungstypen <strong>in</strong> <strong>Java</strong> (2)<br />
◇ Aufzählungstypen <strong>in</strong> <strong>Java</strong> s<strong>in</strong>d Klassen, die besondere Eigenschaften besitzen<br />
Aufzählungstyp-Variable s<strong>in</strong>d somit Referenz-Variable.<br />
◇ Alle Aufzählungstypen s<strong>in</strong>d implizit von der abstrakten Bibliotheksklasse Enum abgeleitet. (Package java.lang)<br />
Diese besitzt u.a. je e<strong>in</strong>e Datenkomponente zur Speicherung des Namens des Aufzählungstyp-Werts (Typ Str<strong>in</strong>g)<br />
sowie der dem Wert zugeordneten Ordnungszahl (Typ <strong>in</strong>t)<br />
◇ Die e<strong>in</strong>zelnen Aufzählungstyp-Werte s<strong>in</strong>d Objekte ihrer jeweiligen Klasse (Enum-Objekte).<br />
Sie werden implizit beim Laden der Klasse erzeugt und als öffentlich zugreifbare statische Datenkomponenten<br />
gespeichert. (Verwendung über ihren vollqualifizierten Namen !, s. oben)<br />
E<strong>in</strong>e explizite Instantierung e<strong>in</strong>er Aufzählungstyp-Klasse ist nicht möglich.<br />
◇ Wie jede Klasse kann e<strong>in</strong> Aufzählungstyp auch Memberfunktionen und weitere Datenkomponenten besitzen.<br />
◇ Neben den für jeden Aufzählungstyp standardmässig vorhandenen Memberfunktionen (teilweise geerbt von<br />
Object und Enum) können bei se<strong>in</strong>er Def<strong>in</strong>ition weitere Methoden und Datenkomponenten festgelegt werden.<br />
• Standardmässig def<strong>in</strong>ierte Memberfunktionen von Aufzählungstypen (Auswahl)<br />
E bezeichnet den jeweiligen Aufzählungstyp<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public static E[] values() /* automatisch vom Compiler generiert */<br />
▻ Die Funktion gibt e<strong>in</strong> Array zurück, das alle Aufzählungstyp-Werte (Enum-Objekte !) <strong>in</strong> der Reihenfolge<br />
ihrer Def<strong>in</strong>ition enthält<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g() /* def<strong>in</strong>iert <strong>in</strong> Enum */<br />
▻ Die Funktion liefert den Namen des aktuellen Aufzählungstyp-Wertes (Enum-Objektes) zurück.<br />
public f<strong>in</strong>al <strong>in</strong>t ord<strong>in</strong>al() /* def<strong>in</strong>iert <strong>in</strong> Enum */<br />
▻ Die Funktion liefert die Ordnungszahl, die mit dem aktuellen Enum-Objekt verknüpft ist, zurück<br />
▻ Die Ordnungszahl entspricht der Reihenfolge der Enum-Objekte (Enum-Werte) <strong>in</strong> der Typ-Def<strong>in</strong>ition.<br />
Der erste Enum-Wert hat die Ordnungszahl 0.<br />
public f<strong>in</strong>al <strong>in</strong>t compareTo(E obj) /* def<strong>in</strong>iert <strong>in</strong> Enum */<br />
▻ Die Funktion vergleicht das aktuelle Enum-Objekt mit dem als Parameter übergebenen Enum-Objekt bezüglich<br />
ihrer Ordnungszahlen<br />
▻ Das aktuelle Enum-Objekt und das Parameter-Enum-Objekt müssen vom gleichen Aufzählungstyp se<strong>in</strong><br />
▻ Funktionswert : 0, wenn das aktuelle Objekt < dem Parameter-Objekt ist<br />
public f<strong>in</strong>al boolean equals(Object obj) /* def<strong>in</strong>iert <strong>in</strong> Enum */<br />
▻ Die Funktion vergleicht das aktuelle Enum-Objekt mit dem als Parameter übergebenen Objekt<br />
▻ Funktionswert : true, wenn das Parameter-Objekt gleich dem aktuellen Enum-Objekt ist<br />
false, wenn das Parameter-Objekt nicht gleich dem aktuellen Enum-Objekt ist
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2A3 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Aufzählungstypen <strong>in</strong> <strong>Java</strong> (3)<br />
• Aufzählungstypen mit selbstdef<strong>in</strong>ierten Methoden und Datenkomponenten<br />
◇ Aufzählungstypen können mit e<strong>in</strong>er beliebigen Anzahl zusätzlicher Memberfunktionen und Datenkomponenten<br />
def<strong>in</strong>iert werden.<br />
Dies eröffnet e<strong>in</strong> weites Spektrum an Gestaltungsmöglichkeiten für sehr effizient e<strong>in</strong>setzbare Aufzählungstypen.<br />
◇ Für die entsprechenden Aufzählungstyp-Def<strong>in</strong>itionen gilt e<strong>in</strong>e erweiterte komplexere Syntax.<br />
◇ Üblicherweise gilt e<strong>in</strong>e Memberfunktion für alle Objekte des entsprechenden Typs. Sie legt e<strong>in</strong> für alle Objekte gleich-<br />
artiges Verhalten fest.<br />
Bei Aufzählungstypen besteht darüberh<strong>in</strong>aus die Möglichkeit, für jeden Enum-Wert (Enum-Objekt) e<strong>in</strong> spezifisches<br />
Verhalten festzulegen.<br />
Hierzu kann man die entsprechende Methode <strong>in</strong> der Aufzählungstyp-Def<strong>in</strong>ition als abstract deklarieren und sie<br />
dann für jeden Enum-Wert konkret def<strong>in</strong>ieren. ( wert-spezifische Methoden, constant specific methods)<br />
◇ Beispiel für e<strong>in</strong>en Aufzählungstyp mit selbstdef<strong>in</strong>ierter für alle Enum-Werte geltender Memberfunktion :<br />
enum Wochentag<br />
{<br />
Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag;<br />
public boolean istWochenende()<br />
{<br />
return this==Samstag || this==Sonntag;<br />
}<br />
};<br />
◇ Wenn e<strong>in</strong> Aufzählungstyp mit zusätzlichen Datenkomponenten def<strong>in</strong>iert wird,<br />
▻ muss auch e<strong>in</strong> Konstruktor def<strong>in</strong>iert werden, mit dem die Datenkomponenten <strong>in</strong>itialisiert werden können<br />
▻ und müssen für jeden Enum-Wert entprechende aktuelle Werte für die Datenkomponenten bereitgestellt werden.<br />
Anmerkung : Auch wenn der Konstruktor public def<strong>in</strong>iert wird, lassen sich explizit ke<strong>in</strong>e Enum-Objekte anlegen.<br />
◇ Beispiel für e<strong>in</strong>en Aufzählungstyp mit e<strong>in</strong>er zusätzlichen Datenkomponente<br />
enum Jahreszeit2<br />
{<br />
WINTER ("Dezember bis Februar"),<br />
FRUEHLING("Maerz bis Mai"),<br />
SOMMER ("Juni bis August"),<br />
HERBST ("September bis Oktober");<br />
private Str<strong>in</strong>g bereich;<br />
public Jahreszeit2 (Str<strong>in</strong>g monate)<br />
{<br />
bereich = monate;<br />
}<br />
public Str<strong>in</strong>g getBereich()<br />
{<br />
return bereich;<br />
}<br />
};
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2A4 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Demonstrationsprogramm zu Aufzählungstypen <strong>in</strong> <strong>Java</strong><br />
• Quellcode des Programms (Klasse EnumDemo2)<br />
// EnumDemo2.java<br />
enum Wochentag<br />
{<br />
Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag;<br />
public boolean istWochenende()<br />
{ return this==Samstag || this==Sonntag; }<br />
};<br />
enum Jahreszeit2<br />
{<br />
WINTER ("Dezember bis Februar"),<br />
FRUEHLING("Maerz bis Mai"),<br />
SOMMER ("Juni bis August"),<br />
HERBST ("September bis Oktober");<br />
private Str<strong>in</strong>g bereich;<br />
public Jahreszeit2 (Str<strong>in</strong>g monate)<br />
{ bereich = monate; }<br />
public Str<strong>in</strong>g getBereich()<br />
{ return bereich; }<br />
};<br />
public class EnumDemo2<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Wochentag tag = Wochentag.Samstag;<br />
System.out.pr<strong>in</strong>tln();<br />
System.out.pr<strong>in</strong>tln(tag + " gehoert zum Wochenende : " + tag.istWochenende());<br />
}<br />
}<br />
Jahreszeit2 saison = Jahreszeit2.HERBST;<br />
System.out.pr<strong>in</strong>tln("aktuelle Jahreszeit : " + saison);<br />
System.out.pr<strong>in</strong>tln("\nDie Jahreszeiten :");<br />
for (Jahreszeit2 jz : Jahreseit2.values())<br />
System.out.pr<strong>in</strong>tln(jz + " umfasst " + jz.getBereich());<br />
• Ausgabe des Programms<br />
Samstag gehoert zum Wochenende : true<br />
aktuelle Jahreszeit : HERBST<br />
Die Jahreszeiten :<br />
WINTER umfasst Dezember bis Februar<br />
FRUEHLING umfasst Maerz bis Mai<br />
SOMMER umfasst Juni bis August<br />
HERBST umfasst September bis Oktober
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2B1 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Generische Programierung <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Unter generischer Programmierung versteht man die Formulierung von Programm-Code, der <strong>in</strong> se<strong>in</strong>er wesentlichen<br />
Funktionalität unabhängig von Repräsentationsdetails konkreter Datentypen ist.<br />
Der Code wird e<strong>in</strong>mal allgeme<strong>in</strong> formuliert und lässt sich dann für unterschiedliche konkrete Datentypen verwenden.<br />
◇ E<strong>in</strong> typisches Beispiel für generische Programmierung bilden i.a. Conta<strong>in</strong>er-Bibliotheken (z.B. STL <strong>in</strong> C++,<br />
Collection Framework <strong>in</strong> <strong>Java</strong>).<br />
Conta<strong>in</strong>er speichern und verwalten Daten (Objekte) unterschiedlicher Typen. Ihre jeweilige Funktionalität ist dabei i.a.<br />
unabhängig von den konkreten Typen der Daten.<br />
Beispiel : E<strong>in</strong> Stack für Integer-Werte besitzt die gleiche Funktionalität wie e<strong>in</strong> Stack für Str<strong>in</strong>gs oder e<strong>in</strong> Stack für<br />
Person-Objekte.<br />
◇ Generische Programmierung lässt sich realisieren mittels<br />
▻ Polymorphie (zum<strong>in</strong>dest e<strong>in</strong>geschränkt)<br />
▻ Typ-Parameterisierung<br />
◇ In C++ wird generische Programmierung durch den E<strong>in</strong>satz von Klassen- und/oder Funktions-Templates ermöglicht,<br />
die mit Typ-Parametern arbeiten<br />
• Generische Programmierung <strong>in</strong> <strong>Java</strong> bis e<strong>in</strong>schliesslich dem JDK 1.4<br />
◇ Für e<strong>in</strong>e – e<strong>in</strong>geschränkte – generische Programmierung steht lediglich das Konzept der Polymorphie zur Verfügung.<br />
◇ Beispielweise verwalten die Conta<strong>in</strong>er des Collection Frameworks Objekte der Klasse Object.<br />
Da <strong>in</strong> <strong>Java</strong> jede Klasse direkt oder <strong>in</strong>direkt von Object abgeleitet ist, können die Conta<strong>in</strong>er für Daten beliebigen<br />
Referenz-Typs e<strong>in</strong>gesetzt werden.<br />
Das Collection Framework ist somit generisch programmiert.<br />
Auch <strong>in</strong> anderen Stellen der <strong>Java</strong> Standard-Bibliothek wird diese Art der generischen Programmierung verwendet.<br />
◇ Im Code, der derartigen Code – z.B.das Collection Framework – verwendet, müssen gegebenenfalls explizite Type-<br />
Casts <strong>in</strong> den tatsächlich konkret verwendeten Datentyp vorgenommen werden.<br />
Der Anwendungsprogrammierer ist für die Wahl der richtigen Type-Casts verantwortlich. Die Verwendung falscher<br />
Typ-Casts kann vom Compiler i.a. nicht erkannt werden, sondern wird erst durch das Auftreten von Laufzeitfehlern<br />
entdeckt.<br />
◇ Beispiel :<br />
// GenProgDemo14.java<br />
// Demonstration der Anwendung generischer Programmierung mittels Polymorphie<br />
// (bis JDK 1.4)<br />
import java.util.*;<br />
public class GenProgDemo14<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Stack stk = new Stack();<br />
stk.push(new Integer(123));<br />
Integer i = (Integer)stk.pop(); // expliziter Type-Cast erforderlich !<br />
System.out.pr<strong>in</strong>tln("Wert vom Stack : " + i);<br />
stk.push("E<strong>in</strong> Str<strong>in</strong>g"); // fehlerfrei uebersetzt<br />
i = (Integer)stk.pop(); // Laufzeitfehler ClassCastException<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2B2 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Generische Programierung <strong>in</strong> <strong>Java</strong> (2)<br />
• Generische Programmierung <strong>in</strong> <strong>Java</strong> ab dem JDK 1.5<br />
◇ Mit dem JDK 1.5 wurde <strong>in</strong> <strong>Java</strong> das Konzept der Generics als neues Sprachelement e<strong>in</strong>geführt.<br />
Dieses sieht die Def<strong>in</strong>ition generischer Klassen (und Interfaces) sowie generischer Methoden (e<strong>in</strong>schliesslich gene-<br />
rischer Konstruktoren) vor.<br />
Dadurch lässt sich nunmehr auch <strong>in</strong> <strong>Java</strong> e<strong>in</strong>e auf Typ-Parameterisierung basierende generische Programmierung<br />
realisieren.<br />
◇ Generics <strong>in</strong> <strong>Java</strong> weisen e<strong>in</strong>e formale Ähnlichkeit zu den Templates <strong>in</strong> C++ auf. Sie unterscheiden sich aber grund-<br />
legend von diesen bezüglich ihrer Implementierung und ihrer Behandlung durch den Compiler.<br />
◇ Mit der Def<strong>in</strong>ition e<strong>in</strong>er generischen Klasse (bzw e<strong>in</strong>es generischen Interfaces) werden formale Typ-Parameter<br />
festgelegt. Diese werden <strong>in</strong> <strong>Java</strong> auch als Typ-Variable (Type Variable) bezeichnet.<br />
Die formalen Typ-Parameter werden nach dem Klassennamen (bzw Interface-Namen) angegeben, <strong>in</strong> spitzen Klammern<br />
e<strong>in</strong>geschlossen und durch Kommata getrennt Klassenbezeichnung e<strong>in</strong>er generischen Klasse (bzw e<strong>in</strong>es Interfaces).<br />
Syntax :<br />
Die Namen der Typ-Parameter sollten per Konvention möglichst nur aus e<strong>in</strong>em Grossbuchstaben bestehen.<br />
Beispiele : Stack<br />
Map<br />
◇ Zur Verwendung e<strong>in</strong>er generischen Klasse (bzw e<strong>in</strong>es generischen Interfaces) müssen die formalen Typ-Parameter<br />
durch aktuelle Typ-Parameter ersetzt werden. Diese werden <strong>in</strong> der <strong>Java</strong>-Syntax als Typ-Argumente (Type Arguments)<br />
bezeichnet. (Es muss sich um Referenz-Typen handeln. E<strong>in</strong>fache Datentypen s<strong>in</strong>d nicht zulässig.)<br />
Hierdurch wird e<strong>in</strong> aus der generischen Klasse (bzw e<strong>in</strong>es Interfaces) erzeugter konkreter Typ festgelegt<br />
parameteriserter Typ<br />
Syntax :<br />
Durch jeden neuen Satz von Typ-Argumenten wird e<strong>in</strong> neuer parameterisierter Typ def<strong>in</strong>iert.<br />
E<strong>in</strong>e generische Klasse (bzw e<strong>in</strong> generisches Interface) def<strong>in</strong>iert also mehrere (i.a. beliebig viele) Typen.<br />
◇ Die Verwendung von parameterisierten Typen vere<strong>in</strong>facht die Programmierung, explizite Type-Casts s<strong>in</strong>d nicht mehr<br />
erforderlich.<br />
Der Compiler kann die fehlerhafte Verwendung parameteriserter Typen erkennen. Es wird typsicherer Code erzeugt.<br />
◇ Beispiel :<br />
Klassen-Name<br />
Klassen-Name<br />
<<br />
<<br />
Typ-Parameter<br />
,<br />
Typ-Argument<br />
// GenProgDemo15.java<br />
// Demonstration der Anwendung generischer Programmierung mittels<br />
// Typ-Parameterisierung (Generics, ab JDK 1.5)<br />
import java.util.*;<br />
public class GenProgDemo15<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Stack stk = new Stack();<br />
stk.push(new Integer(123)); // oder : stk.push(123);<br />
Integer i = stk.pop(); // expliziter Type-Cast nicht erforderlich<br />
System.out.pr<strong>in</strong>tln("Wert vom Stack : " + i);<br />
stk.push("E<strong>in</strong> Str<strong>in</strong>g"); // Compiler-Fehler<br />
}<br />
}<br />
,<br />
><br />
>
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2B3 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Parameterisierte Typen und Vererbung<br />
Generische Programierung <strong>in</strong> <strong>Java</strong> (3)<br />
◇ E<strong>in</strong>e eventuelle Ableitungsbeziehung zwischen Typ-Argumenten wird nicht auf die entsprechenden parameteri-<br />
sierten Typen übertragen (Unterschied zu Arrays !) Typ-Invarianz<br />
◇ Beispiel : Die Klasse Integer ist von der Klasse Number abgeleitet. E<strong>in</strong>e Number-Variable kann damit auch<br />
auf e<strong>in</strong> Integer-Objekt zeigen :<br />
Number num = new Integer(25);<br />
Dagegen besteht zwischen den parameterisierten Typen Stack und Stack ke<strong>in</strong>erlei<br />
Kompatibilität :<br />
Stack = new Stack() // unzulässig !!!<br />
◇ E<strong>in</strong>e der Vererbung entsprechende Kompatibilitätsbeziehung zwischen parameterisierten Datentypen wird durch<br />
die Verwendung von Wildcards und Typbegrenzungen (Type Bounds) bei den Typ-Argumenten ermöglicht<br />
• Wildcards als Typ-Argumente<br />
◇ Die Verwendung des Wildcard-Zeichens ? als Typ-Argument def<strong>in</strong>iert e<strong>in</strong>en parameterisierten Typ, zu dem alle<br />
anderen aus derselben generischen Klasse erzeugbaren Typen zuweisungs-kompatibel s<strong>in</strong>d.<br />
Dieser Wildcard-Typ wirkt als e<strong>in</strong>e Art "Basisklasse" aller anderen parameterisierten Typen derselben Klasse.<br />
◇ Beispiel : Stack stk = new Stack(); // zulässig !!!<br />
stk = new Stack(); // zulässig !!!<br />
stk = new Stack(); // zulässig !!!<br />
◇ Wildcard-Typen s<strong>in</strong>d nur e<strong>in</strong>geschränkt verwendbar.<br />
Sie eignen sich nur für Situationen, die ke<strong>in</strong>e Festlegung auf e<strong>in</strong> konkretes Typ-Argument benötigen<br />
Beispielsweise lässt sich e<strong>in</strong>e Utility-Methode zum Leeren e<strong>in</strong>es beliebigen Stacks mit e<strong>in</strong>em Parameter vom<br />
Typ Stack def<strong>in</strong>ieren :<br />
// GenProgWildcardDemo.java<br />
import java.util.*;<br />
public class GenProgWildcardDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Stack stk = new Stack();<br />
stk.push(3); stk.push(5); stk.push(7);<br />
System.out.pr<strong>in</strong>tln("Stack enthielt " + clearStack(stk) + " Elemente");<br />
}<br />
}<br />
public static <strong>in</strong>t clearStack(Stack s) // Rueckgabe Anzahl entfernter Elemente<br />
{ <strong>in</strong>t i = 0;<br />
while (!s.empty())<br />
{ s.pop();<br />
++i;<br />
}<br />
return i;<br />
}<br />
◇ Aus der Sicht des Compilers s<strong>in</strong>d die Eigenschaften e<strong>in</strong>es Wildcard-Typs bezüglich se<strong>in</strong>er Typ-Argumente völlig<br />
unbekannt. Er kann daher bezüglich der Verwendung der Typ-Argumente ke<strong>in</strong>e Überprüfungen vornehmen.<br />
Deshalb s<strong>in</strong>d sowohl Lese- als auch Schreibzugriffe, die von den Typ-Argumenten abhängen, nicht zulässig.<br />
Ausnahmen : - Da jedes Typ-Argument von Object abgeleitet se<strong>in</strong> muss, ist e<strong>in</strong> Lesen von Object-Objekten<br />
immer zulässig (z.B. können Integer-Objekte jederzeit als Object-Objekte gelesen werden)<br />
- Der Wert null kann jeder Referenz-Variablen zugewiesen werden. Daher kann null immer als<br />
e<strong>in</strong> zu jedem Typ-Argument kompatibler Wert geschrieben werden (z.B. kann auf jedem beliebigen Stack der Wert null<br />
abgelegt werden).
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 2B4 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Typbegrenzte Wildcards als Typ-Argumente<br />
Generische Programierung <strong>in</strong> <strong>Java</strong> (4)<br />
◇ Zu e<strong>in</strong>em Wildcard-Typ mit dem Typ-Argument ? s<strong>in</strong>d alle aus derselben Klasse erzeugbaren parameterisierten<br />
Typen kompatibel.<br />
Häufig wird aber e<strong>in</strong>e e<strong>in</strong>geschränkte Kompatibiltät benötigt, die auf die Berücksichtigung der zwischen den Typ-<br />
Argumenten bestehenden Ableitungsbeziehungen begrenzt ist.<br />
◇ Derartige e<strong>in</strong>geschränkte Kompatibilitäten werden durch typbegrenzte Wildcards (bounded wildcards) als Typ-<br />
Argumente realisiert.<br />
Es gibt zwei Arten der Begrenzung :<br />
▻ Wildcards mit oberer Begrenzung (Upper Type Bound)<br />
▻ Wildcards mit unterer Begrenzung (Lower Type Bound)<br />
◇ Wildcards mit oberer Begrenzung (covarianter Wildcard-Typ):<br />
Zu e<strong>in</strong>em parameterisierten Typ mit e<strong>in</strong>em derartigen Typ-Argument s<strong>in</strong>d alle Typen kompatibel deren Typ-Argument<br />
gleich der oberen Begrenzung ist oder von dieser abgeleitet ist<br />
Syntax :<br />
Beispiel : Stack
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 300 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel 3<br />
3. Elementare Programmfunktionalitäten<br />
3.1. Zugriff zu Programmparametern<br />
3.2. Standard-E<strong>in</strong>-und-Ausgabe (Konsolen-E/A)<br />
3.3. Interaktion mit dem Laufzeitsystem<br />
3.4. Exceptions<br />
3.5. Dateizugriff
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 311 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Zugriff zu Programmparametern <strong>in</strong> <strong>Java</strong><br />
• Programparameter (Kommandozeilenparameter)<br />
◇ E<strong>in</strong>em Programm können i.a. beim Aufruf Parameter übergeben werden. Programmparameter<br />
◇ Diese werden beim Aufruf aus der Kommandozeile durch Blanks getrennt an den eigentlichen Programmaufruf<br />
angehängt. Kommandozeilenparameter<br />
Bei <strong>Java</strong>-Programmen werden sie nach dem Namen der Start-Klasse angegeben.<br />
◇ Beispiel : java Echo Sie tanzte nur e<strong>in</strong>en Sommer<br />
Kommandozeilenparameter s<strong>in</strong>d : Sie tanzte nur e<strong>in</strong>en Sommer<br />
• Zugriff im Programm<br />
◇ Die Programmparameter (ohne Namen der Startklasse !) werden <strong>in</strong> e<strong>in</strong>em Str<strong>in</strong>g-Array zusammengefasst.<br />
E<strong>in</strong>e Referenz auf dieses Array wird der ma<strong>in</strong>()-Methode der Startklasse als Parameter übergeben.<br />
◇ Die ma<strong>in</strong>()-Methode der Startklasse muß daher mit e<strong>in</strong>em Parameter (Argument) vom Typ Str<strong>in</strong>g[] def<strong>in</strong>iert<br />
werden :<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
// ...<br />
}<br />
◇ Innerhalb der ma<strong>in</strong>()-Methode stehen damit die Programmparameter als Komponenten des Str<strong>in</strong>g-Arrays<br />
args zur Verfügung.<br />
◇ Die Anzahl der Programmparameter (= Länge des Str<strong>in</strong>g-Arrays) ist ermittelbar mittels args.length.<br />
• Beispiel :<br />
// Echo.java<br />
class Echo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
for (<strong>in</strong>t i=0; ijava Echo Sie tanzte nur e<strong>in</strong>en Sommer<br />
Parameter 0 : Sie<br />
Parameter 1 : tanzte<br />
Parameter 2 : nur<br />
Parameter 3 : e<strong>in</strong>en<br />
Parameter 4 : Sommer<br />
E:\java\fhm\ee\vorl>
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 321 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Grundsätzliches zum I/O-Model von <strong>Java</strong><br />
Standard-E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong> (1)<br />
◇ E<strong>in</strong>e Programm-E<strong>in</strong>- und Ausgabe f<strong>in</strong>det üblicherweise über Dateien und/oder Geräte statt.<br />
◇ <strong>Java</strong> betrachtet sowohl Geräte als auch Dateien grundsätzlich als sequentielle Folge von Bytes (Byte-Stream).<br />
Da <strong>Java</strong> Zeichen und Str<strong>in</strong>gs im Unicode darstellt, bietet die Sprache auch die Möglichkeit Textdateien/Text-Geräte<br />
als sequentielle Folge von Unicode-Zeichen (Unicode-Stream) zu <strong>in</strong>terpretieren.<br />
◇ Programm<strong>in</strong>tern wird e<strong>in</strong>e Datei bzw e<strong>in</strong> Gerät durch e<strong>in</strong> Objekt e<strong>in</strong>er Stream-Klasse repräsentiert.<br />
◇ Es gibt zahlreiche verschiedene Stream-Klassen, die jeweils unterschiedliche Eigenschaften modellieren.<br />
Alle Stream-Klassen s<strong>in</strong>d im Package java.io enthalten.<br />
◇ Vier abstrakte Klassen s<strong>in</strong>d Basisklassen aller übrigen Stream-Klassen :<br />
▻ InputStream<br />
Basisklasse für Klassen zum byteweisen Lesen (Lesen von Byte-Streams)<br />
▻ Reader<br />
Basisklasse für Klassen zum zeichenweisen Lesen (Lesen von Unicode-Zeichen-Streams)<br />
▻ OutputStream<br />
Basisklasse für Klassen zum byteweisen Schreiben (Schreiben <strong>in</strong> Byte-Streams)<br />
▻ Writer<br />
Basisklasse für Klasse zum zeichenweisen Schreiben (Schreiben <strong>in</strong> Unicode-Zeichen-Streams)<br />
Diese Klassen def<strong>in</strong>ieren jeweils e<strong>in</strong> generelles Interface zur Verwendung der Objekte der entsprechenden abgeleiteten<br />
Klassen.<br />
◇ Konverter-Klassen (Brücken-Klassen) erlauben e<strong>in</strong>en Übergang zwischen Byte-Streams und Unicode-Zeichen-<br />
Streams :<br />
▻ InputStreamReader (abgeleitet von Reader)<br />
Klasse zum zeichenweisen Lesen aus Byte-Streams<br />
▻ OutputStreamWriter (abgeleitet von Writer)<br />
Klasse zum zeichenweisen Schreiben <strong>in</strong> Byte-Streams<br />
• Standard-E<strong>in</strong>- und Ausgabe-Objekte<br />
◇ Für die Standard-E<strong>in</strong>gabe, die Standard-Ausgabe und die Standard-Fehlerausgabe werden für jedes Programm<br />
automatisch Stream-Objekte angelegt, d.h. die entsprechenden Streams (üblicherweise Tastatur und Bildschirm des<br />
Konsolengeräts) s<strong>in</strong>d implizit geöffnet. Aus historischen Gründen handelt es sich hierbei um Byte-Stream-Objekte.<br />
◇ Referenzen auf diese Stream-Objekte stehen als öffentliche statische Datenkomponenten der – nicht <strong>in</strong>stanzierbaren –<br />
Klasse System (im Package java.lang) zur Verfügung :<br />
▻ public static f<strong>in</strong>al InputStream <strong>in</strong><br />
Standard-E<strong>in</strong>gabe-Objekt<br />
▻ public static f<strong>in</strong>al Pr<strong>in</strong>tStream out<br />
Standard-Ausgabe-Objekt<br />
▻ public static f<strong>in</strong>al Pr<strong>in</strong>tStream err<br />
Standard-Fehlerausgabe-Objekt<br />
Die Klasse Pr<strong>in</strong>tStream ist e<strong>in</strong>e von OutputStream – <strong>in</strong>direkt – abgeleitete Klasse.<br />
Sie ermöglicht das Schreiben von Werten der e<strong>in</strong>fachen Datentypen und von Objekten beliebiger Klassen (nach<br />
Umwandlung <strong>in</strong> e<strong>in</strong>e Str<strong>in</strong>g-Repräsentation) sowie direkt von Str<strong>in</strong>gs <strong>in</strong> e<strong>in</strong>en Byte-Stream.<br />
Hierfür stellt sie die mehrfach überladenen Funktionen pr<strong>in</strong>t() und pr<strong>in</strong>tln() (nicht explizit formatierbare<br />
Ausgabe) sowie die Methode pr<strong>in</strong>tf() (formatierte Ausgabe) zur Verfügung.<br />
◇ Ab dem JDK 6.0 kann als Alternative für den Zugriff zum Konsolengerät auch e<strong>in</strong> vordef<strong>in</strong>iertes Objekt der Klasse<br />
Console e<strong>in</strong>gesetzt werden.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 322 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Standard-E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong> (2)<br />
• Schreiben <strong>in</strong> die Standard-Ausgabe und Standard-Fehlerausgabe<br />
◇ Mittels der für die Standard-Stream-Objekte<br />
▻ System.out (Standard-Ausgabe, Klasse Pr<strong>in</strong>tStream)<br />
▻ System.err (Standard-Fehlerausgabe, Klasse Pr<strong>in</strong>tStream)<br />
aufgerufenen Methoden<br />
▻ public void pr<strong>in</strong>t(...)<br />
▻ public void pr<strong>in</strong>tln(...)<br />
▻ public Pr<strong>in</strong>tStream pr<strong>in</strong>tf(Str<strong>in</strong>g form, Object... args) (ab dem JDK 5.0)<br />
▻ public Pr<strong>in</strong>tStream format(Str<strong>in</strong>g form, Object... args) (ab dem JDK 5.0)<br />
◇ Die Methoden pr<strong>in</strong>t() und pr<strong>in</strong>tln() haben jeweils e<strong>in</strong>en Parameter und ermöglichen die Ausgabe<br />
- von boolean-, char-, double-, float-, <strong>in</strong>t- und long-Werten<br />
- von char-Arrays<br />
- von Str<strong>in</strong>gs (Objekte der Klasse Str<strong>in</strong>g)<br />
- sowie der Str<strong>in</strong>g-Repräsentation (Methode toStr<strong>in</strong>g()) von Objekten beliebiger Klassen<br />
◇ Die Methode pr<strong>in</strong>tln() ergänzt die Ausgabe um e<strong>in</strong> Zeilenendezeichen.<br />
Sie lässt sich auch ohne Parameter aufrufen. In diesem Fall bewirkt sie lediglich e<strong>in</strong>en Übergang <strong>in</strong> e<strong>in</strong>e neue Zeile.<br />
◇ Beispiel :<br />
class StdOutDemo1<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ boolean b = true;<br />
char c = 'Z';<br />
<strong>in</strong>t i = 399127;<br />
long l = 124L;<br />
float f = 2.25E-2f;<br />
double d = 0.0/0.0;<br />
Str<strong>in</strong>g s = "Hallo !";<br />
StdOutDemo1 sod = new StdOutDemo1();<br />
System.out.pr<strong>in</strong>t(b);<br />
System.out.pr<strong>in</strong>tln();<br />
System.out.pr<strong>in</strong>tln(c);<br />
System.out.pr<strong>in</strong>tln(i);<br />
System.out.pr<strong>in</strong>tln(l);<br />
System.out.pr<strong>in</strong>tln(f);<br />
System.out.pr<strong>in</strong>tln(d);<br />
System.out.pr<strong>in</strong>tln(s);<br />
System.out.pr<strong>in</strong>tln(sod);<br />
}<br />
}<br />
◇ Die Anwendung der Str<strong>in</strong>g-Konkatenation <strong>in</strong> Verb<strong>in</strong>dung mit der automatischen Umwandlung von beliebigen<br />
Datenwerten und Objekten <strong>in</strong> e<strong>in</strong>e Str<strong>in</strong>g-Repräsentation bei ihrem Auftritt <strong>in</strong> Konkatenations-Aus drücken (Methode<br />
toStr<strong>in</strong>g()) erlaubt die Ausgabe mehrerer Werte/Objekte mit e<strong>in</strong>em Methodenaufruf.<br />
Achtung : Der +-Operator (Konkatenation, Addition) ist l<strong>in</strong>ks-rechts-assoziativ.<br />
Damit bei mehrfacher Konkatenation tatsächlich der richtige Gesamtstr<strong>in</strong>g entsteht, muss bei der ersten (am weitesten<br />
l<strong>in</strong>ks stehenden) Verknüpfungsoperation wenigstens e<strong>in</strong> Str<strong>in</strong>g beteiligt se<strong>in</strong>.<br />
Beispiel :<br />
class StdOutDemo2<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ System.out.pr<strong>in</strong>tln(1 + '+' + 1 + " ergibt " + 2);<br />
System.out.pr<strong>in</strong>tln(1 + "+" + 1 + " ergibt " + 2);<br />
}<br />
}<br />
Ausgabe :<br />
true<br />
Z<br />
399127<br />
124<br />
0.0225<br />
NaN<br />
Hallo !<br />
StdOutDemo1@eee36c<br />
Ausgabe :<br />
45 ergibt 2<br />
1+1 ergibt 2
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 323 – 01 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Formatierte Ausgabe (ab dem JDK 5.0)<br />
◇ Mittels der Pr<strong>in</strong>tStream-Methoden<br />
Standard-E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong> (3 - 1)<br />
public Pr<strong>in</strong>tStream pr<strong>in</strong>tf(Str<strong>in</strong>g form, Object... args);<br />
public Pr<strong>in</strong>tStream format(Str<strong>in</strong>g form, Object... args);<br />
Rückgabewert bei beiden Methoden : aktuelles Pr<strong>in</strong>tStream-Objekt<br />
◇ Beide Methoden s<strong>in</strong>d <strong>in</strong> der Wirkung identisch. Sie ermöglichen e<strong>in</strong>e C-ähnliche formatierte Ausgabe<br />
◇ Der erste Parameter form ist der Format-Str<strong>in</strong>g. Er enthält – analog zum Format-Str<strong>in</strong>g der C-Funktion<br />
pr<strong>in</strong>tf() – die e<strong>in</strong>zelnen Formatangaben (format specifier) für die auszugebenden Werte/Objekte.<br />
Durch die Formatangaben wird auch der Typ bzw die Darstellungsart der Ausgabe-Werte festgelegt<br />
Zusätzlich kann der Format-Str<strong>in</strong>g weiteren Text enthalten, der direkt ausgegeben wird.<br />
◇ Die zweite Parameter-Angabe Object... args bedeutet, dass e<strong>in</strong>e beliebige Anzahl (auch ke<strong>in</strong>e) weiterer<br />
Parameter beliebigen Referenz-Typs folgen darf.<br />
Diese Parameter (Argumente) legen die Werte fest, die entsprechend des jeweils spezifizierten Formats auszugeben s<strong>in</strong>d.<br />
Für jede Formatangabe muss e<strong>in</strong> passendes Argument übergeben werden. Die Typen dieser Argumente müssen zu den<br />
entsprechenden Angaben im Format-Str<strong>in</strong>g passen. Überflüssige Argumente werden ignoriert<br />
Als Parameter können auch Werte e<strong>in</strong>facher Datentypen auftreten, da sie mittels Autobox<strong>in</strong>g automatisch <strong>in</strong> Objekte der<br />
zugehörigen Wrapper-Klassen umgewandelt werden.<br />
◇ Syntax der Formatangaben (vere<strong>in</strong>facht) :<br />
% [flags][width][.precision]conversion<br />
▻ conversion (Konvertierungszeichen)<br />
legt die Formatierungsart und/oder den Typ der Ausgabe fest und schließt e<strong>in</strong>e Formatangabe ab<br />
Die wichtigsten Konvertierungszeichen s<strong>in</strong>d :<br />
b oder B logischer Wert<br />
d ganzzahliger Wert <strong>in</strong> Dezimaldarstellung<br />
o ganzzahliger Wert <strong>in</strong> Oktaldarstellung<br />
x oder X ganzzahliger Wert <strong>in</strong> Sedezimaldarstellung<br />
c oder C Unicode-Zeichen<br />
e oder E Gleitpunkt-Wert <strong>in</strong> Exponentialdarstellung<br />
f Gleitpunkt-Wert <strong>in</strong> Dezimalbruchdarstellung<br />
g oder G Gleitpunkt-Wert <strong>in</strong> Dezimalbruchdarstellung oder Exponentialdarstellung<br />
(abhängig von Wert und Genauigkeit)<br />
s oder S Str<strong>in</strong>g (der Str<strong>in</strong>g, der durch die jeweilige Methode toStr<strong>in</strong>g() erzeugt wird)<br />
n Zeilenendezeichen<br />
Bei e<strong>in</strong>em Großbuchstaben als Konvertierungszeichen werden alle Buchstaben als Großbuchstaben ausgegeben<br />
▻ flags (Steuerflags)<br />
modifizieren das Ausgabeformat, sie können gegebenenfalls mite<strong>in</strong>ander komb<strong>in</strong>iert werden<br />
Die wichtigsten Steuerflags s<strong>in</strong>d :<br />
- l<strong>in</strong>ksbündige Ausgabe<br />
+ auch positive Werte werden mit Vorzeichen ausgegeben (nur für Zahlen anwendbar)<br />
0 Ausgabe führender Nullen (nur für Zahlen anwendbar)<br />
' ' (Blank) Ausgabe positiver Werte mit führendem Blank (nur für Zahlen anwendbar)<br />
▻ width (Ausgabefeldbreite)<br />
legt die m<strong>in</strong>imale Ausgabefeldbreite fest<br />
▻ precision (Genauigkeit)<br />
legt i.a. die maximale Ausgabefeldbreite fest, bei Gleitpunktzahlen jedoch die Anzahl der Nachpunktstellen<br />
(Ausnahme : beim Konvertierungszeichen g bzw G wird die Gesamtzahl der Ziffern festgelegt),<br />
bei Str<strong>in</strong>gs : Anzahl der auszugebenden Zeichen des Str<strong>in</strong>gs<br />
◇ Nichtzulässige Zeichen <strong>in</strong> e<strong>in</strong>er Formatangabe sowie fehlende oder zu e<strong>in</strong>er Formatangabe nicht-kompatible Argu-<br />
mente führen zum Werfen e<strong>in</strong>er IllegalFormatException.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 323 – 02 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Standard-E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong> (3 - 2)<br />
• Ergänzende Anmerkungen zur formatierten Ausgabe (ab dem JDK 5.0)<br />
◇ Es existieren noch weitere Möglichkeiten der Formatierung (<strong>in</strong>sbesondere auch für Datums- und Zeitdarstellungen).<br />
Genauere Informationen können der API-Dokumentation zur Klasse Formatter (Package java.util)<br />
entnommen werden.<br />
◇ Zur Erzeugung von formatierten Ausgaben kann auch die Klasse Formatter e<strong>in</strong>gesetzt werden :<br />
Mit Objekten dieser Klasse ist es u.a. möglich<br />
▻ formatierte Ausgaben direkt <strong>in</strong> Dateien oder OutputStream- sowie Pr<strong>in</strong>tStream-Objekten vorzunehmen<br />
▻ formatierte Str<strong>in</strong>gs zu erzeugen (als Objekte der Klassen Str<strong>in</strong>gBuffer oder Str<strong>in</strong>gBuilder).<br />
Diese Str<strong>in</strong>gs können dann explizit ausgegeben (pr<strong>in</strong>t() oder pr<strong>in</strong>tln()) bzw <strong>in</strong> Dateien geschrieben<br />
werden.<br />
• Demonstrationsprogramm zur formatierten Ausgabe :<br />
// FormOutpDemo1.java<br />
// Demonstrationsprogramm zur formatierten Ausgabe<br />
public class FormOutpDemo1<br />
{<br />
void show()<br />
{ <strong>in</strong>t anz = 10;<br />
double summe = 99.98765;<br />
float anteil = 0.00005432f;<br />
Str<strong>in</strong>g type = "Airbus A-380";<br />
System.out.pr<strong>in</strong>tln("0123456789012345678901234567890123456789");<br />
System.out.pr<strong>in</strong>tf("Anzahl : %5d Summe : %8.3e\n", anz, summe);<br />
System.out.format("Anzahl : %5d Summe : %8.3e\n", anz, summe);<br />
System.out.pr<strong>in</strong>tf("Anzahl : %-5d Summe : %8.3f\n", anz, summe);<br />
System.out.pr<strong>in</strong>tf("Anzahl : %0+5d Summe : %08.3f\n", anz, summe);<br />
System.out.pr<strong>in</strong>tf("Anteil : % .4g\n", anteil);<br />
System.out.pr<strong>in</strong>tf("Anteil : %.4E\n", anteil);<br />
System.out.pr<strong>in</strong>tf("Anteil : %.4f\n", anteil);<br />
System.out.pr<strong>in</strong>tf("Typ : %s\n", type);<br />
System.out.pr<strong>in</strong>tf("Typ : %15s\n", type);<br />
System.out.pr<strong>in</strong>tf("Typ : %5s\n", type);<br />
System.out.pr<strong>in</strong>tf("Typ : %5.6S\n", type);<br />
System.out.pr<strong>in</strong>tf("Typ : %8.6s\n", type);<br />
System.out.pr<strong>in</strong>tf("%B\n", true);<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ FormOutpDemo1 demo = new FormOutpDemo1();<br />
demo.show();<br />
}<br />
Ausgabe des Programms :<br />
0123456789012345678901234567890123456789<br />
Anzahl : 10 Summe : 9.999e+01<br />
Anzahl : 10 Summe : 9.999e+01<br />
Anzahl : 10 Summe : 99,988<br />
Anzahl : +0010 Summe : 0099,988<br />
Anteil : 5.432e-05<br />
Anteil : 5.4320E-05<br />
Anteil : 0,0001<br />
Typ : Airbus A-380<br />
Typ : Airbus A-380<br />
Typ : Airbus A-380<br />
Typ : AIRBUS<br />
Typ : Airbus<br />
TRUE
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 324 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Lesen aus der Standard-E<strong>in</strong>gabe<br />
Standard-E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong> (4)<br />
◇ Das für die Standard-E<strong>in</strong>gabe def<strong>in</strong>ierte Stream-Objekt System.<strong>in</strong> steht als Instanz der Klasse InputStream<br />
zur Verfügung.<br />
Diese Klasse besitzt zum E<strong>in</strong>lesen lediglich die mehrfach überladene Methode read(), mit der nur e<strong>in</strong>zelne Bytes<br />
oder e<strong>in</strong>e Gruppe von Bytes (Byte-Array) e<strong>in</strong>gelesen werden können.<br />
◇ Üblicherweise soll von der Standard-E<strong>in</strong>gabe aber Text e<strong>in</strong>gelesen werden, der vom Programm entweder als Wert<br />
e<strong>in</strong>es e<strong>in</strong>fachen Datentyps oder direkt als Str<strong>in</strong>g <strong>in</strong>terpretiert und verwendet werden soll.<br />
D.h. also, es müssen Zeichenfolgen (Datentyp char) und nicht Bytefolgen (Datentyp Byte) e<strong>in</strong>gelesen werden.<br />
◇ Der über System.<strong>in</strong> erhältliche Byte-Stream muß also <strong>in</strong> e<strong>in</strong>en Unicode-Stream umgewandelt werden.<br />
Diese erfolgt mittels e<strong>in</strong>es Objekts der Klasse InputStreamReader.<br />
Dem Konstruktor zur Erzeugung dieses Objekts ist das zugrundeliegende InputStream-Objekt, hier also<br />
System.<strong>in</strong> als Parameter zu übergeben.<br />
Die Klasse InputStreamReader erlaubt mittels der überladenen Methode read() das E<strong>in</strong>lesen von E<strong>in</strong>zel-<br />
zeichen bzw Zeichen-Arrays.<br />
E<strong>in</strong>lesen von E<strong>in</strong>zelzeichen :<br />
public <strong>in</strong>t read() throws IOException<br />
Funktionswert : gelesenes Zeichen bzw –1 bei E<strong>in</strong>gabeende<br />
◇ Um Str<strong>in</strong>gs e<strong>in</strong>lesen zu können, wird e<strong>in</strong> BufferedReader-Objekt benötigt. Dieses lässt sich unter Verwendung<br />
des InputStreamReader-Objekts, das dem Konstruktor als Parameter zu übergeben ist, erzeugen (Der Kon-<br />
struktor der Klasse BufferedReader benötigt e<strong>in</strong> Reader-Objekt als Parameter, die Klasse<br />
InputStreamReader ist von Reader abgeleitet).<br />
Die Klasse BufferedReader stellt neben der überladenen Methode read() zum E<strong>in</strong>lesen von E<strong>in</strong>zelzeichen<br />
und Zeichen-Arrays e<strong>in</strong>e Methode zum zeilenweisen Lesen zur Verfügung :<br />
public Str<strong>in</strong>g readL<strong>in</strong>e() throws IOException<br />
Funktionswert : e<strong>in</strong>gelesene Zeile als Str<strong>in</strong>g-Objekt (ohne Zeilenende-Zeichen) bzw null wenn das E<strong>in</strong>gabe-<br />
Ende (EOF, Dateiende) erreicht ist.<br />
Bei der Anwendung dieser Methode (wie auch aller anderen Lese-Methoden) ist zu berücksichtigen, dass bei Auftritt<br />
e<strong>in</strong>es I/O-Fehlers, e<strong>in</strong>e Exception vom Typ IOException geworfen wird.<br />
Diese ist entweder <strong>in</strong> der aufrufenden Funktion zu fangen oder von dieser weiterzuwerfen.<br />
◇ Darstellung als Klassendiagramm :<br />
◇ Beispiel :<br />
BufferedReader<br />
+read():<strong>in</strong>t<br />
+readL<strong>in</strong>e():Str<strong>in</strong>g<br />
// EchoL<strong>in</strong>es.java<br />
import java.io.*;<br />
InputStreamReader<br />
+read():<strong>in</strong>t<br />
InputStream<br />
+read():<strong>in</strong>t<br />
class EchoL<strong>in</strong>es<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{<br />
BufferedReader std<strong>in</strong> = new BufferedReader(<br />
new InputStreamReader(System.<strong>in</strong>));<br />
Str<strong>in</strong>g l<strong>in</strong>e;<br />
while ((l<strong>in</strong>e=std<strong>in</strong>.readL<strong>in</strong>e()) != null) System.out.pr<strong>in</strong>tln(l<strong>in</strong>e);<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 325 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Lesen aus der Standard-E<strong>in</strong>gabe, Forts.<br />
Standard-E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong> (5)<br />
◇ Zum E<strong>in</strong>lesen von Werten der e<strong>in</strong>fachen Datentypen muß der e<strong>in</strong>gelesene Str<strong>in</strong>g entsprechend dem Datentyp <strong>in</strong>ter-<br />
pretiert und <strong>in</strong> die <strong>in</strong>terne Wertedarstellung umgewandelt werden.<br />
Hierfür stehen entsprechende statische Methoden der jeweiligen Wrapper-Klassen zur Verfügung :<br />
▻ Klasse Byte : public static byte parseByte(Str<strong>in</strong>g str)<br />
throws NumberFormatException;<br />
▻ Klasse Short : public static short parseShort(Str<strong>in</strong>g str)<br />
throws NumberFormatException;<br />
▻ Klasse Integer : public static <strong>in</strong>t parseInt(Str<strong>in</strong>g str)<br />
throws NumberFormatException;<br />
▻ Klasse Long : public static long parseLong(Str<strong>in</strong>g str)<br />
throws NumberFormatException;<br />
▻ Klasse Float : public static float parseFloat(Str<strong>in</strong>g str)<br />
throws NumberFormatException;<br />
▻ Klasse Double : public static double parseDouble(Str<strong>in</strong>g str)<br />
throws NumberFormatException;<br />
Diese Methoden liefern die <strong>in</strong>terne Darstellung des durch den Parameter str repräsentierten Werts des jeweiligen<br />
Typs als Funktionswert zurück. Sie erzeugen e<strong>in</strong>e Exception vom Typ NumberFormatException, wenn str<br />
ke<strong>in</strong>en entsprechenden Zahlenwert darstellt.<br />
◇ Zur Umwandlung e<strong>in</strong>es Str<strong>in</strong>gs <strong>in</strong> e<strong>in</strong>en boolean-Wert müssen zwei Methoden der Wrapper-Klasse Boolean<br />
e<strong>in</strong>gesetzt werden :<br />
▻ Klasse Boolean : public static Boolean valueOf(Str<strong>in</strong>g str);<br />
Diese Methode erzeugt e<strong>in</strong> Boolean-Objekt, das den Wert true repräsentiert, wenn der Parameter str<br />
gleich dem Str<strong>in</strong>g "true" ist , wobei Groß-/Kle<strong>in</strong>schreibung ignoriert wird ("True" oder "TRUE" z.B.<br />
führen ebenfalls zum Wert true).<br />
Für jeden anderen Wert von str repräsentiert das erzeugte Boolean-Objekt den Wert false.<br />
▻ Klasse Boolean : public boolean booleanValue();<br />
◇ Beispiel :<br />
Diese Methode gibt den durch e<strong>in</strong> Boolean-Objekt repräsentierten boolean-Wert zurück.<br />
import java.io.*;<br />
class StdInpDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{ <strong>in</strong>t a, b;<br />
BufferedReader std<strong>in</strong> = new BufferedReader(<br />
new InputStreamReader(System.<strong>in</strong>));<br />
System.out.pr<strong>in</strong>t("Wert von a ? ");<br />
a = Integer.parseInt(std<strong>in</strong>.readL<strong>in</strong>e());<br />
System.out.pr<strong>in</strong>t("Wert von b ? ");<br />
b = Integer.parseInt(std<strong>in</strong>.readL<strong>in</strong>e());<br />
System.out.pr<strong>in</strong>tln("a+b = " + (a+b));<br />
System.out.pr<strong>in</strong>t("Boolean-Wert ? ");<br />
Str<strong>in</strong>g s = std<strong>in</strong>.readL<strong>in</strong>e();<br />
boolean bw = Boolean.valueOf(s).booleanValue();<br />
System.out.pr<strong>in</strong>tln("E<strong>in</strong>gabe war : " + bw);<br />
}<br />
}<br />
Beispiel für E<strong>in</strong>- und<br />
Ausgabe des Programms :<br />
Wert von a ? 213<br />
Wert von b ? 421<br />
a+b = 634<br />
Boolean-Wert ? True<br />
E<strong>in</strong>gabe war : true<br />
◇ E<strong>in</strong>e alternative, flexiblere und e<strong>in</strong>fachere Möglichkeit zum E<strong>in</strong>lesen von Werten e<strong>in</strong>facher Datentypen bietet die<br />
mit dem JDK 5.0 e<strong>in</strong>geführte Klasse Scanner
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 326 – 01 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es zur Klasse Scanner<br />
Die Klasse Scanner <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Bestandteil des Packages java.util, ab dem JDK 5.0 vorhanden<br />
◇ Objekte der Klasse Scanner dienen zum Zergliedern und Interpretieren von Zeichenfolgen.<br />
◇ Die von Scanner-Objekten bearbeitbaren Zeichenfolgen können aus unterschiedlichen E<strong>in</strong>gabe-Quellen stammen<br />
(Dateien, sonstige E<strong>in</strong>gabe-Streams wie z.B. die Standard-E<strong>in</strong>gabe, Str<strong>in</strong>gs).<br />
Die jeweilige Quelle muss beim Erzeugen e<strong>in</strong>es Scanner-Objekts festgelegt werden.<br />
◇ Scanner-Objekte zerlegen ihre E<strong>in</strong>gabe-Zeichenfolge <strong>in</strong> Teil-Abschnitte (token). Die Zeichen(-muster), die als<br />
Trennzeichen zwischen den Abschnitten <strong>in</strong>terpretiert werden (delimiter pattern), lassen sich konfigurieren.<br />
Defaultmässig werden Whitespace-Character verwendet.<br />
◇ Die e<strong>in</strong>zelnen Teil-Abschnitte stehen als Str<strong>in</strong>gs zur Verfügung und können als Werte e<strong>in</strong>es e<strong>in</strong>fachen Datentyps<br />
<strong>in</strong>terpretiert und <strong>in</strong> die dem jeweiligen Typ entsprechende <strong>in</strong>terne Darstellung umgewandelt werden.<br />
◇ Damit lassen sich Scanner-Objekte sehr elegant zum E<strong>in</strong>lesen von Werten der e<strong>in</strong>fachen Datentypen aus der<br />
Standard-E<strong>in</strong>gabe e<strong>in</strong>setzen, <strong>in</strong>sbesondere auch dann, wenn <strong>in</strong> e<strong>in</strong>er E<strong>in</strong>gabezeile mehrere e<strong>in</strong>zulesende Werte<br />
enthalten s<strong>in</strong>d.<br />
• Konstruktoren der Klasse Scanner (Auswahl)<br />
public Scanner(File source) Erzeugung e<strong>in</strong>es Scanner-Objekts, dessen E<strong>in</strong>gabe-Quelle die<br />
durch source spezifizierte Datei ist<br />
public Scanner(Readable source) Erzeugung e<strong>in</strong>es Scanner-Objekts, dessen E<strong>in</strong>gabe-Quelle das<br />
durch source spezifizierte Objekt ist. Dieses Objekt muss das<br />
Interface Readable implementieren<br />
public Scanner(InputStream source) Erzeugung e<strong>in</strong>es Scanner-Objekts, dessen E<strong>in</strong>gabe-Quelle das<br />
durch source spezifizierte InputStream-Objekt ist<br />
public Scanner(Str<strong>in</strong>g source) Erzeugung e<strong>in</strong>es Scanner-Objekts, dessen E<strong>in</strong>gabe-Quelle der<br />
durch source spezifizierte Str<strong>in</strong>g ist.<br />
• Memberfunktionen der Klasse Scanner (Auswahl)<br />
public Str<strong>in</strong>g nextL<strong>in</strong>e() Rückgabe des Rests der aktuellen E<strong>in</strong>gabe-Zeile<br />
public boolean hasNextL<strong>in</strong>e() Überprüfung, ob e<strong>in</strong>e weitere E<strong>in</strong>gabe-Zeile vorhanden ist, wenn ja true<br />
public Str<strong>in</strong>g next() Rückgabe des nächsten Teil-Abschnitts (token) der E<strong>in</strong>gabe-Zeichenfolge<br />
public boolean hasNext() Überprüfung ob e<strong>in</strong> weiterer Teil-Abschnitt vorhanden ist, wenn ja true<br />
public byte nextByte()<br />
public short nextShort() Interpretation des nächsten Teil-Abschnitts der E<strong>in</strong>gabe-Zeichenfolge als<br />
Wert des jeweiligen Typs und Rückgabe der <strong>in</strong>ternen Darstellung dieses<br />
public <strong>in</strong>t nextInt() Wertes<br />
Jede der Funktionen wirft e<strong>in</strong>e Exception vom Typ<br />
public long nextLong() InputMismatchException,<br />
wenn der Teil-Abschnitt sich nicht als Wert des jeweiligen Typs <strong>in</strong>terpretieren<br />
public float nextFloat() lässt (boolean-Werten können mit Gross- und/oder Kle<strong>in</strong>buchstaben darge-<br />
stellt werden)<br />
public double nextDouble()<br />
public boolean nextBoolean()
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 326 – 02 – TH – 01<br />
------------------------------------------------------------------------------------<br />
• Demonstrationsbeispiele zur Klasse Scanner<br />
◇ Programm EchoL<strong>in</strong>esScanDemo<br />
// EchoL<strong>in</strong>esScanDemo.java<br />
◇ Programm StdInpScanDemo<br />
Die Klasse Scanner <strong>in</strong> <strong>Java</strong> (2)<br />
// Echo der von der Standard-E<strong>in</strong>gabe e<strong>in</strong>gelesenen Zeilen <strong>in</strong> die Standard-Ausgabe<br />
// Verwendung der Klase Scanner<br />
import java.util.*;<br />
public class EchoL<strong>in</strong>esScanDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Scanner scan = new Scanner(System.<strong>in</strong>);<br />
while (scan.hasNextL<strong>in</strong>e())<br />
System.out.pr<strong>in</strong>tln(scan.nextL<strong>in</strong>e());<br />
}<br />
}<br />
// StdInpScanDemo.java<br />
// Demonstrationsprogramm zum E<strong>in</strong>lesen von der Standard-E<strong>in</strong>gabe<br />
// Verwendung der Klasse Scanner<br />
import java.util.*;<br />
public class StdInpScanDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
<strong>in</strong>t a, b;<br />
Scanner scan = new Scanner(System.<strong>in</strong>);<br />
System.out.pr<strong>in</strong>t("Zwei Integer-Werte a und b ? ");<br />
a = scan.nextInt();<br />
b = scan.nextInt();<br />
System.out.pr<strong>in</strong>tln("a+b = " + (a + b));<br />
System.out.pr<strong>in</strong>t("Boolean-Wert ? ");<br />
boolean bw = scan.nextBoolean();<br />
System.out.pr<strong>in</strong>tln("E<strong>in</strong>gabe war : " + bw);<br />
}<br />
}<br />
◇ Beispiel für die E<strong>in</strong>- und Ausgabe des Programms StdInpScanDemo<br />
Zwei Integer-Werte a und b ? 12 25<br />
a+b = 37<br />
Boolean-Wert ? FalsE<br />
E<strong>in</strong>gabe war : false
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 327 – 01 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es zur Klasse Console<br />
Die Klasse Console <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Bestandteil des Packages java.io, ab dem JDK 6.0 vorhanden<br />
◇ Die Klasse stellt Methoden zum Zugriff zum Konsolengerät zur Verfügung.<br />
E<strong>in</strong> Objekt dieser Klasse bildet e<strong>in</strong>e – allerd<strong>in</strong>gs nicht immer vorhandene – Alternative zur Verwendung der Standard-<br />
E<strong>in</strong>-/Ausgabe-Stream-Objekte.<br />
◇ Die Klasse verfügt über ke<strong>in</strong>en öffentlichen Konstruktor. Sie kann also nicht explizit <strong>in</strong>stanziert werden. Vielmehr<br />
erfolgt e<strong>in</strong>e implizite Instanzierung als S<strong>in</strong>gleton durch die JVM, falls mit dieser e<strong>in</strong> Konsolengerät verbunden ist.<br />
Dieses ist u.a. immer dann der Fall, wenn die JVM aus e<strong>in</strong>er Kommandozeile heraus ohne Umleitung der Standard-E<strong>in</strong>und<br />
Ausgabe gestartet wird. Das Konsolengerät wird dann typischerweise durch die Tastatur (Standard-E<strong>in</strong>gabe) und<br />
den Bildschirm (Standard-Ausgabe) gebildet.<br />
Wenn die JVM dagegen aus e<strong>in</strong>em anderen Prozess (z.B. H<strong>in</strong>tergrundprozess oder IDE) heraus gestartet wird, ist mit ihr<br />
i.a. ke<strong>in</strong> Konsolengerät verbunden.<br />
◇ Das gegebenenfalls vorhandene e<strong>in</strong>zige Objekt der Klasse Console kann mittels der statischen Methode der Klasse<br />
System<br />
public static Console console()<br />
ermittelt werden.<br />
Falls ke<strong>in</strong> Console-Objekt existiert, liefert die Methode null zurück.<br />
◇ Die Klasse Console stellt im wesentlichen die folgenden Funktionalitäten zur Verfügung :<br />
▻ Formatierte Ausgabe<br />
▻ zeilenweises E<strong>in</strong>lesen<br />
▻ E<strong>in</strong>lesen von Passwörtern (mit ausgeschalteter Echo-Ausgabe)<br />
▻ Ermittlung der vom Console-Objekt verwendeten Stream-Objekte für die Aus- bzw E<strong>in</strong>gabe.<br />
Bei diesen Objekten handelt es sich um Zeichen-Stream-Objekte.<br />
Über sie bestehen weitere Möglichkeiten zur Aus- bzw E<strong>in</strong>gabe.<br />
Anmerkung : Die Standard-Stream-Objekten s<strong>in</strong>d dagegen Byte-Stream-Objekte.<br />
◇ Die Schreib- und Lese-Methoden der Klasse s<strong>in</strong>d synchronisiert, d.h. sie s<strong>in</strong>d für den E<strong>in</strong>satz <strong>in</strong> Multi-Thread-<br />
anwendungen geeignet.<br />
◇ Die Lese-Methoden geben als Funktionswert null zurück, wenn das Ende des Konsolen-E<strong>in</strong>gabe-Streams erreicht<br />
ist (E<strong>in</strong>gabe von Ctrl-Z unter W<strong>in</strong>dows bzw Ctrl-D unter L<strong>in</strong>ux/Unix).<br />
Wenn anschliessend weitere Zeichen e<strong>in</strong>gegeben werden, können sie mit weiteren Lese-Operationen e<strong>in</strong>gelesen weden.<br />
• Memberfunktionen der Klasse Console zur Ermittlung der E/A-Stream-Objekte<br />
◇<br />
◇<br />
public Reader reader() Ermittlung des mit der Konsole verknüpften E<strong>in</strong>gabe-Stream-Objekts.<br />
(Objekt der Klasse Reader) Funktionswert<br />
Mittels der von der Klasse Reader implementierten Methoden lassen sich über dieses E<strong>in</strong>gabe-Stream-Objekt<br />
- E<strong>in</strong>zelzeichen (Methode read()) sowie<br />
- Zeichenfolgen (mehrere Methoden read(...), s. API-Dokumentation) e<strong>in</strong>lesen<br />
Das E<strong>in</strong>lesen von Zeichenfolgen über Zeilengrenzen h<strong>in</strong>weg ist dabei nicht möglich.<br />
Da die Klasse Reader das Interface Readable implementiert, lässt sich das E<strong>in</strong>gabe-Stream-Obekt als Quelle für<br />
Scanner-Objekte e<strong>in</strong>setzen.<br />
public Pr<strong>in</strong>tWriter writer() Ermittlung des mit der Konsole verknüpften Ausgabe-Stream-Objekts.<br />
(Objekt der Klasse Pr<strong>in</strong>tWriter) Funktionswert<br />
Die Klasse Pr<strong>in</strong>tWriter stellt u.a. die gleichen Methoden pr<strong>in</strong>t(...), pr<strong>in</strong>tln(...), pr<strong>in</strong>tf(...)<br />
und format(...) zur Verfügung wie die Klasse Pr<strong>in</strong>tStream. Damit lassen sich über das Ausgabe-Stream-<br />
Objekt die gleichen Ausgabe-Operationen wie über die Standard-Ausgabe-Stream-Objekte (System.out und<br />
System.err) realisieren.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 327 – 02 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Die Klasse Console <strong>in</strong> <strong>Java</strong> (2)<br />
• Memberfunktionen der Klasse Console zur E<strong>in</strong>- und Ausgabe<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
◇<br />
public Console pr<strong>in</strong>tf(Str<strong>in</strong>g form, Object... args)<br />
public Console format(Str<strong>in</strong>g form, Object... args)<br />
▻ formatierte Ausgabe <strong>in</strong> den Ausgabe-Stream der Konsole<br />
▻ Beide Methoden besitzen die gleiche Funktionalität<br />
▻ Parameter : form Formatstr<strong>in</strong>g, enthält die Formatangaben für die auszugebenden Werte/Objekte<br />
Syntax der Formatangaben s. Methode pr<strong>in</strong>tf(...) der Klasse Pr<strong>in</strong>tStream<br />
args Referenzen auf die auszugebenden Werte/Objekte<br />
▻ Funktionswert : aktuelles Console-Objekt<br />
public void flush()<br />
▻ unmittelbare Ausgabe (Flush) des Buffers des Konsolen-Ausgabe-Streams<br />
public Str<strong>in</strong>g readL<strong>in</strong>e()<br />
▻ Lesen der nächsten Zeile aus dem Konsolen-E<strong>in</strong>gabe-Stream<br />
▻ Funktionswert : gelesene Zeile bzw null (wenn am Zeilenende gelesen wird)<br />
Das Zeilenende-Zeichen wird nicht mit zurückgegeben<br />
public Str<strong>in</strong>g readL<strong>in</strong>e(Str<strong>in</strong>g form, Object... args)<br />
▻ Ausgabe e<strong>in</strong>es formatierten Prompts <strong>in</strong> den Konsolen-Ausgabe-Stream,<br />
anschliessend Lesen der nächsten Zeile aus dem Konsolen-E<strong>in</strong>gabe-Stream<br />
▻ Parameter : Festlegung des Prompts, s. Parameter der Methode pr<strong>in</strong>tf(...) (bzw format(...))<br />
▻ Funktionswert : gelesene Zeile bzw null (wenn am Zeilenende gelesen wird)<br />
Das Zeilenende-Zeichen wird nicht mit zurückgegeben<br />
public char[] readPassword()<br />
▻ Lesen e<strong>in</strong>es Passworts aus dem Konsolen-E<strong>in</strong>gabe-Stream mit ausgeschalteter Echo-Ausgabe<br />
▻ Funktionswert : Gelesenes Passwort (<strong>in</strong> e<strong>in</strong>em char-Array) bzw null (wenn am Zeilenende gelesen wird)<br />
E<strong>in</strong> Zeilenende-Zeichen wird nicht mit zurückgegeben<br />
▻ Anmerkung : Da die Methode das gelesene Passwort als char-Array und nicht als Str<strong>in</strong>g-Objekt<br />
zurückgibt, kann es unmittelbar nach Verwendung im Speicher überschrieben werden<br />
public char[] readPassword(Str<strong>in</strong>g form, Object... args)<br />
▻ Ausgabe e<strong>in</strong>es formatierten Prompts <strong>in</strong> den Konsolen-Ausgabe-Stream,<br />
anschliessend Lesen e<strong>in</strong>es Passworts aus dem Konsolen-E<strong>in</strong>gabe-Stream mit ausgeschalteter Echo-Ausgabe<br />
▻ Parameter : Festlegung des Prompts, s. Parameter der Methode pr<strong>in</strong>tf(...) (bzw format(...))<br />
▻ Funktionswert : Gelesenes Passwort (<strong>in</strong> e<strong>in</strong>em char-Array) bzw null (wenn am Zeilenende gelesen wird)<br />
E<strong>in</strong> Zeilenende-Zeichen wird nicht mit zurückgegeben<br />
▻ Anmerkung : Da die Methode das gelesene Passwort als char-Array und nicht als Str<strong>in</strong>g-Objekt<br />
zurückgibt, kann es unmittelbar nach Verwendung im Speicher überschrieben werden
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 327 – 03 – TH – 01<br />
------------------------------------------------------------------------------------<br />
• Programm ConsoleDemo<br />
// ConsoleDemo.java<br />
Demonstrationsprogramm zur Klasse Console <strong>in</strong> <strong>Java</strong><br />
// Demo-Programm zur Klasse Console<br />
import java.io.*;<br />
import java.util.*;<br />
public class ConsoleDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{<br />
Console con = System.console();<br />
if (con == null)<br />
{ System.err.pr<strong>in</strong>tln("JVM besitzt ke<strong>in</strong>e Console -- Schade");<br />
}<br />
else<br />
{<br />
System.err.pr<strong>in</strong>tln("JVM besitzt e<strong>in</strong>e Console");<br />
con.pr<strong>in</strong>tf("%s\n", "Das ist gut");<br />
char[] altPass = con.readPassword("%s ", "altes Passwort ?");<br />
con.pr<strong>in</strong>tf("Die folgende Ausgabe sollte nicht erfolgen :\n");<br />
con.pr<strong>in</strong>tf("Das Passwort lautet : %s \n", new Str<strong>in</strong>g(altPass));<br />
con.writer().pr<strong>in</strong>t("Das Passwort lautet : ");<br />
con.writer().pr<strong>in</strong>tln(altPass);<br />
if (!verifyPasswd(altPass))<br />
con.pr<strong>in</strong>tf("ke<strong>in</strong>e Berechtigung\n");<br />
else<br />
{<br />
char[] neuPass1;<br />
char[] neuPass2;<br />
do<br />
{<br />
neuPass1 = con.readPassword("neues Passwort ? ");<br />
neuPass2 = con.readPassword("neues Passwort wiederholen : ");<br />
}<br />
while (!Arrays.equals(neuPass1, neuPass2));<br />
changePasswd(neuPass1);<br />
Arrays.fill(neuPass1, ' ');<br />
Arrays.fill(neuPass2, ' ');<br />
}<br />
Arrays.fill(altPass, ' ');<br />
}<br />
System.out.pr<strong>in</strong>t("Geben Sie e<strong>in</strong>en beliebigen Str<strong>in</strong>g e<strong>in</strong> : ");<br />
BufferedReader std<strong>in</strong> = new BufferedReader(new InputStreamReader(System.<strong>in</strong>));<br />
Str<strong>in</strong>g s = std<strong>in</strong>.readL<strong>in</strong>e();<br />
System.out.pr<strong>in</strong>tln(s);<br />
}<br />
}<br />
static void changePasswd(char[] pw)<br />
{<br />
System.out.pr<strong>in</strong>tln("Passwort geaendert !");<br />
}<br />
static boolean verifyPasswd(char[] pw)<br />
{<br />
return true;<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 331 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die Klasse System<br />
Interaktion mit dem Laufzeitsystem <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Die Klasse System ist e<strong>in</strong>e nicht-<strong>in</strong>stanzierbare Utility-Klasse (Package java.lang), die e<strong>in</strong>en Zugriff zu<br />
e<strong>in</strong>igen Systemeigenschaften ermöglicht. Im wesentlichen stellt sie zur Verfügung :<br />
▻ die Standard-E<strong>in</strong>- und Ausgabe-Objekte (öffentliche statische Datenkomponenten)<br />
▻ e<strong>in</strong>e statische Methode zur Ermittlung des Konsolen-Objekts, falls vorhanden (ab JDK 1.6)<br />
▻ statische Methoden zum Ermitteln (und Ändern) der System-Umgebung ("System Properties")<br />
▻ statische Methoden zum Zugriff zu den aktuellen Environment-Variablen des Betriebssystems (ab JDK 1.5)<br />
▻ statische Methoden zum Setzen und Ermitteln des im System <strong>in</strong>stallierten SecurityManager-Objekts<br />
▻ statische Utility-Methoden (z.B. zur Ermittlung der aktuellen Zeit, Teilkopieren von Arrays)<br />
▻ e<strong>in</strong>ige statische Methoden, die zum aktuellen Runtime-Objekt zugreifen (Aufruf gleichnamiger Methoden) :<br />
Der Aufruf System.method() ist äquivalent zu Runtime.getRuntime().method()<br />
• Ermittlung der aktuellen Zeit<br />
◇ Hierzu dient die statische Methode der Klasse System :<br />
public static long currentTimeMillis();<br />
Rückgabewert : Vergangene Zeit seit dem 1.1.1970 UTC, Mitternacht <strong>in</strong> Millisekunden<br />
◇ Zur Decodierung dieser Zeit <strong>in</strong> ihre üblicherweise vom Menschen verwendeten Komponenten (Zeit und Datum)<br />
kann die Bibliotheks-Klasse Date (Package java.util) e<strong>in</strong>gesetzt werden :<br />
▻ Erzeugung e<strong>in</strong>es Date-Objektes, dessen Konstruktor der von currentTimeMillis() zurückgegebene<br />
Wert als Parameter übergeben wird.<br />
▻ Aufruf der Methode public Str<strong>in</strong>g toStr<strong>in</strong>g() für dieses Date-Objekt.<br />
◇ Beispiel :<br />
public static void gc() expliziter Aufruf des Garbage Collectors<br />
public static expliziter Aufruf der f<strong>in</strong>alize()-Methoden aller<br />
void runF<strong>in</strong>alization() zur Vernichtung anstehenden Objekte<br />
public static Laden der durch libname spezifizierten dynam.Library<br />
void loadLibrary(Str<strong>in</strong>g libname) (native Code) Die Zuordnung zwischen Library, Library-Ort,<br />
und Library-Date<strong>in</strong>ame ist systemabhängig<br />
public static Laden e<strong>in</strong>er dynam. Library (native Code), die durch den absoluten<br />
void load(Str<strong>in</strong>g filepath) Dateipfad filepath referiert wird.<br />
public static void exit(<strong>in</strong>t status) Beendigung der aktuell laufenden JVM (u. damit des Programms).<br />
Der Parameter status ist der Programm-Exit-Code<br />
Der von dieser Methode als Funktionswert erzeugte Str<strong>in</strong>g enthält die Zeit (und Datum) <strong>in</strong> folgender Form :<br />
dow mon dd hh:mm:ss zzz yyyy<br />
import java.util.Date;<br />
class ActTime<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Date act = new Date(System.currentTimeMillis());<br />
System.out.pr<strong>in</strong>tln("aktuelle Zeit : " + act.toStr<strong>in</strong>g());<br />
}<br />
}<br />
aktuelle Zeit : Wed Aug 08 19:38:30 CEST 2007
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 332 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• System-Umgebung (System Properties)<br />
Interaktion mit dem Laufzeitsystem <strong>in</strong> <strong>Java</strong> (2)<br />
◇ Die System-Umgebung besteht aus System-Eigenschaften (System Properties).<br />
Diese werden z. Tl von Standard- Bibliotheks-Klassen benutzt. Sie können aber auch <strong>in</strong> eigenen Klassen verwendet<br />
werden.<br />
◇ E<strong>in</strong>e System Property hat e<strong>in</strong>en Namen und e<strong>in</strong>en Wert.<br />
Der Name ist e<strong>in</strong> Str<strong>in</strong>g, der durch jeweils e<strong>in</strong>en Punkt <strong>in</strong> mehrere Abschnitte unterteilt se<strong>in</strong> kann.<br />
Der Wert ist ebenfalls e<strong>in</strong> Str<strong>in</strong>g.<br />
• Änderung der System-Umgebung<br />
◇ Für jede JVM existiert e<strong>in</strong> Satz von Standard System Properties.<br />
◇ Zusätzlich können benutzerdef<strong>in</strong>ierte System Properties beim Programm- (JVM-) Start festgelegt werden.<br />
Hierzu dient die –D Option beim Aufruf der JVM.<br />
Beispiel : java –DLabor.aktuell=<strong>LSW</strong> ActTime<br />
Hierdurch wird die System Property mit dem Namen "Labor.aktuell" und dem Wert "<strong>LSW</strong>" zusätzlich<br />
gesetzt.<br />
◇ Darüberh<strong>in</strong>aus können weitere System Properties auch während des Programmlaufs gesetzt werden, vorausgesetzt<br />
das SecurityManager-Objekt erlaubt es.<br />
Zum Setzen (und Ändern) e<strong>in</strong>er System Property existiert <strong>in</strong> der Klasse System die statische Methode<br />
▻<br />
Die Methode setzt e<strong>in</strong>e System Property mit dem Namen key auf den Wert val.<br />
Als Funktionswert gibt die Methode den zuvor gesetzt gewesenen Wert der System Property bzw – falls diese<br />
noch nicht existiert hat – null zurück.<br />
Beispiel : System.setProperty("Labor.aktuell", "<strong>LSW</strong>");<br />
• Ermittlung der System-Umgebung<br />
◇ Properties werden <strong>in</strong> Objekten der Klasse Properties (Package java.util) gespeichert.<br />
Für die Standard System Properties wird beim Start der JVM e<strong>in</strong> entsprechendes Objekt angelegt. (System-<br />
Properties-Objekt). Zu ihm kann über die Klasse System zugegriffen werden.<br />
Benutzerdef<strong>in</strong>ierte System Properties (sowohl bei Programmstart festgelegte, als auch im Programm gesetzte) werden<br />
<strong>in</strong> dieses Objekt e<strong>in</strong>gefügt.<br />
E<strong>in</strong> Benutzer kann <strong>in</strong> e<strong>in</strong>em Programm darüberh<strong>in</strong>aus weitere Properties-Objekte anlegen.<br />
◇ Statische Methoden der Klasse System zum Zugriff zum System-Properties-Objekt :<br />
▻<br />
▻<br />
public static Str<strong>in</strong>g setProperty(Str<strong>in</strong>g key, Str<strong>in</strong>g val)<br />
public static Properties getProperties()<br />
Funktionswert : das System-Properties-Objekt<br />
public static Str<strong>in</strong>g getProperty(Str<strong>in</strong>g key)<br />
Funktionswert : der Wert der System Property mit dem Namen key, bzw null, falls Property nicht existiert<br />
◇ Sämtliche <strong>in</strong> e<strong>in</strong>em Properties-Objekt enthaltenen Properties (Name/Wert-Paare) lassen sich mittels der<br />
folgenden Methode der Klasse Properties über e<strong>in</strong> Pr<strong>in</strong>tStream-Objekt ausgeben :<br />
public void list(Pr<strong>in</strong>tStream out);
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 333 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Interaktion mit dem Laufzeitsystem <strong>in</strong> <strong>Java</strong> (3)<br />
• Beispielprogramm zur Ausgabe der System Properties <strong>in</strong> die Standard-Ausgabe<br />
import java.util.Properties;<br />
class SysProps<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ System.getProperties().list(System.out);<br />
}<br />
}<br />
-- list<strong>in</strong>g properties --<br />
java.runtime.name=<strong>Java</strong>(TM) SE Runtime Environment<br />
sun.boot.library.path=C:\Programme\<strong>Java</strong>\jre1.6.0\b<strong>in</strong><br />
java.vm.version=1.6.0-b105<br />
java.vm.vendor=Sun Microsystems Inc.<br />
java.vendor.url=http://java.sun.com/<br />
path.separator=;<br />
java.vm.name=<strong>Java</strong> HotSpot(TM) Client VM<br />
file.encod<strong>in</strong>g.pkg=sun.io<br />
user.country=DE<br />
sun.java.launcher=SUN_STANDARD<br />
sun.os.patch.level=Service Pack 2<br />
java.vm.specification.name=<strong>Java</strong> Virtual Mach<strong>in</strong>e Specification<br />
user.dir=E:\<strong>Java</strong>\Vorlesung\elemprogfunc<br />
java.runtime.version=1.6.0-b105<br />
java.awt.graphicsenv=sun.awt.W<strong>in</strong>32GraphicsEnvironment<br />
java.endorsed.dirs=C:\Programme\<strong>Java</strong>\jre1.6.0\lib\endorsed<br />
os.arch=x86<br />
java.io.tmpdir=C:\DOKUME~1\thomas\LOKALE~1\Temp\<br />
l<strong>in</strong>e.separator=<br />
java.vm.specification.vendor=Sun Microsystems Inc.<br />
user.variant=<br />
os.name=W<strong>in</strong>dows XP<br />
sun.jnu.encod<strong>in</strong>g=Cp1252<br />
java.library.path=C:\WINDOWS\system32;.;C:\WINDOWS\Sun\...<br />
java.specification.name=<strong>Java</strong> Platform API Specification<br />
java.class.version=50.0<br />
sun.management.compiler=HotSpot Client Compiler<br />
os.version=5.1<br />
user.home=C:\Dokumente und E<strong>in</strong>stellungen\thomas<br />
user.timezone=<br />
java.awt.pr<strong>in</strong>terjob=sun.awt.w<strong>in</strong>dows.WPr<strong>in</strong>terJob<br />
file.encod<strong>in</strong>g=Cp1252<br />
java.specification.version=1.6<br />
user.name=thomas<br />
java.class.path=.;C:\Programme\<strong>Java</strong>\jre1.6.0\lib\ext\...<br />
java.vm.specification.version=1.0<br />
sun.arch.data.model=32<br />
java.home=C:\Programme\<strong>Java</strong>\jre1.6.0<br />
java.specification.vendor=Sun Microsystems Inc.<br />
user.language=de<br />
awt.toolkit=sun.awt.w<strong>in</strong>dows.WToolkit<br />
java.vm.<strong>in</strong>fo=mixed mode, shar<strong>in</strong>g<br />
java.version=1.6.0<br />
java.ext.dirs=C:\Programme\<strong>Java</strong>\jre1.6.0\lib\ext;C:...<br />
sun.boot.class.path=C:\Programme\<strong>Java</strong>\jre1.6.0\lib\resour...<br />
java.vendor=Sun Microsystems Inc.<br />
file.separator=\<br />
java.vendor.url.bug=http://java.sun.com/cgi-b<strong>in</strong>/bugreport...<br />
sun.cpu.endian=little<br />
sun.io.unicode.encod<strong>in</strong>g=UnicodeLittle<br />
sun.desktop=w<strong>in</strong>dows<br />
sun.cpu.isalist=
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 334 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Interaktion mit dem Laufzeitsystem <strong>in</strong> <strong>Java</strong> (4)<br />
• Zugriff zu den Environment-Variablen des Betriebssystems<br />
◇ Ab dem JDK 5.0 kann <strong>in</strong> <strong>Java</strong>-Programmen wieder zu den vom Betriebssystem verwalteten Environment-Variablen<br />
zugegriffen werden.<br />
◇ E<strong>in</strong>e Environment-Variable besitzt – wie e<strong>in</strong>e System Property – e<strong>in</strong>en Namen und hat e<strong>in</strong>en Wert.<br />
Sowohl Name als auch Wert s<strong>in</strong>d jeweils e<strong>in</strong> Str<strong>in</strong>g. Jede Environment-Variabale bildet e<strong>in</strong> Str<strong>in</strong>g-Paar.<br />
◇ Mit den folgenden statischen Methoden der Klasse System kann zu dem bei der Programmabarbeitung aktuellen<br />
Environment zugegriffen werden :<br />
▻<br />
▻<br />
public static Map getenv()<br />
Ermittlung aller aktuellen Environment-Variablen.<br />
Funktionswert : - Str<strong>in</strong>g-Str<strong>in</strong>g-Map , die die Environment-Variablen enthält.<br />
Falls das Betriebssystem ke<strong>in</strong>e Environment-Variablen unterstützt, ist die zurückgegebene<br />
Map leer.<br />
E<strong>in</strong>e Map ist e<strong>in</strong> assoziativer Conta<strong>in</strong>er, der Schlüssel (key) –Werte (value)-Paare speichert.<br />
Als Schlüssel dient hier der Name e<strong>in</strong>er Environment-Variablen, der Wert ist der Wert dieser Variablen<br />
public static Str<strong>in</strong>g getenv(Str<strong>in</strong>g name)<br />
Ermittlung des Werts der Environment-Variablen mit dem Namen name<br />
Funktionswert : - Wert der Environment-Variablen<br />
- bzw null, wenn ke<strong>in</strong>e Environment-Variable mit dem Namen name existiert<br />
Falls e<strong>in</strong> Security Manager <strong>in</strong>stalliert ist, wird er von beiden Funktionen befragt, ob der Zugriff zum Environment<br />
zulässig ist.<br />
Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />
◇ Beispielprogramm zum Zugriff zu den Environment-Variablen<br />
Auflistung aller Environmentvariablen (Name = Wert) <strong>in</strong> die Standard-Ausgabe<br />
// GetEnv.java<br />
// Ermittlung des aktuellen Environments<br />
import java.util.*;<br />
public class GetEnv<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Map env = System.getenv();<br />
Set keys = env.keySet();<br />
for (Str<strong>in</strong>g name : keys)<br />
System.out.pr<strong>in</strong>tln(name + " = " + System.getenv(name));<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 335 – 00 – TH – 01<br />
------------------------------------------------------------------------------------<br />
• Grundsätzliches<br />
Die Klasse Runtime <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Die Klasse Runtime bef<strong>in</strong>det sich im Package java.lang.<br />
◇ Jede <strong>Java</strong>-Applikation besitzt genau e<strong>in</strong> Objekt dieser Klasse. Es wird beim Start der JVM automatisch erzeugt.<br />
Dieses Objekt bildet e<strong>in</strong> Interface zwischen der <strong>Java</strong>-Applikation und der Laufzeitumgebung der ausführenden JVM.<br />
◇ Zur Ermittlung des aktuellen Runtime-Objekts dient die statischen Methode der Klasse Runtime :<br />
static Runtime getRuntime()<br />
Runtime.getRuntime() liefert das mit der aktuellen <strong>Java</strong>-Applikation assoziierte Runtime-Objekt.<br />
◇ E<strong>in</strong>e explizite Instanzierung der Klasse ist nicht möglich.<br />
◇ Die Klasse Runtime stellt Funktionalitäten <strong>in</strong> folgenden Bereichen zur Verfügung :<br />
▻ Information über Systemresourcem der JVM (Prozessoranzahl, Arbeitsspeicher)<br />
▻ expliziter Aufruf des Garbage Collectors<br />
▻ Ausführung externer Programme <strong>in</strong> K<strong>in</strong>dprozessen<br />
▻ Laden dynamischer Bibliotheken (nativer Code)<br />
▻ Debug-Unterstützung<br />
▻ Beendigung (shutdown) der JVM<br />
• Information über Systemresourcen der JVM<br />
◇ Hierfür dienen die folgenden Methoden der Klasse Runtime<br />
public <strong>in</strong>t availableProcessors() Rückgabe der Anzahl Prozessoren, die der JVM zur Verfügung stehen<br />
public long freeMemory() Ermittlung des freien der JVM zur Verfügung stehenden Arbeitsspeichers,<br />
Funktionswert = freier Arbeitsspeicher <strong>in</strong> Bytes<br />
public long totalMemory() Ermittlung des gesamten der JVM zur Verfügung stehenden Arbeitspeichers,<br />
Funktionswert = gesamter Arbeitsspeicher <strong>in</strong> Bytes<br />
public long maxMemory() Ermittlung der maximalen Arbeitspeichergröße, die die JVM zu nutzen<br />
versuchen wird (<strong>in</strong> Bytes)<br />
Falls ke<strong>in</strong>e obere Grenze existiert, Rückgabe von Long.MAX_VALUE<br />
◇ Demonstrationsbeispiel :<br />
public class ResInfo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Runtime rt = Runtime.getRuntime();<br />
System.out.pr<strong>in</strong>tln("E<strong>in</strong>ige Systemresourcen der JVM :");<br />
System.out.pr<strong>in</strong>tln("Anzahl Prozessoren : " + rt.availableProcessors());<br />
System.out.pr<strong>in</strong>tln("gesamter Arbeitsspeicher : " + rt.totalMemory() + " Bytes");<br />
System.out.pr<strong>in</strong>tln("freier Arbeitsspeicher : " + rt.freeMemory() + " Bytes");<br />
System.out.pr<strong>in</strong>tln("maximaler Arbeitsspeicher : " + rt.maxMemory() + " Bytes");<br />
}<br />
}<br />
E<strong>in</strong>ige Systemresourcen der JVM :<br />
Anzahl Prozessoren : 2<br />
gesamter Arbeitsspeicher : 5177344 Bytes<br />
freier Arbeitsspeicher : 4997096 Bytes<br />
maximaler Arbeitsspeicher : 66650112 Bytes
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 336 – 00 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Die Klasse Runtime <strong>in</strong> <strong>Java</strong> (2)<br />
• Ausführung externer Programme <strong>in</strong> K<strong>in</strong>dprozessen<br />
◇ Die Erzeugung von K<strong>in</strong>dprozessen, die e<strong>in</strong> anzugebendes Programm ausführen, wird durch mehrere überladene<br />
Methoden mit dem Namen exec ermöglicht.<br />
◇ Alle exec-Methoden geben bei Erfolg als Funktionswert e<strong>in</strong> Objekt der Klasse Process zurück.<br />
Dieses Objekt repräsentiert den neu erzeugten K<strong>in</strong>dprozeß. Es ermöglicht dem Elternprozeß h<strong>in</strong>sichtlich bestimmter<br />
Aspekte e<strong>in</strong>e Interaktion mit dem erzeugten K<strong>in</strong>dprozeß (z.B. Warten auf K<strong>in</strong>dprozeßende, Ermittlung des Return-<br />
Codes des K<strong>in</strong>dprozesses, Abbruch des K<strong>in</strong>dprozesses)<br />
◇ Beim Auftreten von Fehlern werfen die exec-Methoden entsprechende Exceptions.<br />
So werfen alle exec-Methoden beim Auftreten e<strong>in</strong>es I/O-Fehlers (z.B. Programmdatei nicht gefunden) e<strong>in</strong>e<br />
IOException.<br />
◇ Falls e<strong>in</strong> Security Manager <strong>in</strong>stalliert ist (e<strong>in</strong> SecurityManager-Objekt existiert), überprüft dieser, ob die Aus-<br />
führung des angegebenen Programms zulässig ist. Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />
◇ Überblick über die exec-Methoden (Auswahl) :<br />
public Process exec(Str<strong>in</strong>g cmd) Ausführung des durch cmd referierten Programms <strong>in</strong> e<strong>in</strong>em neu<br />
throws IOException erzeugten K<strong>in</strong>dprozeß<br />
public Process exec(Str<strong>in</strong>g[] cmdarr) Ausführung des durch cmdarr[0] referierten Programms <strong>in</strong> e<strong>in</strong>em<br />
throws IOException neu erzeugten K<strong>in</strong>dprozeß. Die übrigen Elemente von cmdarr<br />
(ab Index 1) werden dem Programm als Programmparameter übergeben<br />
public Process exec(Str<strong>in</strong>g cmd, Ausführung des durch cmd referierten Programms <strong>in</strong> e<strong>in</strong>em neu<br />
Str<strong>in</strong>g[] envp) erzeugten K<strong>in</strong>dprozeß<br />
throws IOException envp referiert das dem Programm zu übergebende Environment<br />
public Process exec(Str<strong>in</strong>g[] cmdarr, Ausführung des durch cmdarr[0] referierten Programms <strong>in</strong> e<strong>in</strong>em<br />
Str<strong>in</strong>g[] envp) neu erzeugten K<strong>in</strong>dprozeß. Die übrigen Elemente von cmdarr<br />
throws IOException (ab Index 1) werden dem Programm als Programmparameter übergeben<br />
envp referiert das dem Programm zu übergebende Environment<br />
Wird ke<strong>in</strong> Environment angegeben (Methoden mit nur e<strong>in</strong>em Parameter bzw envp == null) so wird dem im<br />
K<strong>in</strong>dprozess ausgeführten Programm das Environment des Elternprozesses übergeben<br />
Es existieren zwei weitere exec-Methoden (3 Parameter), mit denen für den neu erzeugten K<strong>in</strong>dprozeß explizit das<br />
Arbeitsdirectory festgelegt werden kann. Wird für den entsprechenden Parameter null übergeben so erbt – wie bei<br />
den o.a. exec-Methoden – der K<strong>in</strong>dprozeß das Arbeitsdirectory des Elternprozesses.<br />
◇ E<strong>in</strong>faches Demonstrationsbeispiel :<br />
import java.io.*;<br />
class ExecDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{ Str<strong>in</strong>g[] cmd = null;<br />
if (args.length>0)<br />
cmd = args;<br />
else<br />
{ cmd = new Str<strong>in</strong>g[1];<br />
cmd[0]= "calc";<br />
}<br />
Runtime.getRuntime().exec(cmd);<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 341 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zip des Exception Handl<strong>in</strong>gs<br />
Exceptions <strong>in</strong> <strong>Java</strong> (1)<br />
◇ <strong>Java</strong> stellt – wie auch C++ – e<strong>in</strong>en speziellen Mechanismus zur Behandlung von Ausnahmesituationen (Fehlerfällen,<br />
Exceptions), die während der Programmausführung auftreten können, zur Verfügung ⇒ Exception Handl<strong>in</strong>g<br />
◇ Ausnahmesituationen <strong>in</strong> diesem S<strong>in</strong>ne s<strong>in</strong>d Fehler, oder sonstige unerwünschte Sonderfälle (z.B. Dateizugriffsfehler,<br />
Verletzung von Array-Grenzen, Datenformatfehler usw), die im normalen Programmablauf nicht auftreten sollten,<br />
aber auftreten können.<br />
Exception Handl<strong>in</strong>g ist ke<strong>in</strong> Mechanismus zur Behandlung von externen oder <strong>in</strong>ternen Interrupts.<br />
◇ Exception Handl<strong>in</strong>g trennt den Code, der Fehler verursachen kann, von dem Code, der e<strong>in</strong>en aufgetretenen Fehler<br />
behandelt.<br />
Dadurch kann der eigentliche den normalen Programmablauf steuernde (produktive) Code frei gehalten werden von<br />
e<strong>in</strong>er ständigen Überprüfung auf den Auftritt von Fehlern und Sonderfällen sowie der Reaktion auf diese. Dies trägt<br />
erheblich zur Klarheit und Übersichtlichkeit des Codes bei.<br />
◇ Code (z.B. e<strong>in</strong>e Methode e<strong>in</strong>er Bibliotheksklasse), der e<strong>in</strong>e Ausnahmesituation entdeckt, wirft e<strong>in</strong>e Exception, die<br />
dann von e<strong>in</strong>em anderen Code-Teil, dem Exception-Handler gefangen wird.<br />
Im Exception-Handler f<strong>in</strong>det die Reaktion auf die (Bearbeitung der) Ausnahmesituation statt. Diese kann der Fehlerart<br />
sowie der jeweiligen spezifischen Programmsituation angepasst werden. Z.B. kann e<strong>in</strong>e Fehlermeldung ausgegeben<br />
werden und anschliessend das Programm fortgesetzt oder beendet werden. Oder es kann versucht werden, die Fehler-<br />
ursache zu beseitigen und das Programm dann fortzusetzen.<br />
◇ Exceptions werden als Objekte behandelt. Sie enthalten Informationen über die Fehlerursache und stellen Methoden<br />
zum Zugriff zu diesen zur Verfügung.<br />
Werfen e<strong>in</strong>er Exception (throw<strong>in</strong>g) bedeutet das Erzeugen e<strong>in</strong>es Objekts e<strong>in</strong>er Exception-Klasse und die anschlies-<br />
sende Suche e<strong>in</strong>es passenden Exception-Handlers.<br />
Wird e<strong>in</strong> derartiger Handler gefunden, wird ihm das Exception-Objekt (genauer e<strong>in</strong>e Referenz darauf) übergeben<br />
( Fangen der Exception, catch<strong>in</strong>g).<br />
Dem Handler stehen damit die im Exception-Objekt enthaltenen Informationen zur Auswertung zur Verfügung.<br />
◇ Exception Handl<strong>in</strong>g wird <strong>in</strong> <strong>Java</strong> wesentlich umfangreicher und strikter als <strong>in</strong> C++ angewendet :<br />
▻ In der Standard-Bibliothek s<strong>in</strong>d zahlreiche Exception-Klassen def<strong>in</strong>iert.<br />
Sie bilden e<strong>in</strong>e über mehrere Pakete verteilte Klassenhierarchie, die die Klasse Throwable (von Object<br />
abgeleitet, Paket java.lang) als Wurzelklasse besitzt.<br />
Im Konstruktor e<strong>in</strong>er derartigen Klasse wird i.a. die Exception-Ursache bzw e<strong>in</strong>e Kurzbeschreibung der Exception<br />
durch e<strong>in</strong>en Str<strong>in</strong>g (fest codiert oder als Parameter übergeben) festgelegt.<br />
▻ Viele Methoden vieler Bibliotheksklassen werfen Exceptions.<br />
▻ <strong>Java</strong> erzw<strong>in</strong>gt, dass geworfene Exceptions gefangen werden müssen. Existiert <strong>in</strong> e<strong>in</strong>em Benutzerprogramm ke<strong>in</strong><br />
geeigneter Exception-Handler, so werden sie von e<strong>in</strong>em <strong>in</strong> der JVM angesiedelten Standard-Handler behandelt,<br />
der Informationen über die Exception <strong>in</strong> die Standard-Ausgabe ausgibt und anschliessend das Programm (genauer<br />
den aktuellen Thread) beendet.<br />
▻ E<strong>in</strong> Benutzer kann jederzeit eigene Exception-Klassen def<strong>in</strong>ieren. Dies kann s<strong>in</strong>nvoll se<strong>in</strong>, wenn spezielle Fehler-<br />
fälle gesondert von anderen behandelt werden sollen (z.B. "Division durch Null" als Spezialfall e<strong>in</strong>er<br />
ArithmeticException).<br />
E<strong>in</strong>e beutzerdef<strong>in</strong>ierte Exception-Klasse muß von e<strong>in</strong>er der Standard-Bibliotheks-Exception-Klassen abgeleitet<br />
se<strong>in</strong>
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 342 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Hierarchie der Bibliotheks-Exception-Klassen<br />
Exceptions <strong>in</strong> <strong>Java</strong> (2)<br />
◇ Alle Exception-Klassen s<strong>in</strong>d – direkt oder <strong>in</strong>direkt – von der Klasse Throwable abgeleitet.<br />
◇ Die Klasse Throwable (Paket java.lang) ist e<strong>in</strong>e direkte Unterklasse von Object.<br />
◇ Überblick über den Anfang der Hierarchie :<br />
Throwable<br />
Error Exception<br />
VirtualMach<strong>in</strong>eError<br />
weitere<br />
RuntimeException IOException<br />
Error-Klassen<br />
ArithmeticException weitere<br />
FileNotFoundException<br />
RuntimeException-<br />
Klassen<br />
weitere<br />
Exception-<br />
Klassen<br />
weitere<br />
IOException-<br />
Klassen<br />
◇ Exceptions der Klasse Error sowie der davon abgeleiteten Klassen kennzeichnen ernsthafte Systemfehler, die<br />
normalerweise nicht auftreten sollten, aber pr<strong>in</strong>zipiell jederzeit auftreten können.<br />
E<strong>in</strong> normales Benutzerprogramm kann auf derartige Exceptions i.a. nicht s<strong>in</strong>nvoll reagieren und sollte sie deswegen<br />
auch nicht fangen. Vielmehr sollten sie immer vom Default-Exception-Handler der JVM behandelt werden.<br />
◇ Exceptions der Klasse RuntimeException sowie der davon abgeleiteten Klassen können ebenfalls pr<strong>in</strong>zipiell<br />
an beliebiger Stelle während des Programmablaufs auftreten. I.a. liegt ihre Ursache <strong>in</strong> e<strong>in</strong>em logischen Programmier-<br />
fehler (z.B. Division durch 0 oder unzulässiger Array-Index). E<strong>in</strong>e vernünftige Reaktion zur Laufzeit ist i.a. nicht<br />
möglich. Derartige Fehler sollten i.a. im Programm-Code korrigiert werden.<br />
E<strong>in</strong> Benutzerprogramm kann diese Exceptions behandeln (d.h. geeignete Exception-Handler bereitstellen), muß es aber<br />
nicht. Im letzteren Fall erfolgt wiederum e<strong>in</strong>e Behandlung durch den Default-Handler der JVM.<br />
◇ Exceptions aller übrigen Klassen (z.B. IOException) repräsentieren Fehler, mit denen man pr<strong>in</strong>zipiell rechnen<br />
muß (z.B. Datei ist nicht vorhanden) und die deswegen auch <strong>in</strong> irgende<strong>in</strong>er Weise behandelt werden müssen.<br />
Für diese Exceptions schreibt <strong>Java</strong> e<strong>in</strong>e "catch-or-declare"-Erfordernis vor. Sie müssen von der Funktion, <strong>in</strong> der sie<br />
geworfen werden, entweder gefangen oder von ihr als weiter-werfbar deklariert werden.<br />
Andererseits darf e<strong>in</strong>e Funktion nur solche Exceptions dieser Klassen werfen, die sie auch deklariert hat.<br />
Das E<strong>in</strong>halten dieser Erfordernis kann vom Compiler überprüft werden. Sie werden daher als geprüfte (checked)<br />
Exceptions bezeichnet.<br />
◇ Exceptions der Klassen Error und RuntimeException sowie der davon abgeleiteten Klassen s<strong>in</strong>d dagegen<br />
ungeprüfte (unchecked) Exceptions. Sie können jederzeit geworfen werden, ohne daß sie von der entsprechenden<br />
Funktion deklariert werden müssen. Für sie gilt die "catch-or-declare"-Erfordernis nicht, sie dürfen aber deklariert<br />
werden
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 343 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse Throwable<br />
Exceptions <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Die direkt von der Klasse Object abgeleitete Klasse Throwable (Paket java.lang) ist Basisklasse aller<br />
Exception-Klassen.<br />
◇ Sie def<strong>in</strong>iert e<strong>in</strong> allgeme<strong>in</strong>es Interface für den Zugriff zu den Exception-Objekten aller Exception-Klassen<br />
Die vier wichtigsten Methoden dieses Interfaces s<strong>in</strong>d :<br />
▻ public Str<strong>in</strong>g getMessage();<br />
Diese Methode gibt den bei der Exception-Objekt-Erzeugung gespeicherten Ursachen- bzw Kurzbeschreibungs-<br />
Str<strong>in</strong>g als Funktionswert zurück, bzw null, falls ke<strong>in</strong> derartiger Str<strong>in</strong>g gespeichert wurde.<br />
▻ public Str<strong>in</strong>g toStr<strong>in</strong>g();<br />
Diese Methode erzeugt e<strong>in</strong>en Str<strong>in</strong>g, der aus dem vollqualifizierten Namen der tatsächlichen Klasse des Exception-<br />
Objekts besteht, gegebenenfalls (falls getMessage() e<strong>in</strong>en Wert !=null zurückgibt) gefolgt von ": " und<br />
dem Rückgabewert von getMessage().<br />
▻ public void pr<strong>in</strong>tStackTrace();<br />
Diese Methode gibt den Funktionswert von toStr<strong>in</strong>g() gefolgt von dem Aufruf-Stack der Funktion, <strong>in</strong> der<br />
die Exception ursprünglich geworfen wurde, <strong>in</strong> die Standard-Fehler-Ausgabe (System.err) aus.<br />
▻ public void pr<strong>in</strong>tStackTrace(Pr<strong>in</strong>tStream s);<br />
Diese Methode gibt den Funktionswert von toStr<strong>in</strong>g() gefolgt von dem Aufruf-Stack der Funktion, <strong>in</strong> der<br />
die Exception ursprünglich geworfen wurde, <strong>in</strong> den durch s referierten Pr<strong>in</strong>t-Stream aus.<br />
• Deklaration werfbarer Exceptions (throws-Klausel)<br />
◇ Die von e<strong>in</strong>er Funktion werfbaren geprüften Exceptions müssen von dieser deklariert werden.<br />
Werfbare ungeprüfte Exceptions können, müssen aber nicht deklariert werden.<br />
◇ Die Deklaration erfolgt durch e<strong>in</strong>e im Funktionskopf nach der Parameterliste anzugebende throws-Klausel.<br />
Die throws-Klausel besteht aus dem Schlüsselwort throws, gefolgt von e<strong>in</strong>er durch Kommata getrennten<br />
Auflistung von Exception-Klassen<br />
◇ Syntax :<br />
◇ Beispiel : public Str<strong>in</strong>g liesEtwas(Str<strong>in</strong>g dname)<br />
throws FileNotFoundException, EOFException<br />
{<br />
// ...<br />
}<br />
• Werfen e<strong>in</strong>er Exception<br />
◇ Mittels e<strong>in</strong>er throw-Anweisung.<br />
Nach dem Schlüsselwort throw ist e<strong>in</strong>e Referenz auf das zu werfende Exception-Objekt anzugeben.<br />
Diese Referenz kann<br />
▻ der Wert e<strong>in</strong>es new-Ausdrucks se<strong>in</strong> (neu erzeugtes Exception-Objekt)<br />
▻ die e<strong>in</strong>em Exception-Handler übergebene Objekt-Referenz se<strong>in</strong> ("Weiterwerfen" der Exception)<br />
◇ Syntax :<br />
throws<br />
Exception-Klasse<br />
throw Exception-Objekt-Referenz ;<br />
◇ Beispiel : throw new ArithmeticException("Nenner ist Null");<br />
,
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 344 – 00 – TH – 02<br />
------------------------------------------------------------------------------------<br />
• Die try-Anweisung<br />
◇ Sie ermöglicht das Fangen von Exceptions.<br />
◇ E<strong>in</strong>e try-Anweisung besteht i.a. aus drei Teilen :<br />
▻ dem try-Block<br />
▻ e<strong>in</strong>em oder mehreren catch-Blöcken<br />
▻ e<strong>in</strong>em f<strong>in</strong>ally-Block<br />
Exceptions <strong>in</strong> <strong>Java</strong> (4)<br />
Entweder die catch-Blöcke oder der f<strong>in</strong>ally-Block dürfen auch fehlen, aber nicht beides.<br />
◇ Syntax :<br />
try { Anweisung }<br />
catch ( Exception-Klasse Name )<br />
Anweisung<br />
{ }<br />
f<strong>in</strong>ally Anweisung<br />
{ }<br />
◇ Der try-Block enthält den eigentlichen produktiven Code, der auf den Auftritt von Exceptions überwacht wird.<br />
Er wird solange ausgeführt, bis entweder durch e<strong>in</strong>e der Anweisungen e<strong>in</strong>e Exception (direkt durch e<strong>in</strong>e throw-Anwei-<br />
sung oder <strong>in</strong>direkt durch e<strong>in</strong>e aufgerufene Funktion) geworfen wird oder alle Anweisungen erfolgreich abgearbeitet<br />
worden s<strong>in</strong>d.<br />
Beim Auftritt e<strong>in</strong>er Exception wird der try-Block sofort verlassen und nach e<strong>in</strong>em Exception-Handler gesucht,<br />
der die Exception fangen kann.<br />
◇ Die catch-Blöcke bilden die Exception-Handler.<br />
Jeder catch-Block ist zuständig für das Fangen von Exceptions e<strong>in</strong>er bestimmten Klasse bzw deren Unterklassen.<br />
Die von e<strong>in</strong>em catch-Block fangbare Exception-Klasse ist <strong>in</strong> se<strong>in</strong>em Kopf – analog zur Parameter-Deklaration von<br />
Funktionen – angegeben. Da Objekte (genauer Objekt-Referenzen) e<strong>in</strong>er Klasse zuweisungskompatibel zu Variablen<br />
e<strong>in</strong>er Basisklasse s<strong>in</strong>d, können auch Exceptions aller Klassen, die von der deklarierten Klasse abgeleitet s<strong>in</strong>d, gefangen<br />
werden.<br />
Die Suche nach e<strong>in</strong>em "passenden" Exception-Handler erfolgt <strong>in</strong> der Reihenfolge ihrer Angabe im Quellcode.<br />
Wird e<strong>in</strong> Exception-Handler gefunden, der die geworfene Exception fangen kann, wird das Programm mit se<strong>in</strong>er<br />
Abarbeitung fortgesetzt. Dabei wird die Exception wie e<strong>in</strong> formaler Funktionsparameter an den Handler übergeben.<br />
Wird ke<strong>in</strong> "passender" Exception-Handler gefunden, wird die Suche <strong>in</strong> der jeweils nächsten umfassenden try-An-<br />
weisung (gegebenenfalls <strong>in</strong> der aufrufenden Funktion) fortgesetzt.<br />
Bleibt auch das erfolglos, wird der Default-Exception-Handler der JVM ausgeführt und das Programm beendet.<br />
◇ Der f<strong>in</strong>ally-Block enthält Code, der immer ausgeführt wird, unabhängig davon, wie die try-Anweisung<br />
verlassen wird, ob durch reguläre Beendigung des try-Blocks oder durch Werfen e<strong>in</strong>er gefangenen oder nicht<br />
gefangenen Exception.<br />
Die Ausführung des f<strong>in</strong>ally-Blocks erfolgt unmittelbar vor Verlassen des try-Blocks bzw – beim Fangen e<strong>in</strong>er<br />
Exception – vor Verlassen des entsprechenden catch-Blocks. Die Ausführung erfolgt auch dann, wenn try- bzw<br />
catch-Block mit e<strong>in</strong>er return-Anweisung verlassen werden.<br />
Der f<strong>in</strong>ally-Block wird <strong>in</strong>sbesondere verwendet, um Aufräumarbeiten durchzuführen und sicherzustellen, dass<br />
belegte System-Resourcen (z.B. geöffnete Dateien) freigegeben werden
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 345 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Demonstrationsprogramm zu Exceptions<br />
// ExceptDemo.java<br />
import java.io.*;<br />
Exceptions <strong>in</strong> <strong>Java</strong> (5)<br />
class ExceptDemo<br />
{<br />
public void func1()<br />
{ try<br />
{ System.out.pr<strong>in</strong>tln("<strong>in</strong> func1() : Aufruf von func2()");<br />
func2();<br />
System.out.pr<strong>in</strong>tln("normales Ende von try <strong>in</strong> func1()!");<br />
return;<br />
}<br />
f<strong>in</strong>ally<br />
{ System.out.pr<strong>in</strong>tln("func1() verlassen !");<br />
}<br />
}<br />
}<br />
public void func2()<br />
{ try<br />
{ System.out.pr<strong>in</strong>tln("<strong>in</strong> func2() : Aufruf von func3()");<br />
func3();<br />
System.out.pr<strong>in</strong>tln("normales Ende von try <strong>in</strong> func2()!");<br />
return;<br />
}<br />
catch (RuntimeException e)<br />
{ System.out.pr<strong>in</strong>t("Exception-Handler <strong>in</strong> func2() : ");<br />
System.out.pr<strong>in</strong>tln(e.getMessage());<br />
}<br />
f<strong>in</strong>ally<br />
{ System.out.pr<strong>in</strong>tln("func2() verlassen !");<br />
}<br />
}<br />
public void func3()<br />
{ try<br />
{ System.out.pr<strong>in</strong>tln("<strong>in</strong> func3() : Exception wird geworfen");<br />
throw new RuntimeException("Demo-Exception !");<br />
}<br />
catch (ArithmeticException e)<br />
{ System.out.pr<strong>in</strong>t("Exception-Handler <strong>in</strong> func3() : ");<br />
System.out.pr<strong>in</strong>tln(e.getMessage());<br />
}<br />
f<strong>in</strong>ally<br />
{ System.out.pr<strong>in</strong>tln("func3() verlassen !");<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ ExceptDemo ed = new ExceptDemo();<br />
ed.func1();<br />
}<br />
<strong>in</strong> func1() : Aufruf von func2()<br />
<strong>in</strong> func2() : Aufruf von func3()<br />
<strong>in</strong> func3() : Exception wird geworfen<br />
func3() verlassen !<br />
Exception-Handler <strong>in</strong> func2() : Demo-Exception !<br />
func2() verlassen !<br />
normales Ende von try <strong>in</strong> func1()!<br />
func1() verlassen !
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 351 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Überblick<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (1)<br />
◇ <strong>Java</strong> behandelt Dateien als sequentielle Folge von Bytes (Byte-Streams)<br />
◇ In der IO-Bibliothek (Package java.io) s<strong>in</strong>d zahlreiche Klassen def<strong>in</strong>iert, die das Arbeiten mit Dateien unter-<br />
stützen.<br />
Die wichtigsten dieser Klassen s<strong>in</strong>d :<br />
▻ die File-Stream-Klassen zum sequentiellen Zugriff<br />
• FileInputStream (byteweises Lesen)<br />
• FileOutputStream (byteweises Schreiben)<br />
• FileReader (zeichenweises Lesen)<br />
• FileWriter (zeichenweises Schreiben)<br />
▻ e<strong>in</strong>e Klasse zum wahlfreien Zugriff (Lesen und Schreiben)<br />
• RandomAccessFile<br />
▻ Klassen für den Zugriff zum Dateisystem<br />
• FileDescriptor<br />
• File<br />
◇ Auszugsweises Klassendiagramm :<br />
Anmerkungen :<br />
▻ Das Diagramm beschränkt sich auf die Datei-E<strong>in</strong>gabe-Stream-Klassen (FileInputStream, FileReader).<br />
▻ Für die Datei-Ausgabe-Stream-Klassen (FileOutputStream, FileWriter) bestehen analoge Ableitungs-<br />
und Nutzungsbeziehungen.<br />
Deren – direkte oder <strong>in</strong>direkte – Basisklassen s<strong>in</strong>d OutputStream bzw Writer.<br />
▻ Die IO-Bibliothek enthält e<strong>in</strong>e Reihe weiterer – hier nicht aufgeführter – Streamklassen, die zumeist von<br />
InputStream oder Reader (bzw OutputStream oder Writer) direkt oder <strong>in</strong>direkt abgeleitet s<strong>in</strong>d.<br />
FilterInputStream<br />
InputStream<br />
BufferedInputStream DataInputStream<br />
FileInputStream<br />
Reader<br />
InputStreamReader<br />
FileReader<br />
FileDescriptor<br />
File<br />
BufferedReader<br />
RandomAccessFile
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 352 – 01 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die Klasse File<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (2-1)<br />
◇ Objekte dieser Klasse repräsentieren Zugriffspfade (zu Dateien bzw Directories) im Dateisystem.<br />
◇ Wesentliche Funktionalitäten :<br />
▻ Speicherung e<strong>in</strong>es Datei- bzw Directory-Zugriffspfades <strong>in</strong> e<strong>in</strong>er abstrakten system-unabhängigen Darstellung,<br />
sowie Bereitstellung von Informationen über denselben<br />
▻ Ermittlung diverser Eigenschaften e<strong>in</strong>er repräsentierten Datei (bzw e<strong>in</strong>es repräsentierten Directories)<br />
▻ Manipulation von Dateisystem-E<strong>in</strong>trägen (Erzeugen, Löschen, Änderung bestimmter Eigenschaften)<br />
◇ Der repräsentierte Zugriffspfad kann durch e<strong>in</strong>en absoluten oder e<strong>in</strong>en relativen Pfadnamen bezeichnet se<strong>in</strong>.<br />
E<strong>in</strong> relativer Pfadname wird immer auf das aktuelle Arbeitsdirectory des Users bezogen (Wert der System Property<br />
user.dir). Typischerweise handelt es sich hierbei um das Directory, aus dem die JVM gestartet wurde.<br />
◇ Zugriffspfade bestehen aus :<br />
▻ e<strong>in</strong>em optionalen betriebsystem-abhängigen Prefix-Str<strong>in</strong>g (z.B. "D:\\", "E:" oder "/")<br />
▻ e<strong>in</strong>er Folge von ke<strong>in</strong>em oder mehr Namen-Str<strong>in</strong>gs, die jeweils e<strong>in</strong> Directory bzw (nur der letzte Str<strong>in</strong>g) e<strong>in</strong>e<br />
Datei bezeichnen. Die e<strong>in</strong>zelnen Namen-Str<strong>in</strong>gs s<strong>in</strong>d durch e<strong>in</strong> betriebssystem-abhängiges Trennzeichen separiert.<br />
Das betriebssystem-abhängige Trennzeichen ist der Wert der System Property file.separator.<br />
Es steht auch als öffentliche statische Datenkomponente der Klasse File zur Verfügung :<br />
public static f<strong>in</strong>al char separatorChar; bzw<br />
public static f<strong>in</strong>al Str<strong>in</strong>g separator; (Str<strong>in</strong>g mit e<strong>in</strong>em Zeichen)<br />
◇ Konstruktoren :<br />
▻ public File(Str<strong>in</strong>g path)<br />
Erzeugung e<strong>in</strong>es neuen File-Objekts, das den Zugriffspfad path repräsentiert.<br />
Falls path==null ist, wird e<strong>in</strong>e NullPo<strong>in</strong>terException geworfen.<br />
▻ public File(Str<strong>in</strong>g dirName, Str<strong>in</strong>g name)<br />
Erzeugung e<strong>in</strong>es neuen File-Objekts, das den aus dirName und name gebildeten Zugriffspfad repräsentiert.<br />
(E<strong>in</strong>trag name im Directory dirName).<br />
Äquivalent zu : File(dirName + File.separator + name)<br />
Falls name==null ist, wird e<strong>in</strong>e NullPo<strong>in</strong>terException geworfen.<br />
▻ public File(File fileDir, Str<strong>in</strong>g name)<br />
Erzeugung e<strong>in</strong>es neuen File-Objekts, das den Zugriffspfad repräsentiert, der aus dem E<strong>in</strong>trag name <strong>in</strong> dem<br />
durch fileDir repräsentierten Directory gebildet wird,<br />
Äquivalent zu : File(fileDir.getPath(), name)<br />
Falls name==null ist, wird e<strong>in</strong>e NullPo<strong>in</strong>terException geworfen.<br />
▻ public File(URI uri)<br />
Erzeugung e<strong>in</strong>es neuen File-Objekts, dessen repräsentierter Zugriffspfad durch Konvertierung des Unified<br />
Resource Identifiers erhalten wird, der durch das URI-Objekt uri repräsentiert wird. Es muß sich hierbei<br />
um den Resource Identifier e<strong>in</strong>er Datei handeln (Beg<strong>in</strong>n mit file:)<br />
Falls uri==null ist, wird e<strong>in</strong>e NullPo<strong>in</strong>terException geworfen.<br />
Falls uri ke<strong>in</strong>e Datei repräsentiert, wird e<strong>in</strong>e IllegalArgumentException geworfen.<br />
◇ Der durch e<strong>in</strong> File-Objekt repräsentierte Zugriffspfad muß nicht e<strong>in</strong>en tatsächlich existierenden Dateisystem-E<strong>in</strong>trag<br />
referieren.<br />
Zur Überprüfung, ob e<strong>in</strong> entsprechender Dateisystem-E<strong>in</strong>trag vorhanden ist, d.h. durch das File-Objekt also tat-<br />
sächlich e<strong>in</strong>e Datei oder e<strong>in</strong> Directory repräsentiert wird, dient die Memberfunktion<br />
▻ public boolean exists()<br />
Funktionswert : true, wenn der E<strong>in</strong>trag existiert,<br />
false, wenn der E<strong>in</strong>trag nicht existiert
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 352 – 02 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Die Klasse File, Forts.<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (2-2)<br />
◇ Methoden zum Erzeugen neuer Dateisystem-E<strong>in</strong>träge<br />
▻ public boolean createNewFile() throws IOException<br />
Diese Methode erzeugt e<strong>in</strong>e neue leere Datei mit dem vom aktuellen File-Objekt repräsentierten Zugriffspfad,<br />
falls noch ke<strong>in</strong>e Datei mit diesem Zugriffspfad existiert.<br />
Funktionswert : true, falls die Datei erzeugt werden konnte<br />
false, falls e<strong>in</strong>e Datei mit dem Zugriffspfad bereits existiert hat.<br />
Falls e<strong>in</strong> I/O-Fehler auftritt, wird e<strong>in</strong>e IOException geworfen.<br />
▻ public boolean mkdir()<br />
Diese Methode erzeugt e<strong>in</strong>e neues Directory mit dem vom aktuellen File-Objekt repräsentierten Zugriffspfad<br />
Funktionswert : true, falls das Directory erzeugt werden konnte, andernfalls false<br />
▻ public boolean mkdirs()<br />
Diese Methode erzeugt e<strong>in</strong> neues Directory mit dem vom aktuellen File-Objekt repräsentierten Zugriffspfad<br />
sowie gegebenenfalls alle noch nicht existierenden Eltern-Directories.<br />
Funktionswert : true, falls das Directory und alle noch nicht existierenden Eltern-Directories erzeugt<br />
werden konnten<br />
false, falls das Directory nicht erzeugt werden konnte.<br />
Anm. : In diesem Fall können durchaus e<strong>in</strong>ige Eltern-Directories erzeugt worden se<strong>in</strong>.<br />
◇ Methoden zur Ermittlung von Informationen über Dateisystem-E<strong>in</strong>träge<br />
▻ public Str<strong>in</strong>g getAbsolutePath() Rückgabe des absoluten Pfadnamens<br />
▻ public Str<strong>in</strong>g getCanonicalPath() Rückgabe des kanonischen Pfadnamens<br />
▻ public long length() Rückgabe der Dateilänge, bei Directories undef<strong>in</strong>ierter Funktionswert<br />
▻ public boolean isDirectory() true, wenn E<strong>in</strong>trag existiert und Directory ist, sonst false<br />
▻ public boolean isFile() true, wenn E<strong>in</strong>trag existiert und normale Datei ist, sonst false<br />
▻ public boolean isHidden() true, wenn E<strong>in</strong>trag existiert und verborgen ist, sonst false<br />
▻ public boolean canWrite() true, wenn E<strong>in</strong>trag existiert und geändert werden kann, sonst false<br />
▻ public boolean canRead() true, wenn E<strong>in</strong>trag existiert und gelesen werden kann, sonst false<br />
▻ public Str<strong>in</strong>g[] list() Wenn E<strong>in</strong>trag e<strong>in</strong> Directory ist : Rückgabe e<strong>in</strong>er Auflistung aller <strong>in</strong> ihm<br />
enthaltenen E<strong>in</strong>träge als Str<strong>in</strong>g-Array (ausser "." und "..")<br />
Wenn E<strong>in</strong>trag ke<strong>in</strong> Directory ist : Rückgabe von null<br />
▻ public File[] listFiles() Wie list(), nur Rückgabe der E<strong>in</strong>träge als File-Array<br />
◇ Methoden zur Veränderung von Dateisystem-E<strong>in</strong>trägen<br />
▻ public boolean renameTo(File newPath)<br />
Umbenennen / Verschieben des aktuell repräsentierten Dateisystem-E<strong>in</strong>trags.<br />
Der Dateisystem-E<strong>in</strong>trag wird anschliessend durch das File-Objekt newPath repräsentiert.<br />
Der vom aktuellen Objekt bisher repräsentierte E<strong>in</strong>trag existiert anschliessend nicht mehr.<br />
Funktionswert : true, falls Umbenennen / Verschieben erfolgreich war, andernfalls false<br />
Falls newPath==null ist, wird e<strong>in</strong>e NullPo<strong>in</strong>terException geworfen.<br />
▻ public boolean delete()<br />
Löschen des aktuell repräsentierten Dateisystem-E<strong>in</strong>trags. E<strong>in</strong> zu löschendes Directory muss es leer se<strong>in</strong>.<br />
Funktionswert : true, falls erfolgreich gelöscht werden konnte, andernfalls false<br />
◇ Es existieren noch zahlreiche weiterer Methoden.<br />
◇ Alle Methoden, die zu e<strong>in</strong>er System Property zugreifen oder e<strong>in</strong>en Zugriff zum Dateisystem bewirken, werfen e<strong>in</strong>e<br />
SecurityException, wenn der Zugriff nicht zulässig ist.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 352 – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Demoprogramm 1 zur Klasse File<br />
// TestRename.java<br />
import java.io.*;<br />
Beispiele für Programmaufruf und -ausgabe<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (2-3)<br />
public class TestRename<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{<br />
if (args.lengthjava TestRename ftest2.txt ftest2.dat<br />
Dateigroesse : 33 Bytes<br />
rename erfolgreich<br />
alter Pfad : ftest2.txt existiert nicht mehr<br />
neuer Pfad : ftest2.dat<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java TestRename ftest2.txt ftest2.dat<br />
Quellpfad "ftest2.txt" existiert nicht --> neu erzeugt<br />
Dateigroesse : 0 Bytes<br />
rename nicht erfolgreich
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 352 – 04 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Demoprogramm 2 zur Klasse File<br />
// ListDir.java<br />
import java.io.*;<br />
Beispiele für Programmaufruf und -ausgabe<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (2-4)<br />
public class ListDir<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
try<br />
{ if (args.lengthjava ListDir me<strong>in</strong>dir<br />
"me<strong>in</strong>dir" existiert nicht !<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java ListDir ftestdir<br />
"E:\<strong>Java</strong>\fhm\ee\vorl\fileacc\ftestdir" ist ke<strong>in</strong> Directory!<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java ListDir .<br />
Inhalt des Directories "E:\<strong>Java</strong>\fhm\ee\vorl\fileacc\." :<br />
FileTest1.java<br />
FileTest1.class<br />
ftest.txt<br />
ftest2.dat<br />
TestRename.java<br />
TestRename.class<br />
ftest1.dat<br />
ftest3.txt<br />
testren1.txt<br />
testren2.txt<br />
ftestdir<br />
ListDir.java<br />
ListDir.class
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 353 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die Klasse FileDescriptor<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Objekte dieser Klasse bilden e<strong>in</strong> Handle zu der vom jeweiligen Betriebssystem für e<strong>in</strong>e geöffnete Datei (allgeme<strong>in</strong>er :<br />
für e<strong>in</strong>en geöffneten Stream) angelegten Verwaltungsstruktur.<br />
◇ Jedes Objekt, über dem e<strong>in</strong> Zugriff zu e<strong>in</strong>er Datei erfolgt (Objekt e<strong>in</strong>er File-Stream-Klasse bzw der Klasse<br />
RandomAccessFile) ist mit e<strong>in</strong>em FileDescriptor-Objekt assoziiert. Dieses stellt die Verb<strong>in</strong>dung zur<br />
Dateiverwaltung auf der Betriebssystemebene her.<br />
◇ E<strong>in</strong> FileDescriptor-Objekt wird üblicherweise implizit beim Anlegen e<strong>in</strong>es Objekts für den Dateizugriff und<br />
dem damit verbundenen Öffnen der Datei erzeugt.<br />
E<strong>in</strong> explizites Erzeugen e<strong>in</strong>es FileDescriptor-Objekts ist weder üblich noch s<strong>in</strong>nvoll.<br />
Mit dem zur Verfügung stehenden öffentlichen parameterlosen Konstruktor kann nur e<strong>in</strong> ungültiges Objekt, das an ke<strong>in</strong>e<br />
geöffnete Datei gebunden ist, erzeugt werden.<br />
◇ Für Objekte der Klassen FileInputStream, FileOutputStream und RandomAccessFile (nicht jedoch<br />
der Klassen FileReader und FileWriter) kann mit der jeweiligen Methode getFD() das mit ihnen<br />
assoziierte FileDescriptor-Objekt ermittelt werden.<br />
◇ Bei der Erzeugung e<strong>in</strong>es neuen File-Stream-Objekts kann auch e<strong>in</strong> existierendes FileDescriptor-Objekt<br />
verwendet werden. Das neue File-Stream-Objekt referiert dann dieselbe Datei wie das File-Stream-Objekt, das das<br />
FileDescriptor-Objekt geliefert hat. Damit kann über zwei (oder mehr) Stream-Objekte zur selben Datei zuge-<br />
griffen werden.<br />
◇ Methoden der Klasse FileDescriptor<br />
▻<br />
▻<br />
public boolean valid()<br />
Überprüfung, ob das FileDescriptor-Objekt gültig, d.h. an e<strong>in</strong>e geöffnete Datei gebunden ist.<br />
Funktionswert : true, falls das Objekt an e<strong>in</strong>e geöffnete Datei gebunden ist, andernfalls false<br />
public void sync() throws SyncFailedException<br />
Synchronisation aller System-Buffer, die Daten für die referierte Datei enthalten, mit dem physikalischen<br />
Speichermedium.<br />
Die Funktion kehrt erst dann zurück, wenn alle relevanten Daten auf das physikalische Medium geschrieben<br />
worden s<strong>in</strong>d.<br />
Die Methode sorgt nicht für das Herausschreiben von Buffern, die <strong>in</strong> dem Anwendungsprogramm verwendet<br />
werden (z.B. von e<strong>in</strong>em BufferedOutputStream-Objekt). Diese müssen gegebenenfalls zuvor an das<br />
Betriebssystem übergeben werden (mittels der jeweiligen Stream-Methode flush()).<br />
Wenn e<strong>in</strong>e Synchronisation der System-Buffer mit dem physikalischen Speichermedium nicht sichergestellt<br />
werden kann, wird e<strong>in</strong>e SyncFailedException geworfen.<br />
◇ Die Klasse FileDscriptor stellt Handle zu den Standard-Streams als öffentliche statische Datenkompo-<br />
nenten zur Verfügung<br />
Normalerweise werden diese jedoch nicht direkt von User-Code verwendet sondern <strong>in</strong>direkt über die durch die Klasse<br />
System bereitgestellten Standard-Stream-Objekte.<br />
▻ public static f<strong>in</strong>al FileDescriptor <strong>in</strong> Handle zum Standard-E<strong>in</strong>gabe-Stream<br />
▻ public static f<strong>in</strong>al FileDescriptor out Handle zum Standard-Ausgabe-Stream<br />
▻ public static f<strong>in</strong>al FileDescriptor err Handle zum Standard-Fehlerausgab-Stream
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 354 – 01 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die File-Stream-Klassen<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (4-1)<br />
◇ Objekte dieser Klassen ermöglichen e<strong>in</strong>en sequentiellen Zugriff zu Dateien :<br />
▻ FileInputStream (byteweises Lesen)<br />
▻ FileOutputStream (byteweises Schreiben)<br />
▻ FileReader (zeichenweises Lesen)<br />
▻ FileWriter (zeichenweises Schreiben)<br />
◇ Überblick über die Konstruktoren :<br />
Beispiel :<br />
● Bei der Erzeugung e<strong>in</strong>es File-Stream-Objekts für e<strong>in</strong>en Dateizugriffspfad (Param. vom Typ Str<strong>in</strong>g bzw. File)<br />
▻ wird die referierte Datei – falls sie vorhanden und die jeweilige Zugriffsart zulässig ist – geöffnet<br />
▻ und e<strong>in</strong> an sie gebundenes FileDescriptor-Objekt erzeugt.<br />
Die Konstruktoren der Datei-Ausgabe-Stream-Klassen versuchen die referierte Datei neu anzulegen, falls sie nicht<br />
existiert.<br />
Kann e<strong>in</strong>e Datei nicht geöffnet werden (z.B. weil der Zugriffspfad e<strong>in</strong> Directory referiert), wird e<strong>in</strong>e<br />
FileNotFoundException geworfen.<br />
● Bei der Erzeugung e<strong>in</strong>es File-Stream-Objekts für e<strong>in</strong>e bereits geöffnete Datei (Parameter vom Typ<br />
FileDescriptor)<br />
▻ wird zu der Datei – falls die jeweilige Zugriffsart zulässig ist – e<strong>in</strong> weiterer Zugriffskanal geöffnet<br />
● Alle Konstruktoren werfen e<strong>in</strong>e SecurityException, wenn e<strong>in</strong> SecurityManager-Objekt existiert und<br />
dieser feststellt, dass die jeweilige Zugriffsart nicht zulässig ist.<br />
◇ Schliessen e<strong>in</strong>es File-Streams<br />
mittels der für alle File-Stream-Klassen existierenden Methode<br />
▻<br />
1.Parameter 2. Parameter existiert für Klasse<br />
Str<strong>in</strong>g path<br />
Dateizugriffspfad FileInputStream<br />
FileOutputStream<br />
File fil ------- FileReader<br />
repräsentiert Dateizugriffspfad FileWriter<br />
FileDescriptor fd<br />
referiert geöffnete Datei<br />
Str<strong>in</strong>g path<br />
Dateizugriffspfad boolean app FileOutputStream<br />
wenn true : Anhängen an Datei (append) FileWriter<br />
File fil wenn false : Schreiben am Dateianfang<br />
repräsentiert Dateizugriffspfad<br />
public FileInputStream(File datei) throws FileNotFoundException<br />
public void close() throws IOException<br />
Die Methode schliesst den File-Stream und damit die referierte Datei und gibt alle sonstigen mit dem Stream<br />
assoziierten System-Resourcen frei.<br />
Beim Auftritt e<strong>in</strong>es I/O-Fehlers wird e<strong>in</strong>e IOException geworfen.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 354 – 02 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Die File-Stream-Klassen, Forts.<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (4-2)<br />
◇ Ermittlung des assoziierten FileDescriptor-Objekts<br />
Dies ist nur für die Klassen FileInputStream und FileOutputStream möglich.<br />
Für diese Klassen existiert die Methode<br />
▻<br />
public f<strong>in</strong>al FileDescriptor getFD() throws IOException<br />
Die Methode gibt das mit dem Stream-Objekt assoziierte FileDescriptor-Objekt zurück.<br />
Beim Auftritt e<strong>in</strong>es I/O-Fehlers wird e<strong>in</strong>e IOException geworfen.<br />
◇ Methoden zum Dateizugriff<br />
Die File-Stream-Klassen stellen das von ihrer jeweiligen Basisklasse def<strong>in</strong>ierte Stream-Zugriffs-Interface zur<br />
Verfügung. Die wichtigsten Methoden dieser Interfaces s<strong>in</strong>d :<br />
Methode Wirkung existiert für Klasse<br />
void write(<strong>in</strong>t b) Schreiben des Bytes b FileOutputStream<br />
void write(byte[] buff) Schreiben des Byte-Buffers buff<br />
void write(byte[] buff, Schreiben von len Bytes aus buff<br />
<strong>in</strong>t pos, <strong>in</strong>t len) ab Position pos<br />
void write(<strong>in</strong>t c) Schreiben des Zeichens c FileWriter<br />
void write(char[] buff) Schreiben des Zeichen-Buffers buff<br />
void write(char[] buff, Schreiben von len Zeichen aus buff<br />
<strong>in</strong>t pos, <strong>in</strong>t len) ab Position pos<br />
void write(Str<strong>in</strong>g str) Schreiben des Str<strong>in</strong>gs str<br />
void flush() Herausschreiben aller Schreib-Buffer FileOutputStream<br />
(Übergabe an das Betriebssystem) FileWriter<br />
<strong>in</strong>t read() Lesen e<strong>in</strong>es Bytes (= Funktionswert) FileInputStream<br />
Funktionswert == -1 bei Dateiende<br />
<strong>in</strong>t read(byte[] buff) Lesen e<strong>in</strong>er Byte-Folge,<br />
Ablage im Buffer buff<br />
Funktionswert : Anzahl gelesener Bytes<br />
bzw –1 bei Dateiende<br />
<strong>in</strong>t read() Lesen e<strong>in</strong>es Zeichens (= Funktionswert) FileReader<br />
Funktionswert == -1 bei Dateiende<br />
<strong>in</strong>t read(char[] buff) Lesen e<strong>in</strong>er Zeichen-Folge,<br />
Ablage im Buffer buff<br />
Funktionswert : Anzahl gelesener Zeichen<br />
bzw –1 bei Dateiende<br />
long skip(long n) Überlesen der nächsten n Bytes FileInputStream<br />
bzw der nächsten n Zeichen FileReader<br />
Es existieren noch weitere Methoden, mit denen auch Teile e<strong>in</strong>es Byte- bzw Zeichen-Arrays gelesen bzw Teile<br />
e<strong>in</strong>es Str<strong>in</strong>gs geschrieben werden können.<br />
Alle Methoden für den Dateizugriff werfen e<strong>in</strong>e IOException, wenn e<strong>in</strong> I/O-Fehler auftritt.<br />
alle Methoden s<strong>in</strong>d mit der throws-Klausel throws IOException def<strong>in</strong>iert.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 354 – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (4-3)<br />
• Demoprogramm zum Dateizugriff (Kopieren e<strong>in</strong>er Datei)<br />
// FileCopy.java<br />
import java.io.*;<br />
public class FileCopy<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
if (args.length =0)<br />
{<br />
out.write(buff, 0, len);<br />
}<br />
out.close();<br />
<strong>in</strong>.close();<br />
System.out.pr<strong>in</strong>tln("Kopieren der Dateien erfolgreich");<br />
}<br />
catch(IOException ex)<br />
{<br />
System.out.pr<strong>in</strong>tln("Exception : " + ex.getMessage());<br />
}<br />
Beispiel für Programmaufruf und -ausgabe<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java FileCopy ListDir.class ListDir.b<strong>in</strong><br />
Kopiert wird "ListDir.class" (Laenge : 1100 Bytes) nach "ListDir.b<strong>in</strong>"<br />
Kopieren der Dateien erfolgreich
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 355 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (5-1)<br />
• Schreiben und Lesen von Daten <strong>in</strong> B<strong>in</strong>ärdarstellung<br />
◇ Dies wird durch die beiden Klassen DataOutputStream und DataInputStream ermöglicht<br />
◇ Diese beiden Klassen implementieren jeweils e<strong>in</strong> Interface zum Schreiben bzw Lesen der <strong>in</strong>ternen B<strong>in</strong>ärdarstellung<br />
von Werten der e<strong>in</strong>fachen Datentypen <strong>in</strong> bzw aus Streams und damit auch <strong>in</strong> bzw aus Dateien.<br />
Zusätzlich ermöglichen sie e<strong>in</strong>e effiziente Umcodierung zwischen 16-Bit-Unicode-Zeichen und Bytefolgen<br />
für das Schreiben/Lesen von Str<strong>in</strong>gs (modifizierte UTF-8-Codierung)<br />
◇ Objekte dieser Klassen wirken als Filter, die e<strong>in</strong>en zugrundeliegenden Byte-Stream <strong>in</strong> geeigneter Weise umsetzen.<br />
E<strong>in</strong>e Referenz auf das zu filternde Byte-Stream-Objekt ist ihrem Konstruktor als Parameter zu übergeben :<br />
▻ public DataOutputStream(OutputStream out)<br />
▻ public DataInputStream(InputStream <strong>in</strong>)<br />
Das zu filternde Stream-Objekt kann natürlich auch e<strong>in</strong> Objekt der Klasse FileOutputStream (abgeleitet von<br />
OutputStream) bzw FileInputStream (abgeleitet von InputStream) se<strong>in</strong>.<br />
◇ Wichtigste Methoden der von DataOutputStream bzw DataInputStream implementierten Interfaces :<br />
Alle Methoden für den Stream-Zugriff werfen e<strong>in</strong>e IOException, wenn e<strong>in</strong> I/O-Fehler auftritt.<br />
Die meisten Lese-Methoden werfen beim vorzeitigen Erreichen des Stream-Endes e<strong>in</strong>e EOFException<br />
alle Methoden s<strong>in</strong>d mit der throws-Klausel throws IOException def<strong>in</strong>iert.<br />
◇ Beide Klassen stellen noch weitere Methoden zum Stream-Zugriff zur Verfügung.<br />
◇ Anmerkung zur modifizierten UTF-8-Codierung :<br />
DataInputStream FileInputStream<br />
DataOutputStream DataInputStream Datentyp<br />
(Schreiben) (Lesen)<br />
void writeBoolean(boolean b) boolean readBoolean() boolean<br />
void writeByte(<strong>in</strong>t b) byte readByte() byte<br />
void writeChar(<strong>in</strong>t c) char readChar() char<br />
void writeShort(<strong>in</strong>t s) short readShort() short<br />
void writeInt(<strong>in</strong>t i) <strong>in</strong>t readInt() <strong>in</strong>t<br />
void writeLong(long l) long readLong() long<br />
void writeFloat(float f) float readFloat() float<br />
void writeDouble(double d) double readDouble() double<br />
void writeBytes(Str<strong>in</strong>g str) --- Str<strong>in</strong>g als Byte-Folge<br />
void writeChars(Str<strong>in</strong>g str) --- Str<strong>in</strong>g als Char-Folge<br />
void writeUTF(Str<strong>in</strong>g str) Str<strong>in</strong>g readUTF() Str<strong>in</strong>g (UTF-8-Cod.)<br />
void write(<strong>in</strong>t b) <strong>in</strong>t read() byte<br />
void write(byte[] ba) <strong>in</strong>t read(byte[] ba) byte-Array<br />
void write(byte[] ba, <strong>in</strong>t read(byte[] ba, byte-Array (Länge<br />
<strong>in</strong>t off, <strong>in</strong>t len) <strong>in</strong>t off, <strong>in</strong>t len len ab Offset off)<br />
▻ UTF = Universal Transfer Format : effiziente Codierung von Unicode-Zeichen durch 1, 2 und 3 Bytes<br />
▻ Zeichen zwischen '\u0001' und '\u007F' durch e<strong>in</strong> Byte : 01 ... 7F<br />
Zeichen zwischen '\u0080' und '\u07FF' durch zwei Bytes : C2 80 ... DF BF<br />
Zeichen zwischen '\u0800' und '\uFFFF' durch drei Bytes : E0 A0 80 ... EF BF BF<br />
der NUL-Character (das Zeichen '\u0000') durch zwei Bytes : C0 80<br />
▻ writeUTF(str) schreibt vor der eigentlichen den Str<strong>in</strong>g str codierenden Bytefolge deren Länge als<br />
short-Wert (2 Bytes) <strong>in</strong> den Stream.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 355 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (5-2)<br />
• Demoprogramm zum Schreiben von Daten <strong>in</strong> B<strong>in</strong>ärdarstelung<br />
// DataStreamDemo.java<br />
import java.io.*;<br />
public class DataStreamDemo<br />
{<br />
public static Str<strong>in</strong>g byteToHex(byte b)<br />
{<br />
Str<strong>in</strong>g str = Integer.toHexStr<strong>in</strong>g(b & 0x00FF);<br />
if (str.length() == 1)<br />
str = '0' + str;<br />
return str;<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
if (args.length java DataStreamDemo demo.dat<br />
Inhalt der Datei "demo.dat" :<br />
01 00 00 00 7c 40 09 1e b8 51 eb 85 1f 00 12 48 61 6c 6c 6f 20 4a 61 76 61<br />
2d 46 72 65 75 6e 64 65 00 0d 7f c2 80 df bf e0 a0 80 ef bf bf c0 80
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 356 – 01 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Zugriff zu Textdateien<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (6-1)<br />
◇ Der Zugriff zu Textdateien erfolgt s<strong>in</strong>nvollerweise über puffernde Zeichen-Stream-Objekte.<br />
Diese werden durch die Klassen BufferedWriter (abgeleitet von Writer) und BufferedReader (abge-<br />
leitet von Reader) zur Verfügung gestellt.<br />
◇ Die Objekte beider Klassen kapseln jeweils e<strong>in</strong> anderes Writer- bzw Reader-Objekt.<br />
E<strong>in</strong>e Referenz auf dieses ist dem jeweiligen Konstruktor als Parameter zu übergeben.<br />
▻ public BufferedWriter(Writer out)<br />
▻ public BufferedReader(Reader <strong>in</strong>)<br />
Durch Verwendung e<strong>in</strong>es FileWriter- (<strong>in</strong>direkt abgeleitet von Writer) bzw FileReader- (<strong>in</strong>direkt<br />
abgeleitet von Reader) Objekts als Konstruktor-Parameter erhält man pufferende Zeichen-Stream-Objekte für<br />
den Dateizugriff.<br />
◇ Obige Konstruktoren erzeugen Zeichen-Stream-Objekte, deren Puffer e<strong>in</strong>e Standard-Default-Größe besitzen.<br />
Diese Grösse ist für die meisten Anwendungsfälle groß genug.<br />
Es existieren aber auch Konstruktoren, denen die Puffergröße als zweiter Parameter zu übergeben ist.<br />
◇ Methoden der Klassen BufferedWriter und BufferedReader<br />
▻ Beide Klassen stellen alle Methoden des jeweiligen Stream-Zugriffs-Interfaces der Klassen FileWriter<br />
bzw FileReader sowie die Methode close() zur Verfügung<br />
▻ Darüberh<strong>in</strong>aus besitzen sie aber e<strong>in</strong>ige zusätzliche Memberfunktionen :<br />
Auch diese Methoden werfen e<strong>in</strong>e IOException, wenn e<strong>in</strong> I/O-Fehler auftritt.<br />
sie s<strong>in</strong>d mit der throws-Klausel throws IOException def<strong>in</strong>iert.<br />
▻ Zusätzlich verfügt die Klasse BufferedReader über Memberfunktionen zum Markieren und späteren<br />
Wiedere<strong>in</strong>nehmen e<strong>in</strong>er bestimmten Position im Stream.<br />
• Weitere Stream-Filter-Klassen<br />
BufferedReader FileReader<br />
Methode Wirkung existiert für Klasse<br />
void newL<strong>in</strong>e() Schreiben e<strong>in</strong>es Zeilenendes BufferedWriter<br />
Str<strong>in</strong>g readL<strong>in</strong>e() Lesen e<strong>in</strong>er Zeile, Rückgabe als Str<strong>in</strong>g BufferedReader<br />
Rückgabe von null, wenn am Dateiende<br />
◇ Im Package java.io sowie <strong>in</strong> e<strong>in</strong>igen anderen Packages (z.B. java.util.zip) s<strong>in</strong>d noch weitere Stream-<br />
Klassen enthalten, die als Filter von anderen Stream-Objekten und damit auch von File-Stream-Objekten e<strong>in</strong>gesetzt<br />
werden können. Dadurch lassen sich File-Stream-Objekte mit weiteren speziellen Eigenschaften versehen.<br />
◇ Beispiele :<br />
FilterReader abstrakte Basisklasse für – eigene – Reader-Filter-Klassen<br />
L<strong>in</strong>eNumberReader Klasse zum zeilenorientierten Lesen aus Zeichen-Streams<br />
Pr<strong>in</strong>tWriter Klasse zur Ausgabe der externen Darstellung von Datenwerten <strong>in</strong> Zeichen-Streams<br />
Pr<strong>in</strong>tStream Klasse zur Ausgabe der externen Darstellung von Datenwerten <strong>in</strong> Byte-Streams<br />
PushbackInputStream Klasse, die die Rückgabe gelesener Bytes <strong>in</strong> e<strong>in</strong>en E<strong>in</strong>gabe-Byte-Stream ermöglicht<br />
CheckedOutputStream Klasse, die an e<strong>in</strong>en Ausgabe-Stream e<strong>in</strong>e Prüfsumme anhängt.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 356 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (6-2)<br />
• Demoprogramm zum Zugriff zu Textdateien : Ausgabe e<strong>in</strong>er Textdatei am Bildschirm<br />
// TextFileList.java<br />
import java.io.*;<br />
public class TextFileList<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
if (args.length
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 356 – 03 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (6-3)<br />
• Formatiertes Schreiben <strong>in</strong> Textdateien (ab dem JDK 5.0)<br />
◇ Mittels e<strong>in</strong>es Objekts der Klasse Formatter<br />
▻ Die Klasse Formatter (Package java.util) dient zum Erzeugen formatierter Textdarstellungen.<br />
Formatter-Objekte können auch an Dateien gebunden werden. Damit lassen sie sich zur formatierten Ausgabe<br />
<strong>in</strong> Textdateien e<strong>in</strong>setzen.<br />
▻ Die jeweilige Datei ist durch Übergabe e<strong>in</strong>es die Datei referierenden Objekts an den Konstruktor festzulegen.<br />
E<strong>in</strong> derartiges Objekt kann u.a. se<strong>in</strong> :<br />
▹ Objekt der Klasse FileOutputStream (z.B. Konstruktor Formatter(OutputStream os))<br />
▸ Objekt der Klasse FileWriter (z.B. Konstruktor Formatter(Appendable a))<br />
▸ Objekt der Klasse File (z.B. Konstruktor Formatter(File file))<br />
▻ Mit der Formatter-Methode<br />
Formatter format(Str<strong>in</strong>g format, Object... args)<br />
kann formatierter Text <strong>in</strong> die Datei geschrieben werden.<br />
Die Parameter entsprechen den Parametern der Pr<strong>in</strong>tStream-(und Pr<strong>in</strong>tWriter-) Methode pr<strong>in</strong>tf() :<br />
- format ist der anzuwendende Format-Str<strong>in</strong>g<br />
Syntax und Semantik des Format-Str<strong>in</strong>gs ist die gleiche wie beim Format-Str<strong>in</strong>g der Methode pr<strong>in</strong>tf()<br />
- args s<strong>in</strong>d die zu schreibenden (und <strong>in</strong> Textdarstellung umzuwandelnden) Werte<br />
Rückgabewert : aktuelles Formatter-Objekt<br />
▻ Beispiel :<br />
Formatter FileOutputStream<br />
Formatter FileWriter<br />
Formatter File<br />
public void formOutDouble1(Str<strong>in</strong>g dpfad, <strong>in</strong>t anz) throws IOException<br />
{<br />
File datei = new File(dpfad);<br />
//Formatter form = new Formatter(datei);<br />
//Formatter form = new Formatter(new FileOutputStream(datei));<br />
Formatter form = new Formatter(new FileWriter(datei));<br />
Random rand = new Random();<br />
for (<strong>in</strong>t j=1; j
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 356 – 04 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (6-4)<br />
• Formatiertes Schreiben <strong>in</strong> Textdateien, Forts. (ab dem JDK 5.0)<br />
◇ Mittels der Pr<strong>in</strong>tStream- (und Pr<strong>in</strong>tWriter-) Methode pr<strong>in</strong>tf()<br />
▻ Die – u.a. für die Standardausgabe e<strong>in</strong>gesetzte –Klasse Pr<strong>in</strong>tStream ermöglicht die Ausgabe von Str<strong>in</strong>gs und<br />
der externen Textdarstellung von Datenwerten <strong>in</strong> beliebige Byte-Streams, somit auch <strong>in</strong> Dateien.<br />
▻ Analog dient die Klasse Pr<strong>in</strong>tWriter zur Ausgabe derartiger Informationen <strong>in</strong> Zeichen-Streams und damit<br />
ebenfalls <strong>in</strong> entsprechende Dateien.<br />
▻ Für beide Klassen ist die Datei bei der Objekt-Erzeugung durch Übergabe e<strong>in</strong>es sie referierenden Objekts an den<br />
jeweiligen Konstruktor festzulegen.<br />
U.a. existieren die folgenden Konstruktoren :<br />
▹ Pr<strong>in</strong>tStream(OutputStream os) (OutputStream ist u.a. Basisklasse von FileOutputStream)<br />
▹ Pr<strong>in</strong>tStream(File file)<br />
▹ Pr<strong>in</strong>tWriter(Writer out) (Writer ist u.a. Basisklasse von FileWriter)<br />
▹ Pr<strong>in</strong>tWriter(File file)<br />
▻ Beide Klassen stellen ab dem JDK 5.0 zur formatierten Ausgabe die Memberfunktion pr<strong>in</strong>tf() zur Verfügung<br />
▹ Klasse Pr<strong>in</strong>tStream : Pr<strong>in</strong>tStream pr<strong>in</strong>tf(Str<strong>in</strong>g format, Object... args)<br />
▹ Klasse Pr<strong>in</strong>tWriter : Pr<strong>in</strong>tWriter pr<strong>in</strong>tf(Str<strong>in</strong>g format, Object... args)<br />
Beschreibung der Parameter sowie der Wirkungsweise der Funktion siehe "Standardausgabe - Formatierte Ausgabe"<br />
▻ Beispiel :<br />
Pr<strong>in</strong>tStream FileOutputStream<br />
Pr<strong>in</strong>tStream File<br />
Pr<strong>in</strong>tWriter FileWriter<br />
Pr<strong>in</strong>tWriter File<br />
public void formOutDouble2(Str<strong>in</strong>g dpfad, <strong>in</strong>t anz) throws IOException<br />
{<br />
File datei = new File(dpfad);<br />
Pr<strong>in</strong>tStream prnt = new Pr<strong>in</strong>tStream(datei);<br />
//Pr<strong>in</strong>tStream prnt = new Pr<strong>in</strong>tStream(new FileOutputStream(datei));<br />
//Pr<strong>in</strong>tWriter prnt = new Pr<strong>in</strong>tWriter(datei);<br />
//Pr<strong>in</strong>tWriter prnt = new Pr<strong>in</strong>tWriter(new FileWriter(datei));<br />
Random rand = new Random();<br />
for (<strong>in</strong>t j=1; j
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 356 – 05 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (6-5)<br />
• Formatiertes Lesen aus Textdateien (ab dem JDK 5.0)<br />
◇ Hierfür lässt sich die Klasse Scanner e<strong>in</strong>setzen<br />
◇ Scanner-Objekte dienen zum Zergliedern und Interpretieren von Zeichenfolgen. Diese Zeichenfolgen können<br />
auch von Zeichen- und Byte-Streams und damit auch von Dateien geliefert werden.<br />
◇ Die jeweilige Zeichenquelle ist e<strong>in</strong>em Scanner-Objekt im Konstruktor zu übergeben, u.a. als Objekt der<br />
▻ Klasse FileInputStream (Konstruktor Scanner(InputStream source))<br />
▻ Klasse FileReader (Konstruktor Scanner(Readable source))<br />
▻ Klasse File (Konstruktor Scanner(File source))<br />
Scanner File *) *) bzw FileInputStream<br />
oder FileReader<br />
◇ Beschreibung der Funktionalität der Klasse Scanner siehe "Standard- E<strong>in</strong>- und Ausgabe <strong>in</strong> <strong>Java</strong>".<br />
◇ Beispiel :<br />
Funktion zum Lesen aus Textdateien, deren Inhalt pr<strong>in</strong>zipiell wie folgt aufgebaut ist.<br />
Die gelesenen Werte werden im gleichen Format <strong>in</strong> die Standard-Ausgabe ausgegeben<br />
(Memberfunktion der Klasse FormTextFileDemo)<br />
2 : 0,44507 0,06490<br />
3 : 0,25472 0,13943 0,40664<br />
1 : 0,96712<br />
6 : 0,78277 0,24195 0,54913 0,99872 0,71365 0,14333<br />
3 : 0,54464 0,03770 0,15014<br />
public void formInput() throws IOException<br />
{<br />
// Str<strong>in</strong>g dpfad ist Datenkomponente der Klasse FormTextFileDemo<br />
File datei = new File(dpfad);<br />
Scanner scan = new Scanner(datei);<br />
//Scanner scan = new Scanner(new FileInputStream(datei));<br />
//Scanner scan = new Scanner(new FileReader(datei));<br />
try<br />
{<br />
while (scan.hasNext())<br />
{<br />
<strong>in</strong>t anz = scan.nextInt();<br />
System.out.pr<strong>in</strong>tf("%d : ", anz);<br />
scan.next(); // Ueberlesen des ':'<br />
double d;<br />
for (<strong>in</strong>t i = 1; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 357 – 01 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Wahlfreier Zugriff zu Dateien<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (7-1)<br />
◇ Für den wahlfreien Zugriff zu Dateien steht die Klasse RandomAccessFile zur Verfügung.<br />
Diese Klasse ist von ke<strong>in</strong>er der File-Stream-Klassen sondern direkt von Object abgeleitet.<br />
◇ Durch Objekte dieser Klasse können Dateien für e<strong>in</strong>en wahlfreien Zugriff nur zum Lesen oder zum Lesen und<br />
Schreiben geöffnet werden.<br />
Der wahlfreie Zugriff wird durch die Möglichkeit zur expliziten Veränderung der aktuellen Bearbeitungsposition<br />
(File-Po<strong>in</strong>ter) realisiert.<br />
◇ Konstruktoren der Klasse RandomAccessFile<br />
▻ public RandomAccessFile(Str<strong>in</strong>g path, Str<strong>in</strong>g mode) throws FileNotFoundException<br />
▻ public RandomAccessFile(File fil, Str<strong>in</strong>g mode) throws FileNotFoundException<br />
Der erste Parameter referiert die zu bearbeitende Datei (über den Zugriffspfad bzw e<strong>in</strong> File-Objekt, das diesen<br />
repräsentiert)<br />
Der zweite Parameter legt die Zugriffsart fest :<br />
▻ "r" nur Lesen,<br />
▻ "rw" Lesen und Schreiben. ("rws" und "rwd" s<strong>in</strong>d auch zulässig)<br />
Die Konstruktoren versuchen die referierte Datei für die angegebene Zugriffsart zu öffnen.<br />
Falls die referierte Datei nicht existiert wird bei der Zugriffsart "rw" versucht, sie zu erzeugen.<br />
Die Konstruktoren können die folgenden Exceptions werfen :<br />
▻ FileNotFoundException, falls die referierte Datei nicht existiert (Zugriffsart "r") oder e<strong>in</strong> Directory ist<br />
oder nicht erzeugt werden kann oder aus e<strong>in</strong>em anderen Grund nicht geöffnet werden kann.<br />
▻ SecurityException, falls für die vorgesehene Zugriffsart ke<strong>in</strong>e Berechtigung besteht<br />
▻ IllegalArgumentException, falls e<strong>in</strong> nicht zulässiger Str<strong>in</strong>g für die Zugriffsart angegeben wird.<br />
◇ Methoden der Klasse RandomAccessFile zum Dateizugriff :<br />
Die Klasse stellt für den Dateizugriff die gleichnamigen Methoden mit gleicher Signatur wie die Klassen<br />
DataInputStream und DataOutputStream zur Verfügung.<br />
Wie bei diesen Klassen werfen die Zugriffsmethoden e<strong>in</strong>e IOException beim Auftritt e<strong>in</strong>es I/O-Fehlers.<br />
Die meisten Lesemethoden werfen darüber h<strong>in</strong>aus e<strong>in</strong>e EOFException beim vorzeitigen Erreichen des Dateiendes<br />
◇ Weitere Methoden der Klasse RandomAccessFile (Auswahl)<br />
Methode Wirkung<br />
void seek(long pos) Setzen der Bearbeitungsposition auf pos Bytes nach dem Dateianfang<br />
long getFilePo<strong>in</strong>ter() Rückgabe der aktuellen Bearbeitungsposition<br />
(<strong>in</strong> Bytes bezogen auf den Dateianfang)<br />
<strong>in</strong>t skipBytes(<strong>in</strong>t cnt) Versuch, die Bearbeitungsposition um cnt Bytes weiterzusetzen<br />
Rückgabe der Anzahl Bytes, um die tatsächlich weitergesetzt wurde<br />
Str<strong>in</strong>g readL<strong>in</strong>e() Lesen der nächsten Zeile (=Rückgabewert), Bytes werden zu Zeichen<br />
ergänzt (höherwertiges Byte == NUL-Byte)<br />
long length() Rückgabe der Dateilänge<br />
FileDescriptor getFD() Rückgabe des assoziierten FileDescriptor-Objekts<br />
void close() Schliessen der Datei und Freigabe aller belegten Resourcen<br />
Alle o.a. Methoden werfen e<strong>in</strong>e IOException wenn e<strong>in</strong> I/O-Fehler auftritt.<br />
sie s<strong>in</strong>d mit der throws-Klausel throws IOException def<strong>in</strong>iert.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 357 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Demoprogramm zum wahlfreien Dateizugriff<br />
// RandAccDemo.java<br />
Beispiele für Programmaufruf und -ausgabe<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> (7-2)<br />
// Zufallsgesteuerte Auswahl e<strong>in</strong>es Spruches aus e<strong>in</strong>er Textdatei mit Spruechen.<br />
// Die e<strong>in</strong>zelnen Sprueche s<strong>in</strong>d jeweils durch e<strong>in</strong>e Zeile,<br />
// die nur das Zeichen '*' enthaelt, getrennt.<br />
import java.io.*;<br />
public class RandAccDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
try<br />
{<br />
RandomAccessFile raf = new RandomAccessFile("sprueche.txt", "r");<br />
long pos = (long)(raf.length()*Math.random());<br />
raf.seek(pos);<br />
while((pos!=0) && ((char)raf.read()!='*'))<br />
raf.seek(--pos);<br />
<strong>in</strong>t ch;<br />
if (pos==0)<br />
System.out.pr<strong>in</strong>tln();<br />
while (((ch=raf.read())!=-1) && ((char)ch!='*'))<br />
{<br />
System.out.pr<strong>in</strong>t((char)ch);<br />
}<br />
System.out.pr<strong>in</strong>tln();<br />
raf.close();<br />
}<br />
catch (IOException ex)<br />
{<br />
System.out.pr<strong>in</strong>tln(ex);<br />
}<br />
}<br />
}<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java RandAccDemo<br />
Gut gehaengt ist besser als schlecht verheiratet.<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java RandAccDemo<br />
Es ist nicht genug, dass man redet,<br />
man muss auch richtig reden.<br />
E:\<strong>Java</strong>\fhm\ee\vorl\fileacc>java RandAccDemo<br />
E<strong>in</strong> Tor nur schliesst aus aeusserem Gehaben<br />
getrost auf e<strong>in</strong>es Menschen <strong>in</strong>nere Gaben.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 358 – 00 – TH – 01<br />
------------------------------------------------------------------------------------<br />
Dateizugriff <strong>in</strong> <strong>Java</strong> – Zusammenfassender Überblick<br />
Datei- bzw Verwendungsart Klasse Konstruktorparameter wichtige<br />
(Auswahl) Zugriffsmethoden<br />
sequentieller byteweiser FileInputStream File-Objekt oder read()<br />
Zugriff FileOutputStream Dateizugriffspfad write()<br />
sequentieller zeichenweiser FileReader File-Objekt oder read()<br />
Zugriff FileWriter Dateizugriffspfad write()<br />
Lesen/Schreiben von DataInputStream FileInputStream-Obj. readInt() usw<br />
Daten <strong>in</strong> B<strong>in</strong>ärdarstellung DataOutputStream FileOutputStream-Obj. writeInt() usw<br />
Lesen/Schreiben von BufferedReader FileReader-Objekt read()<br />
Textdateien readL<strong>in</strong>e()<br />
BufferedWriter FileWriter-Objekt write()<br />
newL<strong>in</strong>e()<br />
Formatiertes Schreiben Formatter File-Objekt oder format()<br />
<strong>in</strong> Textdateien FileWriter-Objekt oder<br />
FileOutputStream-Obj<br />
Pr<strong>in</strong>tStream File-Objekt oder pr<strong>in</strong>tf()<br />
FileOutputStream-Obj<br />
Pr<strong>in</strong>tWriter File-Objekt oder pr<strong>in</strong>tf()<br />
FileWriter-Objekt<br />
Formatiertes Lesen Scanner File-Objekt oder nextL<strong>in</strong>e()<br />
aus Textdateien FileReader-Objekt oder hasNextL<strong>in</strong>e()<br />
FileInputStream-Obj. next()<br />
hasNext()<br />
nextInt() usw<br />
wahlfreier Zugriff RandomAccessFile File-Objekt oder seek()<br />
Dateizugriffspfad getFilePo<strong>in</strong>ter()<br />
+ Zugriffsmodus (Str<strong>in</strong>g) skipBytes()<br />
read()<br />
readL<strong>in</strong>e()<br />
readInt() usw<br />
write()<br />
writeInt() usw<br />
length()
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 400 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel 4<br />
4. Nähere Betrachtung von Klassen und Interfaces<br />
4.1. Def<strong>in</strong>ition von Klassen<br />
4.2. Datenkomponenten<br />
4.3. Memberfunktionen<br />
4.4. Objekterzeugung<br />
4.5. Konstruktoren und Initialisierungsblöcke<br />
4.6. Vererbung<br />
4.7. Interfaces<br />
4.8. E<strong>in</strong>gebettete Klassen und Interfaces<br />
4.9. Generische Klassen, Interfaces und Funktionen
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 411 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Vorbemerkungen<br />
Def<strong>in</strong>ition von Klassen <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Klassen s<strong>in</strong>d die grundlegenden Programmiere<strong>in</strong>heiten <strong>in</strong> <strong>Java</strong>.<br />
Jedes <strong>Java</strong>-Programm besteht aus e<strong>in</strong>er oder mehreren Klassen.<br />
Es existiert ke<strong>in</strong> Code ausserhalb e<strong>in</strong>er Klasse.<br />
◇ I.a. ist jede Klasse <strong>in</strong> e<strong>in</strong>er eigenen Quelldatei def<strong>in</strong>iert (Ausnahme : e<strong>in</strong>gebettete Klassen).<br />
Diese Klassen-Quelldateien bilden die Übersetzungse<strong>in</strong>heiten (Übersetzungs-Module).<br />
Pro Klasse (auch für jede e<strong>in</strong>gebettete Klasse) wird vom Compiler e<strong>in</strong>e eigene Byte-Code-Datei erzeugt.<br />
◇ Klassen def<strong>in</strong>ieren den Aufbau und die Funktionalität (das Verhalten) von Objekten.<br />
Objekte s<strong>in</strong>d Instanzen von Klassen.<br />
Sie bestehen aus Datenkomponenten (Felder, fields), die ihren Zustand beschreiben und besitzen Funktionen<br />
(Memberfunktionen, Methoden, methods), die mit diesen Datenkomponenten arbeiten und ihr Verhalten festlegen.<br />
Die Datenkomponenten und die (Member-)Funktionen werden <strong>in</strong> e<strong>in</strong>er Klassendef<strong>in</strong>ition festgelegt und als<br />
Klassenkomponenten bezeichnet.<br />
◇ Neben den <strong>in</strong>stanzspezifischen Datenkomponenten (Instanz-Variable) und Memberfunktionen (Instanz-Methoden)<br />
kann e<strong>in</strong>e Klasse auch klassenspezifische Datenkomponenten (Klassen-Variable) und Memberfunktionen (Klassen-<br />
Methoden) besitzen. Derartige statische Klassenkomponenten beschreiben den Zustand und das Verhalten<br />
der Klasse.<br />
◇ Instanz-Methoden wird als impliziter Parameter die this-Referenz übergeben. Diese referiert das aktuelle Objekt,<br />
für das die Methode aufgerufen wird. Klassen-Methoden besitzen diesen impliziten Parameter nicht.<br />
• Klassenkomponenten<br />
◇ Klassenkomponenten (class members) können se<strong>in</strong> :<br />
▻ Datenkomponenten (Membervariable, Felder, fields)<br />
▻ Funktionskomponenten (Memberfunktionen, Methoden, methods)<br />
▻ E<strong>in</strong>gebettete Klassen und Interfaces (nested classes and <strong>in</strong>terfaces)<br />
◇ Zusätzlich kann e<strong>in</strong>e Klassendef<strong>in</strong>ition enthalten :<br />
▻ Konstruktoren (Sie werden <strong>in</strong> <strong>Java</strong> nicht zu den Memberfunktionen gerechnet)<br />
▻ Initialisierungsblöcke (Code zur Initialisierung von Datenkomponenten)<br />
• Syntax der Klassendef<strong>in</strong>ition :<br />
Klassen-<br />
Modifizierer<br />
class Klassen-Name<br />
◇ E<strong>in</strong>fachste Klassendef<strong>in</strong>ition : class Simple<br />
{<br />
;<br />
}<br />
{<br />
Typ-Param-<br />
Deklaration<br />
Komponentendef<strong>in</strong>ition<br />
Konstruktordef<strong>in</strong>ition<br />
;<br />
Klassen-<br />
Ableitung<br />
Initialisierungsblock<br />
Interface-<br />
Implementierung<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 412 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Anmerkung zur Typ-Param-Deklaration<br />
Def<strong>in</strong>ition von Klassen <strong>in</strong> <strong>Java</strong> (2)<br />
Deklaration von formalen Typ-Parametern (Typ-Variable).<br />
Falls vorhanden, wird dadurch e<strong>in</strong>e generische Klasse def<strong>in</strong>iert.<br />
• Klassen-Modifizierer<br />
◇ Sie legen bestimmte Eigenschaften der Klasse fest<br />
◇ Folgende Modifizierer s<strong>in</strong>d möglich :<br />
▻ public<br />
Die Klasse ist öffentlich zugänglich – sie kann überall verwendet werden.<br />
Ohne diesen Modifizierer ist sie nur <strong>in</strong>nerhalb des Packages, <strong>in</strong> dem sie enthalten ist, verwendbar.<br />
▻ abstract<br />
Die Klasse ist unvollständig def<strong>in</strong>iert oder sie wird als unvollständig def<strong>in</strong>iert betrachtet (abstrakte Klasse).<br />
Damit ist sie nicht <strong>in</strong>stanzierbar.<br />
I.a. besitzt sie e<strong>in</strong>e oder mehrere abstrakte Methoden.<br />
E<strong>in</strong>e abstrakte Methode besitzt ke<strong>in</strong>e vollständige Def<strong>in</strong>ition. Häufig ist sie lediglich deklariert.<br />
Ihre – vollständige – Def<strong>in</strong>ition bleibt e<strong>in</strong>er abgeleiteten Klasse überlassen.<br />
▻ f<strong>in</strong>al<br />
Von der Klasse können ke<strong>in</strong>e weiteren Klassen abgeleitet werden.<br />
Damit können ihre Methoden niemals überschrieben werden.<br />
▻ strictfp<br />
Alle <strong>in</strong>nerhalb der Klasse (und allen e<strong>in</strong>gebetteten Klassen) auftretenden float- oder double-Ausdrücke<br />
s<strong>in</strong>d FP-strict. D.h. sie werden so ausgewertet, dass auch alle Zwischenergebnisse mit der <strong>in</strong> IEEE 754 festgeleg-<br />
ten e<strong>in</strong>fachen (float) bzw doppelten (double) Genauigkeit für Gleitpunktwerte ermittelt werden.<br />
Dadurch wird sichergestellt, dass e<strong>in</strong> arithmetischer Ausdruck unabhängig von der jeweiligen JVM immer den<br />
exakt gleichen Wert ergibt.<br />
Ohne diesen Modifizierer (der auch auf der Methoden-Ebene e<strong>in</strong>gesetzt werden kann), darf die JVM Zwischen-<br />
ergebnisse mit erweiterter Genauigkeit (größerer Exponentenbereich) bilden. Dies kann dazu führen, dass die<br />
Auswertung desselben arithmetischen Ausdrucks auf unterschiedlichen JVMs leicht unterschiedliche Ergebnisse<br />
liefert.<br />
◇ E<strong>in</strong>e Klassendef<strong>in</strong>ition kann mehrere Klassen-Modifizierer besitzen.<br />
Allerd<strong>in</strong>gs ist die gleichzeitige Verwendung von abstract und f<strong>in</strong>al nicht möglich.<br />
◇ Anmerkung :<br />
Der Modifizierer abstract sollte nur für Klassen e<strong>in</strong>gesetzt werden, von denen auch tatsächlich Klassen zur<br />
Vervollständigung der Implementierung abgeleitet werden sollen.<br />
Er ist nicht dafür vorgesehen, die Instanzierung von Klassen aus e<strong>in</strong>em anderen Grund als der unvollständigen<br />
Def<strong>in</strong>ition zu verh<strong>in</strong>dern. E<strong>in</strong> solcher anderer Grund kann beispielsweise se<strong>in</strong>, dass die Klasse nur statische Klassen-<br />
komponenten enthält und damit ihre Instanzierung nicht sehr s<strong>in</strong>nvoll ist.<br />
In e<strong>in</strong>em derartigen Fall besteht die saubere Lösung zur Verh<strong>in</strong>derung der Instanziierung <strong>in</strong> der Def<strong>in</strong>ition e<strong>in</strong>es<br />
privaten Default-Konstruktors und ke<strong>in</strong>er weiteren Konstruktoren.<br />
Durch Verwendung des Modifizierers f<strong>in</strong>al kann darüber h<strong>in</strong>aus verh<strong>in</strong>dert werden, dass von der Klasse andere<br />
Klassen abgeleitete werden.<br />
Beispiel : Bibliotheks-Klasse Math<br />
Diese ist e<strong>in</strong>e re<strong>in</strong>e Utility-Klasse, die nur statische Datenkomponenten und statische Methoden zur Verfügung stellt.<br />
public f<strong>in</strong>al class Math<br />
{<br />
private Math() { } // privater Default-Konstruktor<br />
}<br />
// statische Klassenkomponenten<br />
• Kontrakt e<strong>in</strong>er Klasse (contract of the class)<br />
Die Gesamtheit der von außen zugänglichen Methoden und Datenkomponenten e<strong>in</strong>er Klasse, zusammen mit der<br />
Beschreibung ihres Verhaltens, wird häufig als Kontrakt der Klasse bezeichnet.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 413 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Unterschiede zur Klassendef<strong>in</strong>ition <strong>in</strong> C++<br />
Def<strong>in</strong>ition von Klassen <strong>in</strong> <strong>Java</strong> (3)<br />
◇ E<strong>in</strong>e Klassendef<strong>in</strong>ition <strong>in</strong> <strong>Java</strong> kann Klassen-Modifizierer enthalten.<br />
◇ E<strong>in</strong>e Klassendef<strong>in</strong>ition <strong>in</strong> <strong>Java</strong> wird nicht mit e<strong>in</strong>em Semicolon (';') abgeschlossen.<br />
◇ Andere Syntax zur Kennzeichnung e<strong>in</strong>er Vererbung (s. später).<br />
◇ Memberfunktionen müssen <strong>in</strong> <strong>Java</strong> <strong>in</strong>nerhalb der Klassendef<strong>in</strong>ition def<strong>in</strong>iert werden.<br />
Sie werden dadurch nicht zu <strong>in</strong>l<strong>in</strong>e-Funktionen (<strong>in</strong>l<strong>in</strong>e-Funktionen gibt es nicht <strong>in</strong> <strong>Java</strong> !)<br />
◇ Für Datenkomponenten können <strong>in</strong> <strong>Java</strong> Initialisierungswerte festgelegt werden.<br />
Zusätzlich s<strong>in</strong>d Initialisierungsblöcke möglich (s. später).<br />
◇ In <strong>Java</strong> muß e<strong>in</strong> eventueller Zugriffs-Spezifizierer für jede Klassenkomponente gesondert angegeben werden.<br />
(Ausnahme : Zusammenfassung mehrerer Datenkomponenten des gleichen Typs <strong>in</strong> e<strong>in</strong>er Vere<strong>in</strong>barung)<br />
• Vergleich e<strong>in</strong>er Klassendef<strong>in</strong>ition <strong>in</strong> C++ und <strong>Java</strong><br />
// C++-Header-Datei Example.h<br />
// Def<strong>in</strong>ition der Klasse Example<br />
class Example<br />
{ public :<br />
Example(<strong>in</strong>t wx);<br />
~Example();<br />
void setName(char* wname);<br />
void setX(<strong>in</strong>t wx);<br />
const char* getName();<br />
<strong>in</strong>t getX();<br />
private :<br />
char* name;<br />
<strong>in</strong>t x;<br />
};<br />
// C++-Quell-Datei Example.cpp<br />
// Implementierung der Klasse Example<br />
#<strong>in</strong>clude "Example.h"<br />
#<strong>in</strong>clude // fuer NULL<br />
Example::Example(<strong>in</strong>t wx)<br />
{ x = wx;<br />
name = NULL;<br />
}<br />
Example::~Example()<br />
{ /* ... */ }<br />
void Example::setName(char* wname)<br />
{ /* ... */ }<br />
void Example::setX(<strong>in</strong>t wx)<br />
{ x = wx;<br />
}<br />
const char* Example::getName()<br />
{ return name;<br />
}<br />
<strong>in</strong>t Example::getX()<br />
{ return x;<br />
}<br />
// Example.java<br />
public class Example<br />
{<br />
private Str<strong>in</strong>g name;<br />
private <strong>in</strong>t x;<br />
}<br />
public Example(<strong>in</strong>t wx)<br />
{<br />
x = wx;<br />
name = null;<br />
}<br />
public void setName(Str<strong>in</strong>g wname)<br />
{<br />
name = wname;<br />
}<br />
public void setX (<strong>in</strong>t wx)<br />
{<br />
x = wx;<br />
}<br />
public Str<strong>in</strong>g getName()<br />
{<br />
return name;<br />
}<br />
public <strong>in</strong>t getX()<br />
{<br />
return x;<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 421 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Def<strong>in</strong>ition von Datenkomponenten<br />
Datenkomponenten <strong>in</strong> <strong>Java</strong>-Klassen (1)<br />
◇ Datenkomponenten von Klassen (Membervariable) werden <strong>in</strong> <strong>Java</strong> auch als Felder (fields) bezeichnet.<br />
◇ Die Def<strong>in</strong>ition von Datenkomponenten des gleichen Typs kann <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zigen Vere<strong>in</strong>barung zusammengefasst<br />
werden.<br />
◇ Für die – gegebenenfalls <strong>in</strong> e<strong>in</strong>er Vere<strong>in</strong>barung zusammengefassten – Datenkomponenten, die nicht die Zugriffsbe-<br />
rechtigung "package" besitzen sollen, ist gesondert e<strong>in</strong>e andere Zugriffsberechtigung anzugeben.<br />
Wie <strong>in</strong> C++ stehen hierfür die Zugriffs-Spezifizierer (<strong>in</strong> <strong>Java</strong> auch als Zugriffs-Modifizierer bezeichnet) public,<br />
protected und private zur Verfügung.<br />
◇ Zusätzlich können <strong>in</strong> jeder Datenkomponenten-Vere<strong>in</strong>barung weitere Feld-Modifizierer (field modifier) angegeben<br />
werden.<br />
◇ Syntax :<br />
Feld-Modifizierer<br />
• Initialisierung von Datenkomponenten<br />
◇ Zu jeder Datenkomponente kann bei ihrer Def<strong>in</strong>ition e<strong>in</strong> Initialisierungswert festgelegt werden.<br />
◇ Ohne e<strong>in</strong>e derartige Festlegung wird e<strong>in</strong>e Datenkomponente mit e<strong>in</strong>em vorgegebenen Default-Wert <strong>in</strong>itialisiert<br />
(s. "Datentypen")<br />
◇ Der e<strong>in</strong>en Initialisierungswert festlegende Initialisierer (variable <strong>in</strong>itializer) darf se<strong>in</strong><br />
▻ e<strong>in</strong> beliebiger Ausdruck, der e<strong>in</strong>en Wert liefert, der zuweisungskompatibel zum Typ der Datenkomponente ist<br />
und ke<strong>in</strong>e geprüften Exceptions erzeugen kann.<br />
Weiterh<strong>in</strong> darf e<strong>in</strong> Ausdruck zur Initialisierung e<strong>in</strong>er Klassen-Variablen ke<strong>in</strong>e Instanz-Variable enthalten<br />
▻ e<strong>in</strong> Array-Initialisierer (array <strong>in</strong>itializer), wenn die Datenkomponente e<strong>in</strong> Array ist (s. "Arrays").<br />
◇ Beispiele für gültige Initialisierer :<br />
Typangabe Komponentenname<br />
public class InitDemo<br />
{<br />
double zero = 0.0; // Konstante<br />
double sum = 4.5 + 3.7; // konstanter Ausdruck<br />
double zeroCpy = zero; // andere Datenkomponente<br />
double wurz2 = Math.sqrt(2); // Methodenaufruf<br />
double some = sum + 2*Math.sqrt(wurz2); // gemischter Ausdruck<br />
<strong>in</strong>t[] koeff = { 2, 4, 1, 3, 6, 7 }; // Array-Initialisierer<br />
double[] tfeld = { Math.s<strong>in</strong>(1), Math.cos(1), Math.tan(1) }; // Array-Init.<br />
}<br />
◇ Zur Realisierung komplexerer Initialisierungsaufgaben können Initialisierungsblöcke def<strong>in</strong>iert werden (s. später).<br />
◇ E<strong>in</strong> Initialisierer für e<strong>in</strong>e Instanz-Variable wird bei jeder Instanzierung (Objekterzeugung) der Klasse ausgewertet.<br />
E<strong>in</strong> Initialisierer für e<strong>in</strong>e Klassen-Variable wird nur e<strong>in</strong>mal beim Laden der Klasse <strong>in</strong> die JVM ausgewertet<br />
◇ E<strong>in</strong>e Initialisierung von Instanz-Variablen kann auch <strong>in</strong> e<strong>in</strong>em Konstruktor erfolgen. Gegebenenfalls werden<br />
"vorherige" Initialisierungen dadurch überschrieben.<br />
,<br />
=<br />
Initialisierer ;
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 422 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Feld-Modifizierer<br />
Datenkomponenten <strong>in</strong> <strong>Java</strong>-Klassen (2)<br />
◇ Sie legen bestimmte Eigenschaften e<strong>in</strong>er Datenkomponente fest.<br />
◇ Folgende Modifizierer s<strong>in</strong>d möglich :<br />
▻ die Zugriffs-Spezifizierer (Zugriffs-Modifizierer) public, protected und private.<br />
▻ static<br />
Die Datenkomponente ist e<strong>in</strong>e Klassen-Variable (statische Datenkomponente).<br />
Klassen-Variable müssen von ausserhalb (vorausgesetzt es besteht e<strong>in</strong>e entsprechende Zugriffsberechtigung) mit<br />
ihrem vollqualifizierten Namen (Ergänzung um Klassenname und . –Operator) angesprochen werden.<br />
Sie können allerd<strong>in</strong>gs auch als Komponente e<strong>in</strong>es Objekts ihrer Klasse angesprochen werden. Dies sollte jedoch aus<br />
semantischen Gründen zur Vermeidung von Missverständnissen unterbleiben.<br />
▻ f<strong>in</strong>al<br />
Die Datenkomponente kann nach ihrer Initialisierung nicht mehr verändert werden.<br />
Sowohl Instanz- als auch Klassenvariable können diese Eigenschaft besitzen.<br />
Typischerweise wird e<strong>in</strong>e als f<strong>in</strong>al vere<strong>in</strong>barte Datenkomponente e<strong>in</strong>en Initialisierer besitzen. Fehlt e<strong>in</strong><br />
Initialisierer (blank f<strong>in</strong>al), so muß e<strong>in</strong>e f<strong>in</strong>al-Klassen-Variable durch e<strong>in</strong>en Initialisierungsblock, e<strong>in</strong>e<br />
f<strong>in</strong>al-Instanz-Variable durch e<strong>in</strong>en Initialisierungsblock oder durch e<strong>in</strong>en Konstruktor <strong>in</strong>itialisiert werden.<br />
Das Fehlen e<strong>in</strong>er Initialisierung sowie der Versuch e<strong>in</strong>er späteren Wertzuweisung führt zu e<strong>in</strong>em Compiler-Fehler<br />
▻ transient<br />
Die Datenkomponente gehört nicht zum persistenten Zustand e<strong>in</strong>es Objekts. Beim persistenten Abspeichern des<br />
Objekts wird e<strong>in</strong>e transient-Datenkomponente nicht mit abgespeichert.<br />
▻ volatile<br />
Zu der Datenkomponente kann durch mehrere unsynchronisierte Threads zugegriffen werden.<br />
Der Compiler muß durch Vermeidung von Zugriffs-Optimierungen sicherstellen, dass die Datenkomponente sich<br />
immer <strong>in</strong> e<strong>in</strong>em konsistenten Zustand bef<strong>in</strong>det. Z.B. muß e<strong>in</strong> Thread jeden Zugriff zu e<strong>in</strong>er von ihm gehaltenen<br />
lokalen Kopie e<strong>in</strong>er derartigen Variablen immer mit der Orig<strong>in</strong>al-Variablen abgleichen.<br />
◇ Mehrere Feld-Modifizierer dürfen – soweit s<strong>in</strong>nvoll – mite<strong>in</strong>ander komb<strong>in</strong>iert werden.<br />
Allerd<strong>in</strong>gs ist nur jeweils e<strong>in</strong> Zugriffs-Spezifizierer zulässig.<br />
Ausserdem kann e<strong>in</strong>e Datenkomponente nicht gleichzeitig volatile und f<strong>in</strong>al se<strong>in</strong>.<br />
• Konstante <strong>in</strong> <strong>Java</strong><br />
◇ Konstante werden <strong>in</strong> <strong>Java</strong> i.a. als f<strong>in</strong>al-Klassen-Variable (Datenkomponenten mit den Modifizierern static<br />
und f<strong>in</strong>al) def<strong>in</strong>iert. Es ist üblich – aber nicht verpflichtend – , Konstanten-Namen mit Großbuchstaben zu bilden.<br />
◇ Beispiele aus der <strong>Java</strong>-Standard-Bibliothek<br />
public f<strong>in</strong>al class Integer<br />
{ public static f<strong>in</strong>al <strong>in</strong>t MAX_VALUE;<br />
public static f<strong>in</strong>al <strong>in</strong>t MIN_VALUE;<br />
..public static f<strong>in</strong>al Class TYPE;<br />
// ...<br />
}<br />
public f<strong>in</strong>al class System<br />
{<br />
public static f<strong>in</strong>al InputStream <strong>in</strong>;<br />
..// ...<br />
}<br />
◇ Es lassen sich mit dem Schlüsselwort f<strong>in</strong>al auch lokale Konstante <strong>in</strong> Funktionen def<strong>in</strong>ieren :<br />
f<strong>in</strong>al <strong>in</strong>t ANZ = 10;<br />
Sofern diese nicht bei ihrer Def<strong>in</strong>ition <strong>in</strong>itialisiert werden, kann ihnen später e<strong>in</strong>mal e<strong>in</strong> Wert zugewiesen werden.<br />
Jeder Versuch e<strong>in</strong>er weiteren Wertzuweisung führt zu e<strong>in</strong>em Compilerfehler
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 431 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Def<strong>in</strong>ition von Memberfunktionen<br />
Memberfunktionen <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Jede Memberfunktion (Methode) muß – sofern es sich nicht um e<strong>in</strong>e abstrakte Methode handelt – <strong>in</strong>nerhalb der<br />
Klassendef<strong>in</strong>ition vollständig def<strong>in</strong>iert (implementiert) werden.<br />
◇ Für jede Memberfunktion, die nicht die Zugriffsberechtigung "package" besitzen soll, ist gesondert e<strong>in</strong>e andere<br />
Zugriffsberechtigung anzugeben.<br />
Wie <strong>in</strong> C++ stehen hierfür die Zugriffs-Spezifizierer (<strong>in</strong> <strong>Java</strong> auch als Zugriffs-Modifizierer bezeichnet) public,<br />
protected und private zur Verfügung.<br />
◇ Können <strong>in</strong>nerhalb e<strong>in</strong>er Methode geprüfte Exceptions – direkt oder <strong>in</strong>direkt – geworfen werden und werden diese nicht<br />
gefangen, so müssen sie im Funktionskopf <strong>in</strong> e<strong>in</strong>er throws-Klausel deklariert werden.<br />
◇ Syntax :<br />
Methoden-<br />
Modifizierer<br />
Typ-Param-<br />
Deklaration<br />
• Anmerkung zur Typ-Param-Deklaration<br />
Deklaration von formalen Typ-Parametern (Typ-Variable). Falls vorhanden, wird e<strong>in</strong>e generische Methode def<strong>in</strong>iert.<br />
• Anmerkungen zur Formal-Parameterliste :<br />
◇ Auflistung der formalen Methoden-Parameter.<br />
Syntax weitgehend analog zu C/C++ : Angabe von Typ und Name für jeden Parameter, Trennung der Parameter durch<br />
Kommata<br />
◇ Wenn e<strong>in</strong>e Methode ke<strong>in</strong>e Parameter besitzt, ist die Formal-Parameterliste leer (ke<strong>in</strong>e Angabe von void)<br />
◇ Default-Parameterwerte gibt es <strong>in</strong> <strong>Java</strong> nicht.<br />
◇ Parameter e<strong>in</strong>es e<strong>in</strong>fachen Datentyps s<strong>in</strong>d Wertparameter, Parameter e<strong>in</strong>es Klassen-Typs s<strong>in</strong>d Referenzparameter.<br />
◇ Parameter können als f<strong>in</strong>al deklariert werden sie dürfen dann <strong>in</strong>nerhalb der Funktion nicht verändert werden<br />
• Variable Parameterliste (Varargs)<br />
Typangabe Methoden-Name ( Formal-Parameterliste )<br />
Methoden-Kopf<br />
◇ Seit dem JDK 5.0 ist es möglich, Methoden mit e<strong>in</strong>er variablen Parameterliste (Varargs)zu def<strong>in</strong>ieren.<br />
▻ In der Formal-Parameterliste muss hierfür die Typangabe des letzten Parameters von drei Punkten gefolgt werden.<br />
▻ E<strong>in</strong>e derartige Methode kann mit e<strong>in</strong>er beliebigen Anzahl aktueller Parameter aufgerufen werden.<br />
Die aktuellen Parameter müssen zum Typ des letzten formalen Parameters kompatibel se<strong>in</strong>.<br />
▻ Wenn <strong>in</strong> e<strong>in</strong>em derartigen Fall aktuelle Parameter beliebigen Typs übergebbar se<strong>in</strong> sollen, muss als Typangabe<br />
Object verwendet werden : Object...<br />
▻ Beispiel : Methode pr<strong>in</strong>tf() der Klasse Pr<strong>in</strong>tStream (bzw Pr<strong>in</strong>tWriter)<br />
throws-Klausel<br />
Anweisung<br />
{ }<br />
public Pr<strong>in</strong>tStream pr<strong>in</strong>tf(Str<strong>in</strong>g format, Object... args)<br />
Methoden-<br />
Rumpf<br />
▻ Statt mit e<strong>in</strong>er variablen Anzahl von Parametern lässt sich e<strong>in</strong>e derartige Methode auch mit e<strong>in</strong>em Array, <strong>in</strong> dem<br />
die Parameter zusammengefasst s<strong>in</strong>d, aufrufen<br />
◇ Innerhalb der Methode werden die variablen aktuellen Parameter <strong>in</strong> e<strong>in</strong>em Array des deklarierten<br />
Parametertyps zur Verfügung gestellt. Beispielsweise kann die Anzahl der aktuellen Parameter mittels der öffentlichen<br />
Array-Datenkomponente length ermittelt werden.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 432 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Demoprogramm zur variablen Parameterliste<br />
• Signatur e<strong>in</strong>er Memberfunktion<br />
Memberfunktionen <strong>in</strong> <strong>Java</strong> (2)<br />
// VarargsDemo.java<br />
// Demoprogramm zur variablen Parameter-Liste<br />
import java.util.*;<br />
public class VarargsDemo<br />
{<br />
<strong>in</strong>t varargsfunc(Object... pars)<br />
{<br />
System.out.pr<strong>in</strong>tf("Aufruf mit %d Parametern\n", pars.length);<br />
return pars.length;<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
VarargsDemo vad = new VarargsDemo();<br />
vad.varargsfunc(3, 4, 6.5, "Hallo");<br />
vad.varargsfunc();<br />
vad.varargsfunc("Datum : ", new Date());<br />
Number[] na = new Number[] { 3, 5.6, 7};<br />
vad.varargsfunc(na);<br />
}<br />
}<br />
Aufruf mit 4 Parametern<br />
Aufruf mit 0 Parametern<br />
Aufruf mit 2 Parametern<br />
Aufruf mit 3 Parametern<br />
◇ Der Methoden-Name und die Formal-Parameterliste (Anzahl und Typ der Parameter) bilden die Signatur e<strong>in</strong>er<br />
Memberfunktion.<br />
◇ In e<strong>in</strong>er Klasse dürfen nicht zwei Methoden mit der gleichen Signatur def<strong>in</strong>iert werden, auch wenn der Rückgabetyp<br />
und / oder die throws-Klausel unterschiedlich ist ( Compiler-Fehler).<br />
◇ Zulässig s<strong>in</strong>d dagegen überladene Methoden : Zwei oder mehr Methoden gleichen Namens, aber unterschiedlicher<br />
Parameterliste ( unterschiedliche Signatur).<br />
Beispiel :<br />
public class Po<strong>in</strong>t<br />
{<br />
private double x = 0.0;<br />
private double y = 0.0;<br />
public Po<strong>in</strong>t move(double dx, double dy)<br />
{ x += dx; y += dy; return this; }<br />
/*<br />
public void move(double px, double py) // unzulaessig<br />
{ x = px; y = py;}<br />
*/<br />
public void move(Po<strong>in</strong>t p) // zulaessig : überlädt Po<strong>in</strong>t move(double, double)<br />
{ x = p.x; y = p.y;}<br />
}<br />
// ...
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 433 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Methoden-Modifizierer<br />
Memberfunktionen <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Sie legen bestimmte Eigenschaften e<strong>in</strong>er Memberfunktion fest.<br />
◇ Folgende Modifizierer s<strong>in</strong>d möglich :<br />
▻ die Zugriffs-Spezifizierer (Zugriffs-Modifizierer) public, protected und private.<br />
▻ abstract<br />
Es handelt sich um e<strong>in</strong>e abstrakte Methode.<br />
Für e<strong>in</strong>e derartige Methode wird nur die Signatur (Name und Parameter), der Rückgabetyp und gegebenenfalls die<br />
throws-Klausel nicht jedoch die Implementierung festgelegt. (Methode wird nur deklariert)<br />
Der Methoden-Rumpf wird durch e<strong>in</strong> ; ersetzt.<br />
Abstrakte Methoden s<strong>in</strong>d nur <strong>in</strong> abstrakten Klassen zulässig.<br />
Jede von der abstrakten Klasse abgeleitete Klasse, die selbst nicht wieder abstrakt ist, muß e<strong>in</strong>e Def<strong>in</strong>ition der<br />
Methode bereitstellen.<br />
▻ static<br />
Die Methode ist e<strong>in</strong>e Klassen-Methode (statische Memberfunktion).<br />
Da e<strong>in</strong>e derartige Methode nicht für e<strong>in</strong> konkretes Objekt aufgerufen werden kann und ihr ke<strong>in</strong>e implizite this-<br />
Referenz übergeben wird, kann sie direkt nur zu anderen statischen Klassenkomponenten zugreifen.<br />
E<strong>in</strong> Zugriff zu nicht-statischen Klassenkomponenten der eigenen Klasse ist nur über e<strong>in</strong> konkretes Objekt möglich,<br />
das entweder als Parameter übergeben oder <strong>in</strong>nerhalb der Methode erzeugt werden muß.<br />
▻ f<strong>in</strong>al<br />
Die Methode kann <strong>in</strong> e<strong>in</strong>er abgeleiteten Klasse weder überschrieben noch überdeckt werden.<br />
Allerd<strong>in</strong>gs ist es zulässig, die Methode <strong>in</strong> e<strong>in</strong>er abgeleiteten Klasse zu überladen, d.h. e<strong>in</strong>e Methode gleichen<br />
Namens aber mit anderer Parameterliste zu def<strong>in</strong>ieren.<br />
E<strong>in</strong>e private-Methode sowie alle Methoden e<strong>in</strong>er f<strong>in</strong>al deklarierten Klasse s<strong>in</strong>d implizit f<strong>in</strong>al.<br />
E<strong>in</strong>e explizite Angabe des Modifizierers f<strong>in</strong>al für derartige Methoden ist nicht notwendig, aber zulässig.<br />
E<strong>in</strong>e f<strong>in</strong>al-Methode kann vom Masch<strong>in</strong>encode-Generator der JVM als Makro ("<strong>in</strong>l<strong>in</strong>e") expandiert werden.<br />
▻ synchronized<br />
Die Methode implementiert e<strong>in</strong>en Synchronisations-Mechanismus für den Aufruf durch konkurierende Threads.<br />
▻ native<br />
Dieser Modifizierer erlaubt das E<strong>in</strong>b<strong>in</strong>den von Methoden, die <strong>in</strong> nativen Mach<strong>in</strong>encode vorliegen.<br />
Üblicherweise werden derartige Methoden <strong>in</strong> e<strong>in</strong>er anderen Programmiersprache (z.B. C, C++, FORTRAN, Assem-<br />
bler) formuliert und dann <strong>in</strong> Mach<strong>in</strong>encode übersetzt.<br />
E<strong>in</strong>e native-Methode wird <strong>in</strong> der Klassendef<strong>in</strong>ition nur deklariert, d.h. der Methoden-Rumpf wird durch<br />
e<strong>in</strong> ; ersetzt.<br />
Die den Methoden-Code enthaltene Datei muss zur Laufzeit (üblicherweise bei der Klassen-Initialisierung) <strong>in</strong> die<br />
JVM geladen werden. Hierfür stehen <strong>in</strong> den Klassen Runtime und System die statischen Methoden<br />
load(...) und loadLibrary(...) zur Verfügung.<br />
Das <strong>Java</strong>-SDK def<strong>in</strong>iert e<strong>in</strong> Interface zum Formulieren und E<strong>in</strong>b<strong>in</strong>den von native-Methoden ( JNI, <strong>Java</strong><br />
Native Interface).<br />
▻ strictfp<br />
E<strong>in</strong>e derartige Methode arbeitet FP-strict. D.h. alle <strong>in</strong>nerhalb der Methode auftretenden float- oder double-<br />
Ausdrücke werden so ausgewertet, dass auch alle Zwischenergebnisse mit der <strong>in</strong> IEEE 754 festgelegten e<strong>in</strong>fachen<br />
(float) bzw doppelten (double) Genauigkeit für Gleitpunktwerte ermittelt werden. (s. Klassen-Modifizierer !)<br />
Alle <strong>in</strong>nerhalb e<strong>in</strong>er strictfp deklarierten Klasse vere<strong>in</strong>barten Methoden s<strong>in</strong>d implizit strictfp.<br />
◇ Mehrere Methoden-Modifizierer dürfen – soweit s<strong>in</strong>nvoll – mite<strong>in</strong>ander komb<strong>in</strong>iert werden.<br />
Allerd<strong>in</strong>gs ist nur jeweils e<strong>in</strong> Zugriffs-Spezifizierer zulässig.<br />
Ausserdem darf e<strong>in</strong>e abstract vere<strong>in</strong>barte Methode nicht gleichzeitig private, static, f<strong>in</strong>al oder<br />
native se<strong>in</strong>.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 441 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Grundsätzliches<br />
Objekterzeugung <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Die Def<strong>in</strong>ition e<strong>in</strong>er Objekt-Variablen erzeugt noch ke<strong>in</strong> Objekt.<br />
Sie belegt lediglich Speicherplatz zur Aufnahme e<strong>in</strong>er Objekt-Referenz.<br />
◇ Objekte können <strong>in</strong> <strong>Java</strong> nur dynamisch auf dem Heap angelegt werden.<br />
◇ Üblicherweise werden Objekte mittels e<strong>in</strong>es new-Ausdrucks erzeugt.<br />
E<strong>in</strong> new-Ausdruck wird aus dem new-Operator, dem Namen der zu <strong>in</strong>stanzierenden Klasse und e<strong>in</strong>er <strong>in</strong> runde<br />
Klammern e<strong>in</strong>geschlossenen Liste von Initialiserungswerten ( Parameter für den Konstruktor) gebildet.<br />
Die Liste der Initialisierungswerte kann auch leer se<strong>in</strong>, die runden Klammern müssen aber <strong>in</strong> jedem Fall angegeben<br />
werden.<br />
◇ E<strong>in</strong> new-Ausdruck<br />
▻ bewirkt die Allokation von Speicher durch das Laufzeitsystem (JVM) für die Datenkomponenten des Objekts,<br />
▻ <strong>in</strong>itialisiert die Datenkomponenten<br />
▻ und liefert nach Abschluß der Initialisierung e<strong>in</strong>e Referenz auf das neu erzeugte Objekt zurück<br />
◇ Die zurückgelieferte Referenz auf das erzeugte Objekt kann dann e<strong>in</strong>er Objekt-Variablen passenden Typs zugewiesen<br />
werden. Sie kann gegebenenfalls auch als Referenz auf e<strong>in</strong> anonymes Objekt weiterverwendet werden, z.B. zum<br />
Aufruf von Memberfunktionen.<br />
◇ Beispiel : Po<strong>in</strong>t pkt1;<br />
pkt1 = new Po<strong>in</strong>t();<br />
pkt1.move(3.5, 4.7);<br />
Po<strong>in</strong>t pkt2 = (new Po<strong>in</strong>t()).move(-2.3, -1.7);<br />
◇ Falls das Laufzeitsystem ke<strong>in</strong>en ausreichenden Speicher allozieren kann, startet es den Garbage Collector, der<br />
versucht Speicher freizumachen.<br />
Falls auch danach nicht genügend freier Speicher für e<strong>in</strong>e Allokation zur Verfügung steht, wird die Exception<br />
OutOfMemoryError geworfen.<br />
◇ In <strong>Java</strong> s<strong>in</strong>d noch weitere Mechanismen zur Objekterzeugung implementiert, u.a.<br />
▻ Spezielle Generiermethoden (factory methods) im Rahmen des Reflection-APIs . Sie ermöglichen die Instan-<br />
zierung e<strong>in</strong>er Klasse unter dynamischer Bereitstellung des Klassennamens als Str<strong>in</strong>g.<br />
Dies erlaubt z.B. die Instanzierung e<strong>in</strong>er Klasse, deren Name durch e<strong>in</strong> Programm erst e<strong>in</strong>gelesen wird.<br />
▻ Die clone()-Methode<br />
▻ Implizite Objekterzeugung aus Str<strong>in</strong>g-Konkatenationsausdrücken und Array-Initialisierern<br />
• Anmerkung zur Freigabe von Objekten<br />
◇ E<strong>in</strong>e explizite Freigabe von Objekten ist nicht möglich. Die Freigabe nicht mehr referierter Objekte erfolgt vielmehr<br />
durch e<strong>in</strong>en Garbage Collector, der als niederpriorer H<strong>in</strong>tergrund-Thread <strong>in</strong> der JVM läuft.<br />
◇ Damit der Garbage Collector s<strong>in</strong>nvoll arbeiten kann, sollte die Referenz zu nicht mehr benötigten Objekten gegebe-<br />
nenfalls explizit aufgehoben werden, z.B. durch Zuweisung von null an die referierende Objekt-Variable.<br />
• Initialisierung von Objekten<br />
◇ Die Datenkomponenten e<strong>in</strong>es neu erzeugten Objekts werden durch das Laufzeitsystem (die JVM) <strong>in</strong>itialisiert.<br />
◇ Hierfür setzt die JVM die folgenden Mechanismen – falls vorhanden – <strong>in</strong> der angegebenen Reihenfolge e<strong>in</strong> :<br />
▻ Initialisierung mit dem ihrem jeweiligen Typ entsprechenden Default-Wert.<br />
▻ Initialisierung mittels den bei der Datenkomponenten-Def<strong>in</strong>ition angegebenen Initialisierern und durch<br />
Initialisierungsblöcke. Die Auswertung der Initialisierer und die Abarbeitung der Initialisierungsblöcke erfolgt<br />
<strong>in</strong> der Reihenfolge ihres Auftritts <strong>in</strong> der Klassendef<strong>in</strong>ition.<br />
▻ Initialisierung durch e<strong>in</strong>en Konstruktor
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 442 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Objekterzeugung <strong>in</strong> <strong>Java</strong> (2)<br />
• Dynamische Bereitstellung des Namens der zu <strong>in</strong>stanziierenden Klasse<br />
◇ Die im Rahmen des Reflection-API bereitgestellten Bibliotheksklassen ermöglichen die Instanziierung von Klassen,<br />
deren Name erst dynamisch zu Laufzeit festgelegt wird.<br />
◇ Die e<strong>in</strong>fachste Möglichkeit hierfür erlaubt die Instanziierung von Klassen, die über e<strong>in</strong>en Konstruktor ohne Para-<br />
meter (no-arg-Konstruktor) verfügen.<br />
Sie wird mittels Memberfunktionen der Klasse Class (Package java.lang) realisiert.<br />
◇ Die Klasse Constructor (Package java.lang.reflect) ermöglicht darüberh<strong>in</strong>aus die Instanziierung<br />
von Klassen unter Verwendung parameterbehafteter Konstruktoren.<br />
Hierauf wird an dieser Stelle nicht e<strong>in</strong>gegangen.<br />
◇ Die Instanziierung e<strong>in</strong>er Klasse, deren Name lediglich als Str<strong>in</strong>g vorliegt, erfolgt <strong>in</strong> zwei Schritten :<br />
▻ Ermittlung des Objekts der Klasse Class, das die Klasse mit dem angegebenen Namen repräsentiert<br />
Der Typ-Parameter T steht für die repräsentierte Klasse (allgeme<strong>in</strong> : den repräsentierten Typ)<br />
▻ Erzeugung e<strong>in</strong>er Instanz der durch das Class-Objekt repräsentierten Klasse.<br />
◇ Ermittlung des e<strong>in</strong>e Klasse repräsentierenden Class-Objekts :<br />
Mittels der statischen Memberfunktion der Klasse Class :<br />
public static Class forName(Str<strong>in</strong>g name) throws ClassNotFoundException<br />
Diese Methode gibt e<strong>in</strong>e Referenz auf das Objekt der Klasse Class zurück, das die durch den vollqualifizier-<br />
ten Namen name bezeichnete Klasse repräsentiert (Objekt des Typs Class).<br />
Wenn die zugehörige Klasse nicht gefunden wird, wird e<strong>in</strong>e ClassNotFoundException geworfen.<br />
◇ Instanziierung e<strong>in</strong>er Klasse unter Verwendung ihres repräsentierenden Class-Objekts.<br />
Hierfür dient die nicht-statische Memberfunktion der Klasse Class :<br />
public T newInstance() throws InstantationException,<br />
IllegalAccessException<br />
Diese Methode erzeugt e<strong>in</strong> neues Objekt der repräsentierten Klasse T, für das der no-arg-Konstruktor aufgerufen<br />
wird und gibt e<strong>in</strong>e Referenz auf dieses Objekt zurück.<br />
Wenn die Klasse nicht <strong>in</strong>stanziiert werden kann (z.B. abstrakte Klasse, Interface, Array, e<strong>in</strong>facher Datentyp, ke<strong>in</strong><br />
no-arg-Konstruktor vorhanden), wird e<strong>in</strong>e InstantationException geworfen.<br />
Wenn die Klasse oder ihr no-arg-Konstruktor nicht zugreifbar ist, wird e<strong>in</strong>e IllegalAccessException<br />
geworfen.<br />
◇ Damit e<strong>in</strong> mittels newInstance() erzeugtes Objekt s<strong>in</strong>nvoll verwendet werden kann, muß es i.a. <strong>in</strong> se<strong>in</strong>en eigenen<br />
bzw <strong>in</strong> e<strong>in</strong>en zuweisungskompatiblen Typ gecastet werden.<br />
◇ E<strong>in</strong>faches Demonstrationsbeispiel :<br />
public class ObjErzeuger<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ try<br />
{ if (args.length==0)<br />
throw new RuntimeException("Programmparameter (Klassenname) fehlt");<br />
Class cl = Class.forName(args[0]);<br />
Object obj = cl.newInstance();<br />
System.out.pr<strong>in</strong>tln("Erzeugtes Objekt Typ : " + obj.getClass().getName());<br />
}<br />
catch (Exception e)<br />
{ System.out.pr<strong>in</strong>tln(e); }<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 451 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es zu Konstruktoren<br />
Konstruktoren <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Konstruktoren s<strong>in</strong>d im Pr<strong>in</strong>zip spezielle Memberfunktioen.<br />
Allerd<strong>in</strong>gs besitzen sie ke<strong>in</strong>en Rückgabetyp und haben e<strong>in</strong>en festgelegten Namen.<br />
In <strong>Java</strong> werden sie aber nicht zu den Memberfunktionen gerechnet.<br />
◇ Konstruktoren s<strong>in</strong>d nicht vererbbar und können damit weder überschrieben noch überdeckt werden.<br />
◇ Konstruktoren werden implizit bei der Erzeugung e<strong>in</strong>es Objekts zur Initialisierung se<strong>in</strong>er Datenkomponenten ausge-<br />
führt. Bei jeder Objekterzeugung wird genau e<strong>in</strong> Konstruktor durch das Laufzeitsystem aufgerufen.<br />
Se<strong>in</strong> Aufruf erfolgt nach e<strong>in</strong>er Initialisierung der Datenkomponenten mit Defaultwerten und den Werten eventueller<br />
Initialisierer sowie nach der Abarbeitung eventueller Initialisierungsblöcke.<br />
Er kann gegebenenfalls weitere Konstruktoren explizit aufrufen.<br />
◇ Konstruktoren können Parameter zur Festlegung der Initialisierungswerte für die Datenkomponenten besitzen.<br />
E<strong>in</strong>e Klasse kann mehrere Konstruktoren mit jeweils unterschiedlicher Parameterliste besitzen<br />
Konstruktoren können überladen werden.<br />
◇ E<strong>in</strong> Konstruktor ohne Parameter wird <strong>in</strong> <strong>Java</strong> als no-arg constructor bezeichnet.<br />
• Def<strong>in</strong>ition von Konstruktoren<br />
◇ Die Def<strong>in</strong>ition von Konstruktoren entspricht im wesentlichen der Def<strong>in</strong>ition von Memberfunktionen.<br />
Der Name e<strong>in</strong>es Konstruktors muß gleich dem Klassennamen se<strong>in</strong>.<br />
◇ Syntax :<br />
Konstruktor-<br />
Modifizierer<br />
Typ-Param-<br />
Deklaration<br />
Klassen-Name ( Formal-Parameterliste )<br />
throws-Klausel<br />
Anweisung<br />
{ }<br />
Konstruktor-<br />
Kopf<br />
Konstruktor-<br />
Rumpf<br />
◇ Als Konstruktor-Modifizierer s<strong>in</strong>d nur die Zugriffs-Spezifizierer public, protected und private zulässig.<br />
◇ Konstruktoren können auch Exceptions werfen. Geprüfte Exceptions s<strong>in</strong>d <strong>in</strong> e<strong>in</strong>er throws-Klausel zu deklarieren.<br />
Wirft e<strong>in</strong> Konstruktor e<strong>in</strong>e Exception, wird der den Konstruktoraufruf veranlassende new-Ausdruck durch Werfen der<br />
Exception beendet. E<strong>in</strong>e Referenz auf das neu erzeugte Objekt wird nicht zurückgegeben.<br />
◇ Ist <strong>in</strong> e<strong>in</strong>er Klassendef<strong>in</strong>ition ke<strong>in</strong> Konstruktor explizit festgelegt, wird vom Compiler implizit e<strong>in</strong> Konstruktor ohne<br />
Parameter (no-arg constructor) erzeugt Default-Konstruktor.<br />
Die e<strong>in</strong>zige Funktionalität dieses Konstruktors besteht im Aufruf des no-arg-Konstruktors der Basisklasse.<br />
Er besitzt die gleiche Zugriffsberechtigung , die für die Klasse festgelegt ist.<br />
◇ In <strong>Java</strong> kann e<strong>in</strong> Konstruktor andere Konstruktoren der gleichen Klasse (andere Parameterliste) aufrufen<br />
Verkettung von Konstruktoren.<br />
Zum Aufruf e<strong>in</strong>es anderen Konstruktors dient die this-Referenz, der <strong>in</strong> runden Klammern die aktuelle Parameter-<br />
liste nachzustellen ist.<br />
E<strong>in</strong> derartiger expliziter Konstruktoraufruf muß die erste Anweisung im aufrufenden Konstruktor se<strong>in</strong>.<br />
◇ Copy-Konstruktoren s<strong>in</strong>d auch möglich. Allerd<strong>in</strong>gs s<strong>in</strong>d sie <strong>in</strong> <strong>Java</strong> weniger gebräuchlich.<br />
Zur Erzeugung der Kopie e<strong>in</strong>es Objekts wird i.a. die – <strong>in</strong> der Klasse Object def<strong>in</strong>ierte und <strong>in</strong> anderen Klassen<br />
geeignet zu überladene – clone()-Methode bevorzugt.<br />
◇ E<strong>in</strong> Konstruktor kann auch e<strong>in</strong>e Typ-Param-Deklaration besitzen, d.h. mit formalen Typ-Parametern def<strong>in</strong>iert<br />
werden (unabhängig davon, ob die Klasse generisch ist) generischer Konstruktor
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 452 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Beispiel :<br />
// CelBody.java<br />
public class CelBody<br />
{<br />
private long idNum;<br />
private Str<strong>in</strong>g name = "";<br />
private CelBody orbits;<br />
private static long nextID = 1;<br />
}<br />
public CelBody()<br />
{<br />
System.out.pr<strong>in</strong>tln(toStr<strong>in</strong>g());<br />
idNum = nextID++;<br />
}<br />
Konstruktoren <strong>in</strong> <strong>Java</strong> (2)<br />
public CelBody(Str<strong>in</strong>g bName, CelBody orbAround)<br />
{<br />
this();<br />
name = bName;<br />
orbits = orbAround;<br />
System.out.pr<strong>in</strong>tln(toStr<strong>in</strong>g());<br />
}<br />
public CelBody(Str<strong>in</strong>g bName)<br />
{<br />
this(bName, null);<br />
}<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
{<br />
Str<strong>in</strong>gBuffer sb = new Str<strong>in</strong>gBuffer("Name : ");<br />
sb.append(name).append(" ID : ").append(idNum);<br />
sb.append(" orbits around : ").append((orbits==null) ? "null" : orbits.name);<br />
sb.append(" next ID : ").append(nextID);<br />
return new Str<strong>in</strong>g(sb);<br />
}<br />
public CelBody getOrbits()<br />
{<br />
return orbits;<br />
}<br />
// ...<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
CelBody sonne = new CelBody("Sun");<br />
CelBody erde = new CelBody("Earth", sonne);<br />
CelBody mond = new CelBody("Moon", erde);<br />
// ...<br />
}<br />
Name : ID : 0 orbits around : null next ID : 1<br />
Name : Sun ID : 1 orbits around : null next ID : 2<br />
Name : ID : 0 orbits around : null next ID : 2<br />
Name : Earth ID : 2 orbits around : Sun next ID : 3<br />
Name : ID : 0 orbits around : null next ID : 3<br />
Name : Moon ID : 3 orbits around : Earth next ID : 4
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 453 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Initialisierungsblöcke <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Innerhalb Klassendef<strong>in</strong>itionen können auch sogenannte Initialisierungsblöcke def<strong>in</strong>iert werden.<br />
◇ Initialisierungsblöcke s<strong>in</strong>d <strong>in</strong> das Klammerpaar { und } e<strong>in</strong>geschlossene Anweisungsfolgen, die ausserhalb<br />
jeder Memberfunktion stehen.<br />
◇ Sie stellen e<strong>in</strong>e Erweiterung der (Feld-)Initialisierer dar und ermöglichen e<strong>in</strong>e komplexe nicht-triviale Initialisierung<br />
der Datenkomponenten e<strong>in</strong>er Klasse.<br />
◇ Sie werden konkurierend zu der Auswertung der (Feld-)Initialisierer ausgeführt, wobei sich die Reihenfolge nach der<br />
Auftritts-Reihenfolge <strong>in</strong> der Klassendef<strong>in</strong>ition richtet.<br />
◇ E<strong>in</strong>em Initialisierungsblock können ke<strong>in</strong>e Parameter übergeben werden.<br />
◇ E<strong>in</strong> Initialisierungsblock darf ke<strong>in</strong>e return-Anweisung enthalten ( Compiler-Fehler).<br />
◇ Obwohl für die Initialisierung von Datenkomponenten vorgesehen, kann e<strong>in</strong> Initialisierunsgblock pr<strong>in</strong>zipiell beliebigen<br />
Code ausführen.<br />
◇ Es gibt<br />
▻ Objekt-Initialisierungsblöcke (<strong>in</strong>stance <strong>in</strong>itializer) und<br />
▻ Klassen-Initialisierungsblöcke (statische Initialisierungsblöcke, static <strong>in</strong>itializer)<br />
• Objekt-Initialisierungsblöcke (<strong>in</strong>stance <strong>in</strong>itializer)<br />
◇ Objekt-Initialisierungsblöcke werden bei jeder Instanzierung der Klasse ausgeführt.<br />
Sie sollen zur Initialisierung der objektspezifischen Datenkomponenten (Instanz-Variablen) dienen.<br />
◇ Mehrere Objekt-Initialisierungsblöcke werden zusammen mit eventuellen Initialisierern für die Instanz-Variablen <strong>in</strong><br />
der Reihenfolge ihres Auftritts <strong>in</strong> der Klassendef<strong>in</strong>ition zu e<strong>in</strong>er e<strong>in</strong>zigen Initialisierungsrout<strong>in</strong>e zusammengefasst.<br />
Diese wirkt so, als ob sie zu Beg<strong>in</strong>n jedes Konstruktors der Klasse stehen würden.<br />
◇ Objekt-Initialisierungsblöcke können das aktuelle Objekt mittels der this-Referenz referieren.<br />
◇ E<strong>in</strong> Objekt-Initialisierungsblock darf nur dann e<strong>in</strong>e geprüfte Exception werfen, wenn alle Konstruktoren diese<br />
Exception (oder e<strong>in</strong>e ihrer Basisklassen) als werfbar deklariert haben.<br />
◇ Objekt-Initialisierungsblöcke lassen sich s<strong>in</strong>nvoll als Ersatz von no-arg-Konstruktoren e<strong>in</strong>setzen, wenn deren Funktio-<br />
nalität <strong>in</strong> jedem anderen Konstruktor verwendet werden soll (expliziter Aufruf des no-arg-Konstruktors), der no-arg-<br />
Konstruktor für die Objekt-Erzeugung aber direkt nicht benötigt wird.<br />
◇ Beispiel :<br />
public class CelBody2<br />
{ private long idNum;<br />
private Str<strong>in</strong>g name ;<br />
private CelBody2 orbits;<br />
private static long nextID = 1;<br />
}<br />
{ // Objekt-Initialisierungsblock<br />
name = "";<br />
System.out.pr<strong>in</strong>tln(toStr<strong>in</strong>g());<br />
idNum = nextID++;<br />
}<br />
public CelBody2(Str<strong>in</strong>g bName, CelBody2 orbAround)<br />
{ name = bName;<br />
orbits = orbAround;<br />
System.out.pr<strong>in</strong>tln(toStr<strong>in</strong>g());<br />
}<br />
// ...
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 454 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Klassen-Initialisierungsblöcke (static <strong>in</strong>itializer)<br />
Initialisierungsblöcke <strong>in</strong> <strong>Java</strong> (2)<br />
◇ Klassen-Initialisierungsblöcke werden nur e<strong>in</strong>mal beim Laden e<strong>in</strong>er Klasse <strong>in</strong> die JVM ausgeführt.<br />
Sie sollen zur Initialisierung der klassenspezifischen (statischen) Datenkomponenten (Klassen-Variablen) dienen.<br />
◇ Syntax :<br />
◇ Mehrere Klassen-Initialisierungsblöcke werden zusammen mit eventuellen Initialisierern für die Klassen-Variablen <strong>in</strong><br />
der Reihenfolge ihres Auftritts <strong>in</strong> der Klassendef<strong>in</strong>ition zu e<strong>in</strong>er e<strong>in</strong>zigen Initialisierungsrout<strong>in</strong>e zusammengefasst.<br />
Diese kann im Pr<strong>in</strong>zip als e<strong>in</strong>e Art "Klassen-Konstruktor" aufgefasst werden.<br />
◇ E<strong>in</strong> Klassen-Initialisierungsblock kann nur statische Komponenten se<strong>in</strong>er Klasse referieren.<br />
◇ E<strong>in</strong> Klassen-Initialisierungsblock darf ke<strong>in</strong>e geprüften Exceptions werfen.<br />
◇ Beispiele für Anwendungen :<br />
▻ Initialisierung von statischen Datenkomponenten, deren Wertermittlung komplexerer Natur ist. Häufig handelt<br />
es sich hierbei um den Aufbau von Tabellen (z.B. Codetabellen, Tabellen mathematischer Funktionswerte usw).<br />
▻ E<strong>in</strong>lesen von <strong>in</strong> Masch<strong>in</strong>encode vorliegenden Bibliotheks-Rout<strong>in</strong>en, die native-Methoden implementieren<br />
(durch Aufruf von System.load(...) bzw System.loadLibrary()).<br />
◇ Beispiel :<br />
static<br />
Anweisung<br />
{ }<br />
public class Circle<br />
{<br />
// Lookup-Tabellen fuer s<strong>in</strong>- und cos<strong>in</strong>-Werte<br />
static private f<strong>in</strong>al <strong>in</strong>t NUM_VALS = 1000;<br />
static private double s<strong>in</strong>es[] = new double[NUM_VALS];<br />
static private double cos<strong>in</strong>es[] = new double[NUM_VALS];<br />
}<br />
// Klassen-Initialisierungsblock zum Fuellen der Lookup-Tabellen<br />
static<br />
{<br />
double x, deltaX;<br />
<strong>in</strong>t i;<br />
deltaX = (Math.PI/2)/(NUM_VALS-1);<br />
for (i=0, x = 0.0; i < NUM_VALS; i++, x += deltaX)<br />
{ s<strong>in</strong>es[i] = Math.s<strong>in</strong>(x);<br />
cos<strong>in</strong>es[i] = Math.cos(x);<br />
}<br />
System.out.pr<strong>in</strong>tln("Lookup-Tabellen <strong>in</strong>itialisiert !");<br />
}<br />
// ...<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
System.out.pr<strong>in</strong>tln("Klasse Circle wird verwendet !");<br />
}<br />
Lookup-Tabellen <strong>in</strong>itialisiert !<br />
Klasse Circle wird verwendet !
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 461 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zip und Eigenschaften<br />
Vererbung <strong>in</strong> <strong>Java</strong> (1)<br />
◇ E<strong>in</strong>e Klasse kann durch Vererbung erweitert (extended, subclassed) werden Def<strong>in</strong>ition e<strong>in</strong>er abgeleiteten Klasse.<br />
Die abgeleitete Klasse (subclass, extended class) erbt alle Datenkomponenten und Memberfunktionen ihrer Basis-<br />
klasse (superclass)<br />
Sie kann neue Datenkomponenten und Methoden h<strong>in</strong>zufügen. Ergänzung / Änderung des Verhaltens der Klasse<br />
◇ Die <strong>in</strong> der abgeleiteten Klasse neu def<strong>in</strong>ierten Komponenten können den gleichen Namen wie Komponenten der<br />
Basisklasse tragen. In e<strong>in</strong>em derartigen Fall werden die gleichnamigen Komponenten der Basisklasse entweder<br />
überdeckt oder überschrieben oder überladen.<br />
◇ Von e<strong>in</strong>er als f<strong>in</strong>al vere<strong>in</strong>barten Klasse können ke<strong>in</strong>e weiteren Klassen abgeleitet werden.<br />
◇ In <strong>Java</strong> hat jede Klasse, die nicht explizit von e<strong>in</strong>er anderen Klasse abgeleitet ist, die Klasse Object als direkte<br />
Basisklasse.<br />
◇ Da <strong>in</strong> <strong>Java</strong> nur e<strong>in</strong>fache Vererbung möglich ist, besitzt jede Klasse – außer der Klasse Object – genau e<strong>in</strong>e Basis-<br />
klasse.<br />
◇ E<strong>in</strong> Objekt e<strong>in</strong>er abgeleiteten Klasse kann überall verwendet werden, wo e<strong>in</strong> Objekt der Basisklasse benötigt wird.<br />
Referenzvariable e<strong>in</strong>er Basisklasse können auch auf Objekte abgeleiteter Klassen zeigen.<br />
Polymorphie.<br />
Abgeleitete Klassen s<strong>in</strong>d zuweisungs-kompatibel zu ihren Basisklassen.<br />
◇ In jedem Objekt e<strong>in</strong>er abgeleiteten Klasse steht mit dem Schlüsselwort super e<strong>in</strong>e Referenz auf das <strong>in</strong> ihm enthal-<br />
tene Basisklassen-Teilobjekt zur Verfügung.<br />
Mittels der super-Referenz können nur Komponenten der Basisklasse angesprochen sowie Basisklassen-Kon-<br />
struktoren aufgerufen werden. Sie kann nicht – wie this – alle<strong>in</strong> benutzt werden, um das Basisklasen-Teilobjekt<br />
<strong>in</strong>sgesamt anzusprechen.<br />
• Syntax zur Angabe der Basisklasse <strong>in</strong> der Klassendef<strong>in</strong>ition (extends-Deklaration)<br />
Klassen-Ableitung :<br />
• Konstruktoren von abgeleiteten Klassen<br />
extends<br />
Basisklassenname<br />
◇ E<strong>in</strong> Konstruktor kann nur die Datenkomponenten der eigenen Klasse <strong>in</strong>itialisieren.<br />
Die Initialisierung der geerbten Datenkomponenten der Basisklasse muß durch e<strong>in</strong>en Konstruktor der Basisklasse<br />
erfolgen.<br />
◇ Jeder Aufruf e<strong>in</strong>es Konstruktors muß daher als erstes den Aufruf e<strong>in</strong>es Konstruktors der Basisklasse bewirken.<br />
Dies kann erfolgen durch :<br />
▻ den expliziten Aufruf e<strong>in</strong>es Basisklassen-Konstruktors mittels super(...).<br />
Dieser Aufruf muß die erste Anweisung im Konstruktor der abgeleiteten Klasse se<strong>in</strong><br />
▻ den <strong>in</strong>direkten Aufruf e<strong>in</strong>es Basisklassen-Konstruktors über den Aufruf e<strong>in</strong>es anderen Konstruktors der abge-<br />
leiteten (also der eigenen) Klasse mittels this(...).<br />
Der Aufruf this(...) muß die erste Anweisung im Konstruktor der abgeleiteten Klasse se<strong>in</strong>.<br />
▻ den impliziten Aufruf des no-arg-Konstruktors der Basisklasse, wenn die erste Anweisung im Konstruktor der<br />
abgeleiteten Klasse weder super(...) noch this(...) ist.<br />
◇ Nach der Abarbeitung des Basisklassen-Konstruktors werden zunächst die Initialisierer der Instanz-Variablen und<br />
die Objekt-Initialisierungsblöcke der eigenen (abgeleiteten) Klasse ausgewertet.<br />
Erst danach werden die – übrigen – Anweisungen im Rumpf des Konstruktors ausgeführt.<br />
◇ Anmerkung : In den Parameter-Ausdrücken e<strong>in</strong>es expliziten Konstruktorsaufrufs (mittels super(...) oder<br />
this(...)) darf ke<strong>in</strong>e Komponente des aktuellen Objekts referiert werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 462 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Überschreiben von Methoden (Overrid<strong>in</strong>g)<br />
Vererbung <strong>in</strong> <strong>Java</strong> (2)<br />
◇ E<strong>in</strong>e <strong>in</strong> der abgeleiteten Klasse def<strong>in</strong>ierte Methode mit gleichem Namen und gleicher Parameterliste ( == gleicher<br />
Signatur) sowie gleichem Rückgabetyp wie <strong>in</strong> der Basisklasse, überschreibt die Methode der Basisklasse.<br />
Hierdurch wird die Basisklassen-Implementierung der Methode für die abgeleitete Klasse durch e<strong>in</strong>e neue Imple-<br />
mentierung ersetzt.<br />
◇ Handelt es sich bei der überschriebenen Funktion um e<strong>in</strong>e abstrakte Methode (Deklaration als abstract), so wird<br />
sie durch die überschreibende Funktion erst implementiert.<br />
◇ Ausnahme von der Gleichheit der Parameterlisten : Parameter dürfen sich <strong>in</strong> der f<strong>in</strong>al-Eigenschaft unterscheiden.<br />
◇ Die Def<strong>in</strong>ition e<strong>in</strong>er Methode <strong>in</strong> der abgeleiteten Klasse, die sich nur im Rückgabetyp von e<strong>in</strong>er Methode gleichen<br />
Namens <strong>in</strong> der Basisklasse unterscheidet, ist e<strong>in</strong> Fehler.<br />
◇ Es können nur Methoden überschrieben werden, die weder als static noch als private noch als f<strong>in</strong>al<br />
vere<strong>in</strong>bart s<strong>in</strong>d.<br />
In <strong>Java</strong> ist jede nichtstatische Methode der Basisklasse, die nicht private oder f<strong>in</strong>al ist, grundsätzlich<br />
virtuell.<br />
◇ Beim Aufruf e<strong>in</strong>er derartigen Methode über e<strong>in</strong>e Basisklassen-Referenz wird die <strong>in</strong> der tatsächlichen Klasse des<br />
aktuell referierten Objekts def<strong>in</strong>ierte Methode ausgeführt ( late b<strong>in</strong>d<strong>in</strong>g, Polymorphie !)<br />
◇ E<strong>in</strong>e <strong>in</strong> der abgeleiteten Klasse def<strong>in</strong>ierte überschreibende Funktion darf die <strong>in</strong> der Basisklasse festgelegte Zugriffs-<br />
berechtigung nicht e<strong>in</strong>schränken.<br />
E<strong>in</strong>e Erweiterung der Zugriffsberechtigung ist zulässig.<br />
Beispiel : Wenn <strong>in</strong> der Basisklasse für e<strong>in</strong>e Methode protected festgelegt ist, darf e<strong>in</strong>e überschreibende Methode<br />
<strong>in</strong> der abgeleiteten Klasse protected oder public se<strong>in</strong>, jedoch nicht private oder package.<br />
◇ Die übrigen Methoden-Modifizierer dürfen wie folgt verändert werden :<br />
▻ synchronized, native und strictfp können beliebig verändert (entfernt oder h<strong>in</strong>zugefügt) werden<br />
▻ abstract kann entfernt oder h<strong>in</strong>zugefügt werden.<br />
▻ e<strong>in</strong>e überschreibende Methode kann f<strong>in</strong>al gemacht werden.<br />
▻ e<strong>in</strong>e überschreibende Methode kann nicht static se<strong>in</strong>.<br />
◇ Bezüglich der Exception-Deklaration (throws-Klausel) gelten folgende Regeln :<br />
▻ Die Exception-Deklarationen von überschreibender und überschriebener Methode können unterschiedlich se<strong>in</strong>.<br />
▻ E<strong>in</strong>e überschreibende Methode darf <strong>in</strong> ihrer Exception-Deklaration nur Exception-Typen enthalten, die zu<br />
e<strong>in</strong>em <strong>in</strong> der Exception-Deklaration der überschriebenen Methode festgelegten Typen polymorph kompatibel<br />
(d.h. von der gleichen Klasse oder e<strong>in</strong>er von ihr abgeleiteten Klasse) s<strong>in</strong>d.<br />
▻ E<strong>in</strong>e überschreibende Methode muss nicht alle von der überschriebenen Methode deklarierten Exception-Typen<br />
ebenfalls deklarieren.<br />
Auch wenn die überschriebene Methode e<strong>in</strong>e Exception-Deklaration hat, darf diese bei der überschreibenden<br />
Methode fehlen.<br />
▻ E<strong>in</strong>e überschreibende Methode darf nichtgeprüfte Exceptions werfen, die <strong>in</strong> der überschriebenen Methode nicht<br />
auftreten können. Diese dürfen aber nicht <strong>in</strong> die Exception-Deklaration aufgenommen werden.<br />
◇ Zu der überschriebenen Methode kann – <strong>in</strong>nerhalb der überschreibenden Methode oder <strong>in</strong> e<strong>in</strong>er anderen Instanz-<br />
Methode der gleichen Klasse – über die Basisklassen-Teilobjekt-Referenz super zugegriffen werden.<br />
super.method(...) ruft immer die Implementierung der Methode method(...) auf, die <strong>in</strong> der direkten<br />
Basisklasse verwendet wird.<br />
Es kann sich dabei durchaus um e<strong>in</strong>e Methode handeln, die <strong>in</strong> der Ableitungshierarchie "weiter oben" def<strong>in</strong>iert und <strong>in</strong><br />
der direkten Basisklasse selbst nicht neu def<strong>in</strong>iert worden ist.<br />
◇ E<strong>in</strong> Zugriff zur überschriebenen Methode über ihren vollqualifizierten Namen ist nicht möglich ( Compiler-Fehler).<br />
◇ E<strong>in</strong> Cast e<strong>in</strong>er Referenz auf e<strong>in</strong> Objekt der abgeleiteten Klasse <strong>in</strong> die Basisklassen-Referenz ändert nicht den tatsäch-<br />
lichen Typ des referierten Objekts. Über e<strong>in</strong>en derartigen Cast kann daher nicht zur überschriebenen sondern nur zur<br />
überschreibenden Methode zugegriffen werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 463 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Überladen von Methoden (Overload<strong>in</strong>g)<br />
Vererbung <strong>in</strong> <strong>Java</strong> (3)<br />
◇ E<strong>in</strong>e <strong>in</strong> der abgeleiteten Klasse def<strong>in</strong>ierte Methode mit gleichem Namen aber anderer Parameterliste, überlädt die<br />
Methode der Basisklasse.<br />
Der Rückgabetyp bleibt unberücksichtigt, er kann gleich oder unterschiedlich se<strong>in</strong>.<br />
Das gleiche gilt für die Exception-Deklaration (throws-Klausel).<br />
◇ In der abgeleiteten Klasse kann sowohl zu der geerbten Methode der Basisklasse als auch zu der neu def<strong>in</strong>ierten<br />
Methode alle<strong>in</strong> über ihren Namen zugegriffen werden.<br />
<strong>in</strong> <strong>Java</strong> ist – anders als <strong>in</strong> C++ – e<strong>in</strong> Überladen von Methoden auch über Klassengrenzen h<strong>in</strong>weg möglich.<br />
◇ Zusätzlich können Methoden natürlich auch <strong>in</strong>nerhalb e<strong>in</strong>er Klasse überladen werden.<br />
◇ Wenn <strong>in</strong> der Basisklasse zwei Methoden überladen s<strong>in</strong>d, ist es möglich, dass nur e<strong>in</strong>e der Methoden <strong>in</strong> e<strong>in</strong>er abgelei-<br />
teten Klasse überschrieben wird. Die andere steht dann auch <strong>in</strong> der abgeleiteten Klasse als überladene Funktion zur<br />
Verfügung. Das Überschreiben von Methoden erfolgt auf der Basis der Signaturen.<br />
C++ verhält sich <strong>in</strong> e<strong>in</strong>em derartigen Fall anders : Durch das Überschreiben e<strong>in</strong>er Methode werden sämtliche weiteren<br />
überladenen Methoden der Basisklasse überdeckt.<br />
◇ Auch statische Methoden können im obigen S<strong>in</strong>n überladen werden.<br />
◇ Ferner können statische Methoden nicht-statische Methoden und umgekehrt überladen.<br />
• Überdecken von Klassenkomponenten (Hid<strong>in</strong>g)<br />
◇ Statische Methoden können überdeckt statt überschrieben werden.<br />
E<strong>in</strong>e <strong>in</strong> der abgeleiteten Klasse def<strong>in</strong>ierte statische Methode mit gleicher Signatur sowie gleichen Rückgabetyps wie<br />
e<strong>in</strong>e statische Methode der Basisklasse, überdeckt die Methode der Basisklasse.<br />
◇ E<strong>in</strong>e statische Methode darf ke<strong>in</strong>e Instanz-Methode überdecken ( Compiler-Fehler)<br />
◇ Überdecken von Datenkomponenten ist zulässig<br />
▻ zwischen Instanz-Variablen (nicht-statischen Datenkomponenten)<br />
▻ zwischen Klassen-Variablen (statischen Datenkomponenten)<br />
▻ gemischt zwischen Instanz- und Klassen-Variablen.<br />
◇ Das Überdecken zwischen Datenkomponenten unterschiedlichen Typs ist zulässig.<br />
◇ Überdeckt werden genaugenommen Namen.<br />
Überdecken e<strong>in</strong>es Namens bedeutet, dass <strong>in</strong> der abgeleiteten Klasse der Name alle<strong>in</strong> nur <strong>in</strong> der <strong>in</strong> dieser Klasse defi-<br />
nierten Bedeutung verwendet werden kann.<br />
Um den Namen <strong>in</strong> der Bedeutung, die <strong>in</strong> der Basisklasse def<strong>in</strong>iert ist, zu verwenden, muss der entsprechende voll-<br />
qualifizierte Name oder der Name zusammen mit e<strong>in</strong>er anderen Basisklassen-Referenz (z.B. super.kompo,<br />
<strong>in</strong>nerhalb e<strong>in</strong>er Instanz-Methode) verwendet werden.<br />
Die Verwendung des vollqualifizierten Namens ist nur für statische Komponenten zulässig.<br />
◇ Beim Zugriff zu überdeckten Komponenten wird die tatsächlich ausgewählte Komponente durch die deklarierte<br />
Klasse der verwendeten Referenz (und nicht durch die Klasse des referierten Objekts) festgelegt. (Festlegung zur<br />
Compile-Zeit, early b<strong>in</strong>d<strong>in</strong>g)<br />
◇ Zwischen e<strong>in</strong>er Variablen und e<strong>in</strong>er Funktion gleichen Namens f<strong>in</strong>det ke<strong>in</strong> Überdecken statt.<br />
Beide können gleichzeitig alle<strong>in</strong> mit ihrem Namen verwendet werden.<br />
Das gilt auch, wenn beide <strong>in</strong> derselben Klasse def<strong>in</strong>iert s<strong>in</strong>d.<br />
◇ E<strong>in</strong>e als private deklarierte Komponente kann weder überschrieben noch überdeckt werden (Sie ist ja <strong>in</strong> der<br />
abgeleiteten Klasse überhaupt nicht zugänglich).<br />
Ihr Name kann deshalb <strong>in</strong> der abgeleiteten Klasse für beliebige Def<strong>in</strong>itionen verwendet werden.<br />
Beispielsweise ist es bei e<strong>in</strong>er Memberfunktion zulässig, <strong>in</strong> der abgeleiteten Klasse e<strong>in</strong>e Methode mit gleicher<br />
Signatur aber unterschiedlichem Rückgabetyp zudef<strong>in</strong>ieren.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 464 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Vererbung <strong>in</strong> <strong>Java</strong> (4-1)<br />
• Demonstrationsbeispiel zum Überschreiben und Überladen von Methoden<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er Basisklasse Punkt<br />
public class Punkt<br />
{<br />
private double x = 0.0;<br />
private double y = 0.0;<br />
}<br />
public Punkt()<br />
{ }<br />
public Punkt(double wx, double wy)<br />
{ x = wx; y = wy; }<br />
public Punkt move(double dx, double dy)<br />
{ x += dx; y += dy; return this; }<br />
public Punkt change(Punkt p)<br />
{ x = p.x; y = p.y; return this;<br />
}<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
{ Str<strong>in</strong>gBuffer hb = new Str<strong>in</strong>gBuffer();<br />
hb.append('(').append(x).append(" , ").append(y).append(')');<br />
return new Str<strong>in</strong>g(hb);<br />
}<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er abgeleiteten Klasse Farbpunkt<br />
public class Farbpunkt extends Punkt<br />
{<br />
private Str<strong>in</strong>g col;<br />
public Farbpunkt()<br />
{ this("black"); }<br />
public Farbpunkt(Str<strong>in</strong>g wcol)<br />
{ super(); col = wcol; }<br />
public Farbpunkt(double wx, double wy)<br />
{ this(wx, wy, "black"); }<br />
public Farbpunkt(double wx, double wy, Str<strong>in</strong>g wcol)<br />
{ super(wx, wy); col = wcol; }<br />
public Farbpunkt change(Str<strong>in</strong>g ncol) // ueberlaedt Basisklassenmethode<br />
{ col = ncol; return this; }<br />
public Farbpunkt change(Farbpunkt fp) // ueberlaedt Basisklassenmethode<br />
{ change((Punkt)fp);<br />
change(fp.col);<br />
return this;<br />
}<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g() // ueberschreibt Basisklassenmethode<br />
{ Str<strong>in</strong>gBuffer hb = new Str<strong>in</strong>gBuffer(super.toStr<strong>in</strong>g());<br />
hb.append(" & ").append(col);<br />
return new Str<strong>in</strong>g(hb);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 464 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Vererbung <strong>in</strong> <strong>Java</strong> (4-2)<br />
• Demonstrationsbeispiel zum Überschreiben und Überladen von Methoden, Forts<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er verwendenden Test-Klasse PunktTest<br />
// PunktTest.java<br />
public class PunktTest<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Punkt p1 = new Punkt(4.2, 6.3);<br />
Punkt p2 = new Farbpunkt();<br />
Farbpunkt p3 = new Farbpunkt(1.8, 7.9);<br />
Punkt p4 = new Farbpunkt("magenta");<br />
Farbpunkt p5 = new Farbpunkt(2.5, 3.7, "blue");<br />
System.out.pr<strong>in</strong>tln("p1 : " + p1);<br />
System.out.pr<strong>in</strong>tln("p2 : " + p2);<br />
System.out.pr<strong>in</strong>tln("p3 : " + p3);<br />
System.out.pr<strong>in</strong>tln("p4 : " + p4);<br />
System.out.pr<strong>in</strong>tln("p5 : " + p5);<br />
System.out.pr<strong>in</strong>tln("nach e<strong>in</strong>igen Aenderungen : ");<br />
p3.move(1.0, 1.0);<br />
System.out.pr<strong>in</strong>tln("p3 : " + p3);<br />
p3.change("yellow");<br />
System.out.pr<strong>in</strong>tln("p3 : " + p3);<br />
p5.change(p1);<br />
System.out.pr<strong>in</strong>tln("p5 : " + p5);<br />
p3.change(p5);<br />
System.out.pr<strong>in</strong>tln("p3 : " + p3);<br />
}<br />
}<br />
◇ Ausgabe des Demonstrations-Programms<br />
p1 : (4.2 , 6.3)<br />
p2 : (0.0 , 0.0) & black<br />
p3 : (1.8 , 7.9) & black<br />
p4 : (0.0 , 0.0) & magenta<br />
p5 : (2.5 , 3.7) & blue<br />
nach e<strong>in</strong>igen Aenderungen :<br />
p3 : (2.8 , 8.9) & black<br />
p3 : (2.8 , 8.9) & yellow<br />
p5 : (4.2 , 6.3) & blue<br />
p3 : (4.2 , 6.3) & blue
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 465 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Vererbung <strong>in</strong> <strong>Java</strong> (5)<br />
• Demonstrationsbeispiel zum Überdecken und Überladen von statischen Methoden<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er Basisklasse Ober2<br />
class Ober2<br />
{<br />
public static Str<strong>in</strong>g gruss()<br />
{<br />
return "sagt Hallo !";<br />
}<br />
}<br />
public Str<strong>in</strong>g name()<br />
{<br />
return "Ober2 ";<br />
}<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er abgeleiteten Klasse Unter2<br />
class Unter2 extends Ober2<br />
{<br />
public static Str<strong>in</strong>g gruss() // ueberdeckt Basisklassen-Methode<br />
{<br />
return "sagt Guten-Morgen !";<br />
}<br />
}<br />
public static Str<strong>in</strong>g gruss(Str<strong>in</strong>g gr) // ueberlaedt Basisklassen-Methode<br />
{<br />
return "sagt " + gr;<br />
}<br />
public Str<strong>in</strong>g name() // ueberschreibt Basisklassen-Methode<br />
{<br />
return "Unter2 ";<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Ober2 s = new Ober2();<br />
System.out.pr<strong>in</strong>tln(s.name() + s.gruss());<br />
s = new Unter2();<br />
System.out.pr<strong>in</strong>tln(s.name() + s.gruss());<br />
Unter2 u = new Unter2();<br />
System.out.pr<strong>in</strong>tln(u.name() + u.gruss());<br />
System.out.pr<strong>in</strong>tln(u.name() + u.gruss("Servus !"));<br />
System.out.pr<strong>in</strong>tln(u.name() + gruss());<br />
System.out.pr<strong>in</strong>tln(u.name() + Ober2.gruss());<br />
}<br />
◇ Ausgabe des Demonstrations-Programms<br />
Ober2 sagt Hallo !<br />
Unter2 sagt Hallo !<br />
Unter2 sagt Guten-Morgen !<br />
Unter2 sagt Servus !<br />
Unter2 sagt Guten-Morgen !<br />
Unter2 sagt Hallo !
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 466 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Vererbung <strong>in</strong> <strong>Java</strong> (6)<br />
• Demonstrationsbeispiel zum Überdecken von Datenkomponenten<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er Basisklasse Ober3<br />
class Ober3<br />
{<br />
protected <strong>in</strong>t me<strong>in</strong>W = 125;<br />
protected static float de<strong>in</strong>W = 6.35f;<br />
}<br />
protected <strong>in</strong>t val = 23;<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>er abgeleiteten Klasse Unter3<br />
class Unter3 extends Ober3<br />
{<br />
private static double me<strong>in</strong>W = 3.5;<br />
private float de<strong>in</strong>W = 5.2f;<br />
}<br />
public <strong>in</strong>t val()<br />
{<br />
return val;<br />
}<br />
public void nutzeWerte()<br />
{<br />
System.out.pr<strong>in</strong>tln("<strong>in</strong> Unter3 : me<strong>in</strong>W " + me<strong>in</strong>W + " de<strong>in</strong>W " + de<strong>in</strong>W);<br />
System.out.pr<strong>in</strong>t( "<strong>in</strong> Ober3 : me<strong>in</strong>W " + super.me<strong>in</strong>W);<br />
System.out.pr<strong>in</strong>tln(" de<strong>in</strong>W " + super.de<strong>in</strong>W);<br />
System.out.pr<strong>in</strong>t( "<strong>in</strong> Ober3 : me<strong>in</strong>W " + super.me<strong>in</strong>W);<br />
System.out.pr<strong>in</strong>tln(" de<strong>in</strong>W " + Ober3.de<strong>in</strong>W);<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Unter3 u = new Unter3();<br />
u.nutzeWerte();<br />
System.out.pr<strong>in</strong>tln();<br />
System.out.pr<strong>in</strong>tln("val direkt : " + u.val);<br />
System.out.pr<strong>in</strong>tln("val ueber Fkt : " + u.val());<br />
}<br />
◇ Ausgabe des Demonstrations-Programms<br />
<strong>in</strong> Unter3 : me<strong>in</strong>W 3.5 de<strong>in</strong>W 5.2<br />
<strong>in</strong> Ober3 : me<strong>in</strong>W 125 de<strong>in</strong>W 6.35<br />
<strong>in</strong> Ober3 : me<strong>in</strong>W 125 de<strong>in</strong>W 6.35<br />
val direkt : 23<br />
val ueber Fkt : 23
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 467 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Typkompatibilität und -umwandlung<br />
Vererbung <strong>in</strong> <strong>Java</strong> (7)<br />
◇ E<strong>in</strong>e abgeleitete Klasse ist zuweisungs-kompatibel zu ihrer Basisklasse.<br />
E<strong>in</strong>er Basisklassen-Variablen kann jederzeit e<strong>in</strong>e Referenz auf e<strong>in</strong> Objekt e<strong>in</strong>er von der Basisklasse abgeleiteten<br />
Klasse zugewiesen werden.<br />
◇ Das durch e<strong>in</strong>e Basisklassen-Variable referierte Objekt e<strong>in</strong>er abgeleiteten Klasse wird dadurch als Objekt der<br />
Basisklasse behandelbar.<br />
Implizite Typumwandlung.<br />
Da von e<strong>in</strong>em spezialisierteren Typ <strong>in</strong> e<strong>in</strong>en allgeme<strong>in</strong>eren Typ umgewandelt wird, spricht man auch von e<strong>in</strong>er<br />
erweiternden Typumwandlung (widen<strong>in</strong>g conversion).<br />
Weil diese Umwandlung <strong>in</strong> der Klassen-Hierarchie aufwärts erfolgt nennt man sie auch Aufwärts-Cast (upcast).<br />
◇ Die Zuweisung e<strong>in</strong>er Basisklassen-Referenz, die aber tatsächlich auf e<strong>in</strong> Objekt e<strong>in</strong>er abgeleiteten Klasse zeigt, an<br />
e<strong>in</strong>e Variable des tatsächlich referierten Typs ist nicht implizit möglich.<br />
Sie erfordert e<strong>in</strong>e explizite Typumwandlung mittels des Cast-Operators.<br />
Hierbei f<strong>in</strong>det e<strong>in</strong>e Umwandlung von e<strong>in</strong>em allgeme<strong>in</strong>eren Typ <strong>in</strong> e<strong>in</strong>en spezialisierteren Typ statt. Man nennt dies<br />
e<strong>in</strong>e e<strong>in</strong>engende Typumwandlung (narrow<strong>in</strong>g conversion) oder e<strong>in</strong>en Abwärts-Cast (down cast).<br />
◇ E<strong>in</strong> Abwärts-Cast ist pr<strong>in</strong>zipiell unsicher.<br />
Er darf nur dann durchgeführt werden, wenn durch die Basisklassen-Referenz tatsächlich e<strong>in</strong> Objekt des angege-<br />
benen Zieltyps referiert wird.<br />
Der Versuch e<strong>in</strong>er Typumwandlung, bei der dies nicht erfüllt ist, führt zum Werfen e<strong>in</strong>er Exception vom Typ<br />
ClassCastException.<br />
• Der Operator <strong>in</strong>stanceof<br />
◇ Dieser b<strong>in</strong>äre Operator ermöglicht die Überprüfung, ob e<strong>in</strong> Ausdruck zuweisungskompatibel zu e<strong>in</strong>em bestimmten<br />
Typ ist.<br />
◇ Syntax :<br />
◇ Wert e<strong>in</strong>es <strong>in</strong>stanceof-Ausdrucks :<br />
▻ true, wenn der Ausdruck der l<strong>in</strong>ken Seite zuweisungs-kompatibel zum Typ der rechten Seite ist<br />
▻ false, wenn der Ausdruck der l<strong>in</strong>ken Seite nicht zuweisungs-kompatibel zum Typ der rechten Seite ist<br />
◇ Der <strong>in</strong>stanceof-Operator kann e<strong>in</strong>gesetzt werden, um e<strong>in</strong>en sicheren Abwärts-Cast zu ermöglichen.<br />
◇ Beispiel :<br />
class That<br />
{<br />
// ...<br />
}<br />
Ausdruck<br />
class More extends That<br />
{<br />
// ...<br />
}<br />
// ...<br />
That sref = new More();<br />
More mref;<br />
// ...<br />
if (sref <strong>in</strong>stanceof More)<br />
mref=(More)sref;<br />
// ...<br />
<strong>in</strong>stanceof<br />
Typangabe
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 471 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zip<br />
Interfaces <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Interfaces def<strong>in</strong>ieren – ähnlich wie Klassen – Typen.<br />
Allerd<strong>in</strong>gs erfolgt die Def<strong>in</strong>ition <strong>in</strong> e<strong>in</strong>er abstrakten Form, die ke<strong>in</strong>erlei Implementierung bereitstellt.<br />
Damit lassen sich Interfaces nicht <strong>in</strong>stanziieren.<br />
Sie legen – wie der Name bereits ausdrückt – lediglich e<strong>in</strong>e Schnittstelle (Kontrakt) fest, die dann von Klassen imple-<br />
mentiert werden kann.<br />
◇ E<strong>in</strong> Interface besteht – ähnlich wie e<strong>in</strong>e Klasse – aus Komponenten.<br />
Diese Komponenten können aber lediglich se<strong>in</strong> :<br />
▻ abstrakte Methoden<br />
▻ Konstante<br />
▻ e<strong>in</strong>gebettete Klassen und Interfaces<br />
◇ Im Pr<strong>in</strong>zip ähnelt e<strong>in</strong> Interface e<strong>in</strong>er abstrakten Klasse.<br />
Im Unterschied zu e<strong>in</strong>em Interface kann e<strong>in</strong>e abstrakte Klasse aber e<strong>in</strong>e (Teil-) Implementierung enthalten.<br />
(Instanz- und Klassen-Variable, Klassen-Methoden, def<strong>in</strong>ierte Instanz-Methoden).<br />
E<strong>in</strong> Interface kann als abstrakte Klasse, die nur Konstante und abstrakte Methoden (und gegebenenfalls e<strong>in</strong>gebettete<br />
Typen) vere<strong>in</strong>bart, aufgefasst werden ("re<strong>in</strong> abstrakte" Klasse).<br />
◇ Interfaces müssen wie Klassen <strong>in</strong> jeweils e<strong>in</strong>er eigenen Quelldatei (Ausnahme e<strong>in</strong>gebettete Interfaces) def<strong>in</strong>iert<br />
werden, deren Hauptname gleich dem Interface-Namen se<strong>in</strong> muß.<br />
Interfaces werden vom Compiler auch getrennt übersetzt.<br />
• Interface-Def<strong>in</strong>ition<br />
◇ Syntax :<br />
◇ Beispiel :<br />
Interface-<br />
Modifizierer<br />
public <strong>in</strong>terface Fahrbar<br />
{<br />
<strong>in</strong>t MOTOR_UND_REIFEN = 3;<br />
<strong>in</strong>t MOTOR_UND_SCHRAUBE = 5;<br />
<strong>in</strong>t MUSKEL_UND_REIFEN = 2;<br />
<strong>in</strong>t MUSKEL_UND_SCHRAUBE = 4;<br />
<strong>in</strong>t LEHRLAUF = 0;<br />
void setAntrieb(<strong>in</strong>t antr);<br />
void fahreVor(double dist);<br />
void fahreRueck(double dist);<br />
<strong>in</strong>t getAntrieb();<br />
double getFahrZaehler();<br />
}<br />
<strong>in</strong>terface Interface-Name<br />
{<br />
Typ-Param-<br />
Deklaration<br />
Konstantendef<strong>in</strong>ition<br />
Abstrakte-Methoden-Deklaration<br />
Klassen-/Interface-Def<strong>in</strong>ition<br />
;<br />
Interface-<br />
Ableitung<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 472 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Interface-Modifizierer<br />
◇ Zulässig s<strong>in</strong>d :<br />
Interfaces <strong>in</strong> <strong>Java</strong> (2)<br />
▻ public<br />
Ohne diesen Zugriffs-Spezifizierer besitzt jedes Interface die Zugrifssberechtigung package.<br />
▻ abstract<br />
Jedes Interface ist implizit abstract.<br />
E<strong>in</strong>e explizite Angabe dieses Modifizierers ist daher überflüssig.<br />
In der Sprachspezifikation ist sie als "überholt" (obsolete) bezeichnet und sollte daher nicht verwendet werden.<br />
▻ strictfp<br />
Alle Float<strong>in</strong>g-Po<strong>in</strong>t-Ausdrücke <strong>in</strong>nerhalb der Interface-Def<strong>in</strong>ition (z.B. zur Konstanten-Initialisierung bzw <strong>in</strong>nerhalb<br />
e<strong>in</strong>gebetteter Typen) werden FP-strict ausgewertet<br />
◇ Für Interfaces, die <strong>in</strong>nerhalb von Klassen oder anderen Interfaces def<strong>in</strong>iert s<strong>in</strong>d (e<strong>in</strong>gebettete Interfaces, member<br />
<strong>in</strong>terfaces) s<strong>in</strong>d darüber h<strong>in</strong>aus auch zulässig :<br />
▻ protected<br />
▻ private<br />
▻ static<br />
• Def<strong>in</strong>ition von Memberkonstanten (Interface-Konstante)<br />
◇ E<strong>in</strong> Interface darf als Datenkomponenten nur Konstante enthalten.<br />
◇ Jede Datenkomponente ist daher implizit static und f<strong>in</strong>al. Zusätzlich ist sie implizit public.<br />
E<strong>in</strong>e explizite Angabe dieser Feld-Modifizierer ist zwar zulässig, aber überflüssig.<br />
◇ Jede Datenkomponente muß durch e<strong>in</strong>en Initialisierer <strong>in</strong>itialisiert werden. blank f<strong>in</strong>als s<strong>in</strong>d nicht zulässig.<br />
Der Initialisierer muß e<strong>in</strong> konstanter Ausdruck se<strong>in</strong>.<br />
Dieser Ausdruck darf weder den Namen der zu <strong>in</strong>itialisierenden Komponente noch e<strong>in</strong>er Komponente, die erst<br />
später def<strong>in</strong>iert wird, enthalten Compiler-Fehler.<br />
◇ Beispiel :<br />
<strong>in</strong>terface Test<br />
{ float f = j; // Compiler-Fehler !<br />
<strong>in</strong>t j = 1;<br />
<strong>in</strong>t k = k + 1; // Compiler-Fehler !<br />
}<br />
• Deklaration abstrakter Memberfunktionen (Interface-Methoden)<br />
◇ Jede <strong>in</strong> e<strong>in</strong>er Interface-Def<strong>in</strong>ition enthaltene Memberfunktion ist implizit abstract.<br />
Ihre Vere<strong>in</strong>barung muß an Stelle e<strong>in</strong>es Funktionsrumpfes e<strong>in</strong> ; enthalten.<br />
◇ Jede <strong>in</strong> e<strong>in</strong>er Interface-Def<strong>in</strong>ition enthaltene Memberfunktion ist implizit public.<br />
Nichtöffentliche Memberfunktionen machen ke<strong>in</strong>en S<strong>in</strong>n.<br />
◇ E<strong>in</strong>e explizite Verwendung der Modifizierer abstract und public ist zwar zulässig, aber überflüssig und sollte<br />
vermieden werden.<br />
◇ Andere Modifizierer s<strong>in</strong>d unzulässig.<br />
Allerd<strong>in</strong>gs dürfen die <strong>in</strong> implementierenden Klassen enthaltenen Def<strong>in</strong>itionen der Interface-Methoden mit den Modifiern<br />
strictfp, native, synchronized und f<strong>in</strong>al versehen werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 473 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Vererbung von Interfaces<br />
◇ Interfaces können auch vone<strong>in</strong>ander abgeleitet werden<br />
Interfaces <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Es gibt aber ke<strong>in</strong> allgeme<strong>in</strong>es Wurzel-Basis-Interface (etwa wie die Wurzel-Basisklasse Object)<br />
◇ Im Unterschied zu Klassen ist bei Interfaces Mehrfachvererbung zulässig.<br />
E<strong>in</strong> Interface kann von mehreren anderen Interfaces abgeleitet se<strong>in</strong>.<br />
◇ Syntax :<br />
Interface-Ableitung :<br />
extends<br />
Basis-Interface-Name<br />
◇ Beispiel : Bibliotheks-Interfaces Serializable (Package java.io)<br />
Runnable (Package java.lang)<br />
public Interface SerializeAndRunnable<br />
extends java.io.Serializable, Runnable<br />
{<br />
// ...<br />
}<br />
Das Interface SerializeAndRunnable enthält – durch Vererbung – alle Komponenten der Interfaces<br />
Serializable und Runnable. Zusätzlich kann es weitere Komponenten def<strong>in</strong>ieren.<br />
◇ Bei abgeleiteten Interfaces kann ebenfalls Überschreiben, Überladen und Überdecken von Komponenten auftreten.<br />
Pr<strong>in</strong>zipiell gelten hierfür die gleichen Regeln und E<strong>in</strong>schränkungen wie bei abgeleiteten Klassen :<br />
▻ Überschreiben von Memberfunktionen :<br />
Die Deklaration e<strong>in</strong>er Memberfunktion <strong>in</strong> e<strong>in</strong>em abgeleiteten Interface überschreibt alle geerbten Memberfunktionen<br />
mit gleicher Signatur (gleicher Name und gleiche Parameterliste) und gleichem Rückgabetyp.<br />
E<strong>in</strong>e tatsächliche Auswirkung hat e<strong>in</strong> derartiges Überschreiben nur, wenn dadurch im abgeleiteten Interface e<strong>in</strong>e<br />
E<strong>in</strong>schränkung <strong>in</strong> der Exception-Deklaration (throws-Klausel) der Methode vorgenommen wird (s. Vererbung<br />
bei Klassen).<br />
▻ Die Deklaration e<strong>in</strong>er Memberfunktion <strong>in</strong> e<strong>in</strong>em abgeleiteten Interface mit gleicher Signatur aber unterschied-<br />
lichem Rückgabetyp wie <strong>in</strong> e<strong>in</strong>em Basis-Interface ist unzulässig und führt zu e<strong>in</strong>em Compilerfehler.<br />
Gleiches gilt, wenn zwei Methoden mit gleichem Namen und gleicher Signatur aber unterschiedlichen Rückgabe-<br />
typen – von unterschiedlichen Basis-Interfaces – geerbt werden.<br />
▻ Überladen von Memberfunktionen :<br />
Die Deklaration e<strong>in</strong>er Memberfunktion <strong>in</strong> e<strong>in</strong>em abgeleiteten Interface überlädt alle geerbten Memberfunktionen<br />
mit gleichem Namen aber unterschiedlicher Parameterliste. Der Rückgabetyp und die Exception-Deklaration<br />
bleiben unberücksichtigt.<br />
Überladen liegt auch vor, wenn <strong>in</strong>nerhalb desselben Interfaces Methoden mit gleichem Namen aber unterschied-<br />
licher Parameterliste deklariert werden oder wenn alle derartigen Methoden von Basis-Interfaces geerbt werden.<br />
▻ Überdecken von Datenkomponenten (Konstanten)<br />
Die Def<strong>in</strong>ition e<strong>in</strong>er Konstanten <strong>in</strong> e<strong>in</strong>em abgeleiteten Interface überdeckt jede geerbte Konstante gleichen Namens,<br />
unabhängig vom jeweiligen Typ.<br />
Der Zugriff zur geerbten Konstanten ist nur über deren vollqualifizierten Namen möglich.<br />
◇ Erbt e<strong>in</strong> Interface von zwei verschiedenen Basis-Interfaces zwei Methoden gleicher Signatur und gleichem Rückgabe-<br />
typ, so "verschmelzen" diese im abgeleiteten Interface zu e<strong>in</strong>er e<strong>in</strong>zigen Methode.<br />
◇ Erbt e<strong>in</strong> Interface von zwei verschiedenen Basis-Interfaces zwei Konstante gleichen Namens, so kann zu Ihnen<br />
– unabhängig von ihrem jeweiligen Typ – nur über ihren vollqualifizierten Namen zugegriffen werden.<br />
◇ Es ist auch zulässig, dass e<strong>in</strong> Interface dieselbe Methode bzw Konstante auf verschiedenen Ableitungswegen erbt.<br />
Die Methode bzw die Konstante ist <strong>in</strong> dem abgeleiteten Interface nur e<strong>in</strong>mal vorhanden. E<strong>in</strong> Zugriff ist e<strong>in</strong>deutig.<br />
,
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 474 – 00 – TH – 06<br />
------------------------------------------------------------------------------------<br />
• Implementierung von Interfaces<br />
Interfaces <strong>in</strong> <strong>Java</strong> (4)<br />
◇ Der S<strong>in</strong>n von Interfaces liegt <strong>in</strong> der Def<strong>in</strong>ition von Schnittstellen, die zur Realisierung e<strong>in</strong>er Funktionalität durch<br />
Klassen implementiert werden müssen.<br />
◇ E<strong>in</strong>e Klasse, die e<strong>in</strong> Interface implementiert, muß sämtliche Methoden des Interfaces (e<strong>in</strong>schliesslich der von Basis-<br />
Interfaces geerbten) def<strong>in</strong>ieren (d.h. für sie e<strong>in</strong>e Implementierung bereitstellen) oder selbst als abstract deklariert<br />
se<strong>in</strong>. Im letzteren Fall können – müssen aber nicht – die nicht implementierten Methoden des Interfaces als abstrakt<br />
deklariert werden<br />
Pr<strong>in</strong>zipiell entspricht die Implementierung e<strong>in</strong>es Interfaces damit der Ableitung von e<strong>in</strong>er (re<strong>in</strong>) abstrakten Klasse.<br />
◇ E<strong>in</strong>e Klasse kann – gegebenenfalls zusätzlich zur Ableitung von e<strong>in</strong>er Klasse – mehrere Interfaces implementieren.<br />
Realisierung e<strong>in</strong>er Art e<strong>in</strong>geschränkter Mehrfachableitung <strong>in</strong> <strong>Java</strong>.<br />
◇ Syntax :<br />
Interface-Implementierung :<br />
Die implements-Klausel muss nach e<strong>in</strong>er – gegebenenfalls vorhandenen – extends-Klausel aufgeführt werden.<br />
◇ Beispiel :<br />
implements<br />
◇ Die Implementierung e<strong>in</strong>es Interfaces wird auch an abgeleitete Klassen vererbt.<br />
In e<strong>in</strong>em derartigen Fall ist die Angabe e<strong>in</strong>er implements-Klausel bei der abgeleiteten Klasse nicht explizit<br />
notwendig, aber zulässig.<br />
Dem Kopf e<strong>in</strong>er Klassendef<strong>in</strong>ition können nicht <strong>in</strong> jedem Fall die implementierten Interfaces entnommen werden.<br />
Beispiel : public <strong>in</strong>terface GraphObj<br />
{ /* ... */ }<br />
public class Punkt implements GraphObj<br />
{ /* ... */ }<br />
public class Quadrat extends Punkt // implements GraphObj<br />
{ /* ... */ }<br />
Die Klasse Quadrat implementiert auch das Interface GraphObj.<br />
Interface-Name<br />
public class CompCelBody extends CelBody<br />
implements Comparable<br />
{<br />
private <strong>in</strong>t orbDist;<br />
public CompCelBody(Str<strong>in</strong>g bName, CelBody orbAround, <strong>in</strong>t dist)<br />
{ super(bName, orbAround);<br />
orbDist = dist;<br />
}<br />
public <strong>in</strong>t compareTo(CompCelBody o)<br />
{ if (getOrbits() == o.getOrbits())<br />
return orbDist-o.orbDist;<br />
else<br />
throw new IllegalArgumentException("unterschiedlicher Orbit");<br />
}<br />
// ...<br />
}<br />
◇ Ob die Klasse e<strong>in</strong>es Objekts e<strong>in</strong> bestimmtes Interface implementiert, kann mit dem <strong>in</strong>stanceof-Operator<br />
überprüft werden.<br />
Beispiel : Quadrat qd = new Quadrat();<br />
boolean isgo = qd <strong>in</strong>stanceof GraphObj; // true<br />
,
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 475 – 00 – TH – 06<br />
------------------------------------------------------------------------------------<br />
• Interfaces als Objekt-Referenzen<br />
Interfaces <strong>in</strong> <strong>Java</strong> (5)<br />
◇ Objekte e<strong>in</strong>er Klasse, die e<strong>in</strong> Interface implementiert, lassen sich auch als Instanzen des implementierten Inter-<br />
faces behandeln.<br />
Explizite oder implizite Typkonvertierung (cast) e<strong>in</strong>es Objekts <strong>in</strong> den Typ e<strong>in</strong>es implementierten Interfaces.<br />
◇ Man kann Variable e<strong>in</strong>es Interface-Typs def<strong>in</strong>ieren und ihnen Referenzen auf Objekte e<strong>in</strong>er implementierenden<br />
Klasse zuweisen.<br />
Natürlich lassen sich über e<strong>in</strong>e Interface-Variable auch nur die Komponenten e<strong>in</strong>es Objekts ansprechen, die <strong>in</strong> dem<br />
implementierten Interface def<strong>in</strong>iert s<strong>in</strong>d.<br />
◇ Beispiel :<br />
◇ Jede Objekt-Referenz e<strong>in</strong>es Interface-Typs lässt sich allerd<strong>in</strong>gs als Referenz auf die Klasse Object verwenden.<br />
Damit lassen sich über e<strong>in</strong>e Interface-Variable auch die <strong>in</strong> der Klasse Object def<strong>in</strong>ierten Methoden aufrufen.<br />
Dies ist deswegen möglich, da ja das referierte Objekt von irgende<strong>in</strong>er Klasse se<strong>in</strong> muß und jede Klasse von Object<br />
abgeleitet ist.<br />
Beispiel : // ...<br />
GraphObj go = new FPunkt(5,5, Color.BLACK);<br />
Str<strong>in</strong>g str = go.toStr<strong>in</strong>g(); // ke<strong>in</strong>e Methode von GraphObj, aber von Object<br />
// ...<br />
• Marker Interfaces<br />
◇ Es kann auch s<strong>in</strong>nvoll se<strong>in</strong>, e<strong>in</strong> Interface leer, d.h. ohne jegliche Komponenten, zu def<strong>in</strong>ieren.<br />
◇ E<strong>in</strong> derartige Interface dient dazu, anzuzeigen, dass e<strong>in</strong>e implementierende Klasse über e<strong>in</strong>e bestimmte Eigenschaft<br />
verfügt. Es markiert die Klasse h<strong>in</strong>sichtlich des Besitzes dieser Eigenschaft Marker Interface<br />
◇ In der <strong>Java</strong>-Standardbibliothek s<strong>in</strong>d mehrere derartige Marker Interfaces enthalten.<br />
Beispiele :<br />
public <strong>in</strong>terface GraphObj<br />
{ void show();<br />
void hide();<br />
// ...<br />
}<br />
public class FPunkt implements GraphObj<br />
{ // ...<br />
public FPunkt(<strong>in</strong>t x, <strong>in</strong>t y, Color f) { /* ... */ }<br />
public void show() { /* ... */ }<br />
public void hide() { /* ... */ }<br />
// ...<br />
public void drawPo<strong>in</strong>t() { /* ... */ }<br />
}<br />
// ...<br />
// ...<br />
GraphObj go = new FPunkt(1,1, Color.GREEN);<br />
go.show();<br />
go.drawPo<strong>in</strong>t(); // unzulässig !<br />
// ...<br />
▻ Cloneable (Package java.lang)<br />
Es legt fest, dass Objekte e<strong>in</strong>er implementierenden Klasse mit der clone()-Methode geclont werden können.<br />
Die clone()-Methode ist selbst nicht Komponente des Interfaces, sondern der Klasse Object.<br />
▻ Serializable (Package java.io)<br />
Es kennzeichnet, dass Objekte e<strong>in</strong>er implementierenden Klasse serialisiert (<strong>in</strong> e<strong>in</strong>en Byte-Stream umgewandelt)<br />
und deserialisiert (aus e<strong>in</strong>em Byte-Stream wiedergewonnen) werden können.<br />
Klassen, die zur Realisierung des Serialisierungs-/Deserialisierungs-Mechanismus e<strong>in</strong>er besonderen Behandlung<br />
bedürfen, müssen die Methoden writeObject() und readObject() implementieren.<br />
Diese Methoden s<strong>in</strong>d aber ke<strong>in</strong>e Komponenten des Interfaces Serializable.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 481 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Überblick<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (1)<br />
◇ In <strong>Java</strong> können (ab JDK 1.1) Klassen und Interfaces auch <strong>in</strong>nerhalb anderer Klassen und Interfaces def<strong>in</strong>iert werden.<br />
e<strong>in</strong>gebettete Typen (nested types).<br />
◇ Die Def<strong>in</strong>ition e<strong>in</strong>gebetteter Typen ist möglich als<br />
▻ Komponente der umgebenden Klasse bzw des umgebenden Interfaces<br />
▻ lokale Klasse <strong>in</strong>nerhalb e<strong>in</strong>es <strong>in</strong> der umgebenden Klasse enthaltenen Codeblocks<br />
(z.B. <strong>in</strong> e<strong>in</strong>er Memberfunktion, Konstruktor oder Initialisierungsblock)<br />
◇ Die Möglichkeit, e<strong>in</strong>gebettete Typen zu def<strong>in</strong>ieren, ist im wesentlichen <strong>in</strong> zweierlei H<strong>in</strong>sicht zweckmässig :<br />
▻ Strukturierung von Klassen und Interfaces <strong>in</strong> Gruppen entsprechend ihres logischen Zusammenhangs<br />
▻ Def<strong>in</strong>ition von mit spezieller Funktionalität ausgestatteten "Hilfs"- oder "Adaptor"-Klassen an genau der Stelle im<br />
Programm, an der sie gebraucht werden.<br />
Dadurch lassen sich logisch zusammenhängende Objekte <strong>in</strong> e<strong>in</strong>facher und effizienter Weise mite<strong>in</strong>ander verb<strong>in</strong>den.<br />
Hiervon wird <strong>in</strong>sbesondere im Event-Model der GUI-Klassen der JFC (<strong>Java</strong> Foundation Classes) und <strong>in</strong> der <strong>Java</strong>-<br />
Beans-Komponenten-Architektur Gebrauch gemacht.<br />
◇ E<strong>in</strong> e<strong>in</strong>gebetteter Typ kann als Bestandteil des umschliessenden Typs aufgefaßt werden.<br />
Das bedeutet, dass die beiden Typen pr<strong>in</strong>zipiell gegenseitigen Zugriff auch zu ihren jeweiligen private- und<br />
protected- Komponenten besitzen (Unterschied zu C++ !).<br />
◇ E<strong>in</strong> e<strong>in</strong>gebetteter Typ kann i.a. wieder e<strong>in</strong>gebettete Typen enthalten<br />
Grundsätzlich ist e<strong>in</strong>e E<strong>in</strong>bettung <strong>in</strong> beliebiger Tiefe möglich.<br />
Allerd<strong>in</strong>gs verm<strong>in</strong>dert jede weitere E<strong>in</strong>bettung die Übersichtlichkeit und Klarheit e<strong>in</strong>er Klassendef<strong>in</strong>ition.<br />
E<strong>in</strong>e E<strong>in</strong>bettung über mehr als zwei Ebenen sollte daher vermieden werden.<br />
In den meisten Fällen ist e<strong>in</strong>e E<strong>in</strong>bettungsebene ausreichend.<br />
◇ Der Compiler erzeugt für jeden e<strong>in</strong>gebetteten Typ e<strong>in</strong>e eigene class-Datei. Deren Haupt-Name (=Typ-Name)<br />
wird aus den Typnamen des umschliessenden und des e<strong>in</strong>gebetteten Typs zusammengesetzt (Trennung durch $)<br />
• Arten e<strong>in</strong>gebetteter Typen<br />
◇ Es existieren vier verschieden Arten e<strong>in</strong>gebetteter Typen.<br />
Sie unterscheiden sich h<strong>in</strong>sichtlich des Orts und der Art ihrer Def<strong>in</strong>ition (Komponente / lokale Klasse, statisch/nicht-<br />
statisch, Typname / namenlos)<br />
◇ E<strong>in</strong>gebettete Top-Level-Klassen und –Interfaces (nested top level classes and <strong>in</strong>terfaces)<br />
Sie werden als static-Komponenten e<strong>in</strong>er Klasse oder e<strong>in</strong>es Interfaces def<strong>in</strong>iert.<br />
E<strong>in</strong>gebettete Interfaces s<strong>in</strong>d immer von dieser Art (sie s<strong>in</strong>d implizit static).<br />
Auch alle <strong>in</strong>nerhalb e<strong>in</strong>es Interfaces def<strong>in</strong>ierte Typen (Klassen und Interfaces) s<strong>in</strong>d immer implizit static (und<br />
public) und damit ebenfalls immer von dieser Art.<br />
◇ Innere Klassen (<strong>in</strong>ner classes, member classes)<br />
Sie werden als Komponenten e<strong>in</strong>er Klasse, die nicht static s<strong>in</strong>d, def<strong>in</strong>iert.<br />
Ihre Def<strong>in</strong>ition als Interface-Komponente ist nicht möglich.<br />
Auch gibt es ke<strong>in</strong>e <strong>in</strong>neren Interfaces.<br />
E<strong>in</strong> Objekt e<strong>in</strong>er <strong>in</strong>neren Klasse ist immer mit e<strong>in</strong>em Objekt der umfassenden Klasse assoziiert.<br />
◇ Lokale Klassen (local classes, local <strong>in</strong>ner classes)<br />
Sie werden <strong>in</strong>nerhalb e<strong>in</strong>es Code-Blocks def<strong>in</strong>iert und s<strong>in</strong>d nur <strong>in</strong>nerhalb dieses Blockes verwendbar.<br />
Lokale Interfaces s<strong>in</strong>d nicht möglich.<br />
◇ Anonyme Klassen (anonymous classes)<br />
Hierbei handelt es sich ebenfalls um Klassen, die <strong>in</strong>nerhalb e<strong>in</strong>es Code-Blocks def<strong>in</strong>iert werden (es s<strong>in</strong>d also auch<br />
lokale Klassen). Im Unterschied zu "normalen" lokalen Klassen werden sie aber ohne Namen <strong>in</strong>nerhalb e<strong>in</strong>es new-<br />
Ausdrucks def<strong>in</strong>iert.<br />
Anonyme Interfaces s<strong>in</strong>d ebenfalls nicht möglich.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 482 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• E<strong>in</strong>gebettete Top-Level-Klassen und –Interfaces<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (2)<br />
◇ Normalerweise werden Klassen und Interfaces auf der globalen Ebene <strong>in</strong>nerhalb e<strong>in</strong>er jeweils eigenen Quelldatei<br />
– gegebenenfalls als Mitglied e<strong>in</strong>es Packages – def<strong>in</strong>iert.<br />
Derartige Klassen / Interfaces werden als Top-Level-Klassen / -Interfaces bezeichnet.<br />
◇ E<strong>in</strong>gebettete Top-Level-Klassen / -Interfaces s<strong>in</strong>d Typen, die <strong>in</strong>nerhalb e<strong>in</strong>er umschliessenden Klasse / Interface<br />
als static-Komponente def<strong>in</strong>iert s<strong>in</strong>d.<br />
Dabei s<strong>in</strong>d alle <strong>in</strong>nerhalb e<strong>in</strong>es Interfaces def<strong>in</strong>ierte Klassen oder Interfaces implizit static (und public).<br />
Ebenfalls s<strong>in</strong>d alle <strong>in</strong>nerhalb e<strong>in</strong>er Klasse def<strong>in</strong>ierten Interfaces implizit static.<br />
Die explizite Angabe des Modifiers static ist <strong>in</strong> diesen Fällen also überflüssig, aber zulässig.<br />
◇ Diese Typen verhalten sich wie "normale" – nicht e<strong>in</strong>gebettete – Top-Level-Typen, mit dem Unterschied, dass ihr<br />
Name und ihre Zugreifbarkeit durch den umschliessenden Typ festgelegt wird.<br />
Sie lassen sich ausserhalb ihrer umschliessenden Klasse / Interface pr<strong>in</strong>zipiell wie jeder andere Top-Level-Typ<br />
ver wenden, mit den E<strong>in</strong>schränkungen, dass<br />
▻ ihr Name mit dem Namen des umschliessenden Typs qualifiziert werden muß ( vollqualifizierter Name)<br />
▻ und zu ihnen nur zugegriffen werden kann, wenn auch der umschliessende Typ zugreifbar ist.<br />
Unter Berücksichtigung dieser E<strong>in</strong>schränkungen und der jeweiligen Zugriffsberechtigung kann e<strong>in</strong> e<strong>in</strong>gebetteter Top-<br />
Level-Typ von e<strong>in</strong>er anderen Klasse / Interface abgeleitet se<strong>in</strong> bzw selbst Basisklasse / Basis<strong>in</strong>terface für weitere Ab-<br />
leitungen se<strong>in</strong>. E<strong>in</strong>e e<strong>in</strong>gebettete Top-Level-Klasse kann beliebige Interfaces implementieren und kann <strong>in</strong>stanziiert<br />
werden. Sie kann f<strong>in</strong>al oder abstract deklariert werden.<br />
◇ Bezüglich der Zugreifbarkeit e<strong>in</strong>gebetteter Typen gelten die gleichen Regeln wie für die Daten- bzw Funktionskom-<br />
ponenten e<strong>in</strong>er Klasse /e<strong>in</strong>es Interfaces. Das bedeutet, dass <strong>in</strong>nerhalb e<strong>in</strong>er Klasse def<strong>in</strong>ierte e<strong>in</strong>gebettete Typen die<br />
Zugriffsberechtigungen private, package, protected oder public besitzen können.<br />
Für <strong>in</strong>nerhalb e<strong>in</strong>es Interfaces def<strong>in</strong>ierte Typen ist dagegen die Zugriffsberechtigung public implizit festgelegt.<br />
◇ Da e<strong>in</strong>gebettete Top-Level-Typen Komponenten ihrer jeweiligen umschliessenden Klasse s<strong>in</strong>d, besteht zwischen<br />
ihnen und dieser Klasse e<strong>in</strong> besonders privilegiertes Verhältnis bezüglich der gegenseitigen Zugriffsberechtigung :<br />
Die e<strong>in</strong>gebetteten Typen dürfen zu allen anderen Komponenten ihrer umschliessenden Klasse – <strong>in</strong>sbesondere auch<br />
zu den private deklarierten – zugreifen.<br />
Umgekehrt gilt, dass auch die umschliessende Klasse die Zugriffsberechtigung zu allen Komponenten der e<strong>in</strong>gebet-<br />
teten Klasse besitzt.<br />
Zu den nicht-statischen Komponenten kann natürlich nur über e<strong>in</strong> Objekt der jeweiligen Klasse zugegriffen werden.<br />
Das privilegierte Zugriffsberechtigungsverhältnis wird nicht an abgeleitete Klassen vererbt.<br />
◇ E<strong>in</strong>gebettete Top-Level-Klassen / -Interfaces dienen zur Strukturierung logisch zusammenhängender Typen.<br />
◇ Beispiel :<br />
public class MyL<strong>in</strong>kedList<br />
{<br />
public static <strong>in</strong>terface L<strong>in</strong>kable // e<strong>in</strong>gebettetes Interface<br />
{ public L<strong>in</strong>kable getNext();<br />
public void setNext(L<strong>in</strong>kable neu);<br />
}<br />
}<br />
private L<strong>in</strong>kable head;<br />
public void <strong>in</strong>sert(L<strong>in</strong>kable neu) { /* ... */ }<br />
public void remove(L<strong>in</strong>kable elem) { /* ... */ }<br />
public class L<strong>in</strong>kableInteger implements MyL<strong>in</strong>kedList.L<strong>in</strong>kable<br />
{ private <strong>in</strong>t val;<br />
private MyL<strong>in</strong>kedList.L<strong>in</strong>kable next;<br />
public L<strong>in</strong>kableInteger(<strong>in</strong>t i) { val = i; next = null; }<br />
public MyL<strong>in</strong>kedList.L<strong>in</strong>kable getNext() { return next; }<br />
public void setNext(MyL<strong>in</strong>kedList.L<strong>in</strong>kable neu) { next = neu; }<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 483 – 01 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Innere Klassen<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (3 - 1)<br />
◇ Dies s<strong>in</strong>d Klassen, die <strong>in</strong>nerhalb e<strong>in</strong>er anderen Klasse als nicht-statische Komponenten def<strong>in</strong>iert werden.<br />
◇ E<strong>in</strong>e <strong>in</strong>nere Klasse kann pr<strong>in</strong>zipiell analog zu e<strong>in</strong>er Top-Level-Klasse def<strong>in</strong>iert werden.<br />
Allerd<strong>in</strong>gs darf sie ke<strong>in</strong>e static-Komponenten besitzen<br />
Ausnahme : sie darf Konstante (static f<strong>in</strong>al, <strong>in</strong>itialisiert mit e<strong>in</strong>em konstanten Ausdruck) enthalten.<br />
◇ E<strong>in</strong>e <strong>in</strong>nere Klasse kann von e<strong>in</strong>er beliebigen anderen Klasse abgeleitet se<strong>in</strong> und beliebige Interfaces implementieren.<br />
Sie kann Basisklasse für beliebige andere Klassen se<strong>in</strong>, sofern sie für diese zugreifbar ist.<br />
Sie kann f<strong>in</strong>al oder abstract deklariert werden.<br />
◇ E<strong>in</strong> Objekt e<strong>in</strong>er <strong>in</strong>neren Klasse muß immer mit genau e<strong>in</strong>em Objekt der umschliessenden Klasse assoziiert se<strong>in</strong><br />
(Die Umkehrung gilt nicht).<br />
Der Compiler ergänzt die Parameterliste jedes Konstruktors e<strong>in</strong>er <strong>in</strong>neren Klasse um e<strong>in</strong> verborgenes Argument,<br />
dem implizit e<strong>in</strong>e Referenz auf das assoziierte Objekt der umschliessenden Klasse übergeben wird.<br />
Diese Referenz wird <strong>in</strong> e<strong>in</strong>er zusätzlichen – ebenfalls vom Compiler automatisch e<strong>in</strong>gefügten – f<strong>in</strong>al-Daten-<br />
komponente abgelegt.<br />
Über diese Datenkomponente kann das Objekt der <strong>in</strong>neren Klasse implizit zu allen – auch den private-Kompo-<br />
nenten des assoziierten Objekts der umschliessenden Klasse zugreifen.<br />
◇ Beispiel : Klasse BankKonto mit <strong>in</strong>nerer Klasse Buchung (s. nächste Seite)<br />
◇ Die implizit abgelegte Referenz auf das Objekt der umschliessenden Klasse kann auch explizit angegeben werden.<br />
Syntax :<br />
Das Objekt der <strong>in</strong>neren Klasse kann damit auch über diese explizite Referenz zu den Komponenten des Objekts der<br />
umschliessenden Klasse zugreifen.<br />
Beispiel : Zugriff zur Datenkomponente nummer des assoziierten Objekts der umschliessenden Klasse BankKonto<br />
aus e<strong>in</strong>em Objekt der <strong>in</strong>neren Klasse Buchung :<br />
BankKonto.this.nummer (s. Beispiel nächste Seite)<br />
E<strong>in</strong>e explizite Referenz ist <strong>in</strong>sbesondere s<strong>in</strong>nvoll (und dann auch notwendig), wenn<br />
▻ Komponenten der umschliessenden Klasse durch gleichnamige Komponenten der <strong>in</strong>neren Klasse überdeckt werden.<br />
(E<strong>in</strong>e Methode e<strong>in</strong>er <strong>in</strong>neren Klasse überdeckt alle überladenen Formen e<strong>in</strong>er gleichnamigen Methode der um-<br />
schliessenden Klasse)<br />
▻ zu Komponenten e<strong>in</strong>er umschliessenden Klasse höherer Ebene zugegriffen werden soll.<br />
◇ Aus der umschliessenden Klasse kann ebenfalls zu den privaten Komponenten der <strong>in</strong>neren Klasse zugegriffen werden<br />
– allerd<strong>in</strong>gs nur über e<strong>in</strong>e explizite Referenz auf e<strong>in</strong> Objekt der <strong>in</strong>neren Klasse.<br />
• Instanziierung <strong>in</strong>nerer Klassen<br />
◇ Normalerweise werden <strong>in</strong>nere Klassen <strong>in</strong> Instanz-Memberfunktionen der umschliessenden Klasse <strong>in</strong>stanziiert.<br />
In e<strong>in</strong>em derartigen Fall ist die Referenz auf das Objekt der umschliessenden Klasse durch this gegeben.<br />
◇ Soll e<strong>in</strong> neu zu erzeugendes Objekt der <strong>in</strong>neren Klasse dagegen mit e<strong>in</strong>em anderen Objekt der umschliessenden<br />
Klasse assoziiert werden, so muß dieses bei der Objekterzeugung explizit angegeben werden<br />
Hierfür existiert e<strong>in</strong>e Erweiterung der Syntax für den new-Ausdruck : qualified class <strong>in</strong>stance creation expression<br />
Syntax :<br />
Name_der_umschliessenden_Klasse . this<br />
Referenz_auf_umschliessendes_Objekt . new Konstruktoraufruf<br />
Beispiel : Klasse Buchung sei <strong>in</strong>nere Klasse von BankKonto<br />
E<strong>in</strong>e Methode von BankKonto (z.B. ma<strong>in</strong>()) könnte folgenden Code enthalten :<br />
BankKonto de<strong>in</strong>Kto = new BankKonto(2481);<br />
Buchung buchg = de<strong>in</strong>Kto.new Buchung(null, 0.0f);
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 483 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Demonstrationsbeispiel zu <strong>in</strong>neren Klassen<br />
// BankKonto.java<br />
import java.io.*;<br />
public class BankKonto<br />
{<br />
private long nummer;<br />
private float ktoStand;<br />
private Buchung letzteBuch;<br />
}<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (3 - 2)<br />
// ---------------------------- <strong>in</strong>nere Klasse -------------------------------<br />
public class Buchung<br />
{<br />
private Str<strong>in</strong>g art;<br />
private float betrag;<br />
}<br />
Buchung(Str<strong>in</strong>g act, float betr)<br />
{ art = act;<br />
betrag = betr;<br />
}<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g()<br />
{ return nummer + " : " + art + ' ' + betrag; // BankKonto.this.nummer<br />
}<br />
// --------------------------------------------------------------------------<br />
public BankKonto(long num)<br />
{ nummer = num;<br />
ktoStand = 0.0f;<br />
letzteBuch = null;<br />
}<br />
public void e<strong>in</strong>zahlen(float betr)<br />
{ ktoStand += betr;<br />
letzteBuch = new Buchung("E<strong>in</strong>zahlung", betr);<br />
}<br />
public boolean abbuchen(float betr)<br />
{ boolean bRet = true;<br />
if (ktoStand >= betr)<br />
{ ktoStand -= betr;<br />
letzteBuch = new Buchung("Abbuchung", betr);<br />
}<br />
else<br />
{ letzteBuch = new Buchung("Versuch der Kontoueberziehung", betr);<br />
bRet = false;<br />
}<br />
return bRet;<br />
}<br />
public void ueberweisen(BankKonto empf, float betr)<br />
{ if (abbuchen(betr))<br />
{ empf.e<strong>in</strong>zahlen(betr);<br />
letzteBuch = new Buchung("Ueberweisung ab ", betr);<br />
empf.letzteBuch = empf.new Buchung("Ueberweisung auf ",betr);<br />
}<br />
}<br />
// ...
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 483 – 03 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Ableitung <strong>in</strong>nerer Klassen<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (3 - 3)<br />
◇ Analog zu Top-Level-Klassen können auch <strong>in</strong>nere Klassen abgeleitet werden.<br />
Die abgeleitete Klasse kann sowohl e<strong>in</strong>e Top-Level-Klasse als auch e<strong>in</strong>e <strong>in</strong>nere Klasse se<strong>in</strong>.<br />
◇ Die e<strong>in</strong>zige besondere Erfordernis ist, dass auch e<strong>in</strong> Objekt der abgeleiteten Klasse mit e<strong>in</strong>em Objekt der ursprüng-<br />
lichen umfassenden Klasse (d.h. der umfassenden Klasse se<strong>in</strong>er Basisklasse) oder e<strong>in</strong>er davon abgeleiteten Klasse<br />
assoziiert se<strong>in</strong> muß (Basisklassen-Teilobjekt enthält verborgene Komponente auf assoziiertes Objekt !).<br />
I.a. ist das ke<strong>in</strong> Problem, da die abgeleitete Klasse meist als <strong>in</strong>nere Klasse e<strong>in</strong>er Klasse, die von der ursprünglichen<br />
umschliessenden Klasse abgeleitet ist, def<strong>in</strong>iert wird.<br />
◇ Beispiel :<br />
class Outer<br />
{<br />
class Inner<br />
{<br />
// ...<br />
}<br />
// ...<br />
}<br />
class ExtOuter extends Outer<br />
{<br />
class ExtInner extends Inner<br />
{<br />
// ...<br />
}<br />
}<br />
Da hier sowohl Inner als auch die hiervon abgeleitete Klasse ExtInner <strong>in</strong>nere Klassen s<strong>in</strong>d, wird bei der Er-<br />
zeugung e<strong>in</strong>es Objekts der Klasse ExtInner (z.B. zur Initialisierung von ref) dieses zweimal an e<strong>in</strong> Objekt der<br />
Klasse ExtOuter gebunden :<br />
- Das ExtOuter-Objekt wird dem Konstruktor von ExtInner implizit übergeben.<br />
Mit ihm wird die für das Objekt der Klasse ExtInner angelegte verborgene Komponente <strong>in</strong>itialisiert<br />
- Zum anderen wird dieses Objekt auch dem – hier implizit aufgerufenen – Konstruktor der Basisklasse Inner<br />
(super()) implizit übergeben<br />
Dieser setzt die für das Teilobjekt der Klasse Inner angelegte und vom ExtInner-Objekt geerbte verbor-<br />
gene Komponente damit auf dasselbe ExtOuter-Objekt.<br />
◇ Wenn die von der <strong>in</strong>neren Klasse abgeleitete Klasse selbst ke<strong>in</strong>e <strong>in</strong>nere Klasse ist, dann muß dem Konstruktor ihrer<br />
Basisklasse e<strong>in</strong>e explizite Referenz auf e<strong>in</strong> assoziierendes Objekt deren umschliessender Klasse übergeben werden.<br />
Hierfür existiert wiederum e<strong>in</strong>e spezielle Syntax :<br />
Syntax :<br />
Beispiel :<br />
// ...<br />
Inner ref = new ExtInner();<br />
// ...<br />
Referenz_auf_umschliessendes_Objekt . super ( Parameterliste )<br />
class ExtNotInner extends Outer.Inner<br />
{<br />
ExtNotInner(Outer ref)<br />
{<br />
ref.super();<br />
}<br />
// ...<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 484 – 01 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Lokale Klassen<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (4- 1)<br />
◇ Dies s<strong>in</strong>d Klassen, die <strong>in</strong>nerhalb e<strong>in</strong>es Codeblocks (Methode, Konstruktor oder Initialisierungsblock) def<strong>in</strong>iert s<strong>in</strong>d.<br />
◇ Sie können von beliebigen anderen Klassen abgeleitet se<strong>in</strong> und beliebige Interfaces implementieren.<br />
◇ Es handelt sich bei Ihnen nicht um Klassenkomponenten.<br />
◇ Sie s<strong>in</strong>d lokal zu dem Block, <strong>in</strong> dem sie def<strong>in</strong>iert s<strong>in</strong>d, analog zu lokalen Variablen.<br />
Ausserhalb dieses Blocks ist ihre jeweilige Def<strong>in</strong>ition nicht zugänglich und damit auch nicht verwendbar.<br />
◇ Instanzen von Ihnen können aber pr<strong>in</strong>zipiell wie Objekte anderer Klassen verwendet werden.<br />
Sie existieren nach ihrer Erzeugung, bis sie nicht mehr referiert werden.<br />
Referenzen auf sie können als Funktionswerte zurückgegeben und als Parameter an Funktionen übergeben werden.<br />
Da ihr Klassenname ausserhalb des def<strong>in</strong>ierenden Codeblocks nicht zugänglich ist, werden derartige Objekte i.a. dann<br />
als Instanzen e<strong>in</strong>es von ihnen implementierten Interfaces oder e<strong>in</strong>er Basisklasse referiert<br />
◇ Wie <strong>in</strong>nere Klassen dürfen sie ke<strong>in</strong>e static-Komponenten besitzen, ausgenommen Daten-Komponenten, die als<br />
static und f<strong>in</strong>al deklariert s<strong>in</strong>d (Konstante)<br />
◇ Lokale Klassen können nicht mit e<strong>in</strong>em Zugriffs-Spezifizierer (public, protected, private) deklariert werden<br />
• Zugriffsmöglichkeiten von lokalen Klassen<br />
◇ Lokale Klassen können zu allen lokalen Variablen und Funktionsparametern, die <strong>in</strong> ihrem Sichtbarkeitsbereich<br />
(scope) liegen und die als f<strong>in</strong>al vere<strong>in</strong>bart s<strong>in</strong>d, zugreifen.<br />
Derartige Variablen / Funktionsparameter werden den Konstruktoren e<strong>in</strong>er lokalen Klasse implizit über vom Compiler<br />
h<strong>in</strong>zugefügte verborgene Parameter übergeben. Sie dienen zur Initialisierung von entsprechenden – ebenfalls vom<br />
Compiler h<strong>in</strong>zugefügten – privaten Datenkomponenten der lokalen Klasse.<br />
Genaugenommen arbeiten die Objekte e<strong>in</strong>er lokalen Klasse also nicht mit den orig<strong>in</strong>alen lokalen Variablen und Funk-<br />
tionsparametern sondern mit Kopien derselben.<br />
Allerd<strong>in</strong>gs werden <strong>in</strong> den folgenden Fällen ke<strong>in</strong>e privaten Datenkomponenten für lokale Variable / Funktionspara-<br />
meter angelegt :<br />
▻ lokale Variable / Funktionsparameter, die <strong>in</strong> der lokalen Klasse nicht verwendet werden<br />
▻ lokale f<strong>in</strong>al-Variable e<strong>in</strong>es e<strong>in</strong>fachen Datentyps, die gleich bei ihrer Def<strong>in</strong>ition <strong>in</strong>itialisiert werden (= lokale<br />
Konstante). Ihr jeweiliger Wert wird direkt als Konstante e<strong>in</strong>gesetzt<br />
◇ Objekte e<strong>in</strong>er lokalen Klasse, die <strong>in</strong>nerhalb e<strong>in</strong>er nicht-statischen Memberfunktion oder <strong>in</strong> e<strong>in</strong>em Objekt-Initialisie-<br />
rungsblock def<strong>in</strong>iert ist, müssen – wie Objekte <strong>in</strong>nerer Klassen – immer an e<strong>in</strong> Objekt der umschliessenden Klasse<br />
gebunden se<strong>in</strong>. Damit haben sie direkten Zugriff zu allen Komponenten dieses Objekts.<br />
Die Implementierung dieser B<strong>in</strong>dung ist analog zu <strong>in</strong>neren Klassen realisiert (Übergabe e<strong>in</strong>er Referenz auf das<br />
assoziierte Objekt der umschliessenden Klasse über e<strong>in</strong>en verborgenen Konstruktorparameter und Speicherung derselben<br />
<strong>in</strong> e<strong>in</strong>er h<strong>in</strong>zugefügten privaten Datenkomponente).<br />
Auch die explizite Referierung des assoziierten Objekts ist – mit derselben Syntax – wie bei <strong>in</strong>neren Klassen möglich<br />
(Erweiterte Form der this-Referenz).<br />
◇ Objekte e<strong>in</strong>er lokale Klasse, die <strong>in</strong> e<strong>in</strong>er statischen Memberfunktion oder <strong>in</strong> e<strong>in</strong>em Klassen-Initialisierungsblock<br />
def<strong>in</strong>iert ist, besitzen ke<strong>in</strong> assoziiertes Objekt der umschliessenden Klasse.<br />
Sie können direkt nur zu statischen Komponenten der umschliessenden Klasse zugreifen.<br />
Zum Zugriff zu den nicht-statischen Klassenkomponenten benötigten sie e<strong>in</strong>e explizite Objekt-Referenz.<br />
• Typische Anwendung von lokalen Klassen<br />
◇ Event-Listener-Klassen für GUI-Komponenten der JFC werden häufig als lokale Klassen def<strong>in</strong>iert (Adapter-Klassen).<br />
Allerd<strong>in</strong>gs ist für diese auch die Def<strong>in</strong>ition als <strong>in</strong>nere Klassen oder als anonyme Klassen üblich.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 484 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Demonstrationsprogramm zu lokalen Klassen<br />
// ArrayWalker.java<br />
Programmausgabe :<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (4- 2)<br />
// Implementierung e<strong>in</strong>er Klasse, die e<strong>in</strong>e – hier statische – Memberfunktion<br />
// makeEnum() zur Erzeugung e<strong>in</strong>es Enumeration-Objekts für Arrays bereitstellt.<br />
// Die Klasse ArrayEnum des erzeugten Enumeration-Objekts ist als lokale Klasse<br />
// der Erzeugungs-Funktion implementiert.<br />
// Sie implementiert das Bibliotheks-Interface Enumeration<br />
import java.util.Enumeration;<br />
public class ArrayWalker<br />
{<br />
public static Enumeration makeEnum(f<strong>in</strong>al Object[] objs)<br />
{<br />
f<strong>in</strong>al <strong>in</strong>t startpos;<br />
startpos = 0; // nur zu Demo-Zwecken so umstaendlich<br />
}<br />
}<br />
// ------------------------ lokale Klasse -------------------------------<br />
class ArrayEnum implements Enumeration<br />
{<br />
private <strong>in</strong>t pos = startpos; // nur zu Demo-Zwecken so umstaendlich<br />
}<br />
public boolean hasMoreElements()<br />
{<br />
return pos < objs.length;<br />
}<br />
public Object nextElement()<br />
{<br />
return objs[pos++];<br />
}<br />
// ----------------------------------------------------------------------<br />
return new ArrayEnum();<br />
// Demonstration der Anwendung<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ f<strong>in</strong>al <strong>in</strong>t anz = 10;<br />
Integer[] ia = new Integer[anz];<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 485 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Anonyme Klassen<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (5- 1)<br />
◇ Anonyme Klassen s<strong>in</strong>d im wesentlichen lokale Klassen ohne Namen.<br />
Sie verfügen über alle Eigenschaften von lokalen Klassen, die nicht vom Besitz e<strong>in</strong>es Klassennamens abhängen.<br />
◇ Sie müssen immer von e<strong>in</strong>er anderen Klasse abgeleitet se<strong>in</strong> oder genau e<strong>in</strong> Interface implementieren.<br />
◇ Sie werden gleichzeitig mit ihrer Instanziierung <strong>in</strong> e<strong>in</strong>em new-Ausdruck def<strong>in</strong>iert.<br />
Von ihnen lässt sich also immer nur e<strong>in</strong> Objekt erzeugen.<br />
◇ Zur Realisierung anonymer Klassen existiert e<strong>in</strong>e entsprechende Erweiterung der Syntax für den new-Ausdruck :<br />
Der new-Ausdruck wird nicht – wie bei Klassen mit Namen – mit e<strong>in</strong>em Semikolon abgeschlossen, sondern durch<br />
e<strong>in</strong>en Klassen-Rumpf ergänzt.<br />
Der Klassen-Rumpf bildet die Def<strong>in</strong>ition der anonymen Klasse. Er enthält die Def<strong>in</strong>ition ihrer Komponenten und<br />
Initialisierungsblöcke.<br />
Der im new-Ausdruck anzugebende Klassen-/bzw Interface-Name<br />
▻ ist der Name der Klasse, von dem die anonyme Klasse abgeleitet ist<br />
▻ bzw der Name des Interfaces, das sie implementiert.<br />
E<strong>in</strong>e nicht-leere Parameterliste kann nur im Fall der Ableitung von e<strong>in</strong>er anderen Klasse angegeben werden.<br />
Die Parameter werden dem implizit aufgerufenen Konstruktor der Basisklasse übergeben.<br />
Im Fall der Implementierung e<strong>in</strong>es Interfaces muss die Parameterliste leer se<strong>in</strong>.<br />
Die explizite Angabe e<strong>in</strong>er extends- oder implements-Klausel ist nicht möglich.<br />
◇ Beispiel :<br />
new Klassen-/Interface-Name ( Parameterliste ) {<br />
// DirLister.java<br />
import java.io.*;<br />
Klassen-Rumpf }<br />
public class DirLister<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ File dir = new File(args[0]); // Achtung : hier ke<strong>in</strong>e Überprüfung<br />
f<strong>in</strong>al Str<strong>in</strong>g endung = args[1]; // auf richtiges Aufrufformat<br />
}<br />
}<br />
Str<strong>in</strong>g[] flist = dir.list(new FilenameFilter() {<br />
public boolean accept(File d, Str<strong>in</strong>g s)<br />
{ return s.endsWith(endung);<br />
}<br />
});<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 485 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Verwendung anonymer Klassen<br />
E<strong>in</strong>gebettete Klassen und Interfaces <strong>in</strong> <strong>Java</strong> (5- 2)<br />
◇ Anonyme Klassen werden häufig konkurierend zu – benannten – lokalen Klassen e<strong>in</strong>gesetzt.<br />
Sie dienen im wesentlichen auch zur Def<strong>in</strong>ition von Adapter-Klassen, wie z.B. Event-Listener-Klassen für<br />
GUI-Komponenten.<br />
◇ Die Verwendung e<strong>in</strong>er anonymen Klasse statt e<strong>in</strong>er lokalen Klasse kann <strong>in</strong>sbesondere s<strong>in</strong>nvoll se<strong>in</strong>, wenn<br />
▻ die Def<strong>in</strong>ition der Klasse sehr kurz ist (nur wenige Quellcode-Zeilen umfasst),<br />
▻ nur e<strong>in</strong> Objekt der Klasse benötigt wird<br />
▻ die Klasse direkt dort, wo sie def<strong>in</strong>iert wird, auch verwendet werden soll,<br />
▻ e<strong>in</strong> Klassenname nicht explizit benötigt wird und die Vergabe e<strong>in</strong>es Klassennamens den Code nicht verständ-<br />
licher macht.<br />
• class-Date<strong>in</strong>ame e<strong>in</strong>er anonymen Klasse<br />
◇ Der Haupt-Name der vom Compiler erzeugten class-Datei für e<strong>in</strong>e anonyme Klasse besteht aus dem Namen<br />
der umschliessenden Klasse gefolgt vom Zeichen $ und e<strong>in</strong>er laufenden Nummer.<br />
• Demonstrationsprogramm zu anonymen Klassen<br />
Realisierung der Klasse ArrayEnum (s. Demonstrationsprogramm zu lokalen Klassen) als anonyme Klasse<br />
// ArrayWalker2.java<br />
import java.util.Enumeration;<br />
public class ArrayWalker2<br />
{<br />
public static Enumeration makeEnum(f<strong>in</strong>al Object[] objs)<br />
{<br />
f<strong>in</strong>al <strong>in</strong>t startpos;<br />
startpos=0;<br />
}<br />
}<br />
return new Enumeration() { // Def<strong>in</strong>ition der anonymen Klasse<br />
private <strong>in</strong>t pos = startpos;<br />
public boolean hasMoreElements()<br />
{<br />
return pos < objs.length;<br />
}<br />
public Object nextElement()<br />
{<br />
return objs[pos++];<br />
}<br />
};<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ f<strong>in</strong>al <strong>in</strong>t anz = 10;<br />
Integer[] ia = new Integer[anz];<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 491 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Generische Klassen, Interfaces und Funktionen (Generics) <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Mit dem JDK 5.0 wurde <strong>in</strong> <strong>Java</strong> die Möglichkeit der generischen Programmierung mittels Typ-Parameterieisrung<br />
e<strong>in</strong>geführt (Konzept der Generics)<br />
◇ Typ-Parameterisierung lässt sich anwenden bei :<br />
▻ Klassen generische Klassen<br />
▻ Interfaces generische Interfaces<br />
▻ Memberfunktionen generische Methoden<br />
▻ Konstruktoren generische Konstruktoren<br />
◇ Typ-Parameterisierung bedeutet, dass bei der Def<strong>in</strong>ition e<strong>in</strong>er Klasse (bzw Interface, bzw Methode bzw Konstruktor)<br />
durch e<strong>in</strong>e Typ-Param-Deklaration formale Typ-Parameter (Typ-Variablen) def<strong>in</strong>iert werden.<br />
Dabei kann e<strong>in</strong>e Typ-Variable durch e<strong>in</strong>e Typ-Begrenzung (Type Bound) ergänzt werden<br />
Zur Anwendung der Klasse (bzw Interface, Methode, Konstruktor) müssen dieTyp-Variablen durch konkrete aktuelle<br />
Typ-Parameter (Typ-Argumente) ersetzt werden.<br />
Dadurch lässt sich der gleiche – nur e<strong>in</strong>mal vorhandene – Code für unterschiedliche Typen verwenden.<br />
• Typ-Param-Deklaration<br />
◇ Sie ist anzugeben bei<br />
▻ der Klassen- und Interface-Def<strong>in</strong>ition : unmittelbar nach dem Klassen- bzw Interface-Namen<br />
▻ der Methoden-Def<strong>in</strong>ition : unmittelbar vor dem Rückgabetyp<br />
▻ der Konstruktor-Def<strong>in</strong>ition : unmittelbar vor dem Konstruktor(==Klassen)-Namen<br />
◇ Syntax der Typ-Param-Deklaration :<br />
Typ-Parameter :<br />
Typ-Begrenzung :<br />
(Type Bound)<br />
extends<br />
◇ Durch Angabe e<strong>in</strong>er Typ-Begrenzung werden die Typen der möglichen aktuellen Typ-Parameter (Typ-Argumente)<br />
e<strong>in</strong>geschränkt.<br />
E<strong>in</strong> Typ-Argument muss zu der jeweiligen Typ-Begrenzung kompatibel se<strong>in</strong>, d.h. gleich dem angegebenen Klassen-<br />
Typ oder von ihm abgeleitet se<strong>in</strong> und/oder die angegebenen Interface-Typen implementieren.<br />
Das Schlüsselwort extends steht hier sowohl für die Ableitung als auch für die Implementierung.<br />
◇ Beispiele : public <strong>in</strong>terface Map { ... }<br />
<<br />
formaler Typ-Name<br />
Typ-Parameter<br />
,<br />
Klassen-Typ<br />
Interface-Typ<br />
public class EnumMap extends ... implements ...<br />
{ ... }<br />
public static <br />
T getMaxElement(Collection coll) { ... }<br />
><br />
Typ-Begrenzung<br />
& Interface-Typ
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 492 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Generische Klassen, Interfaces und Funktionen (Generics) <strong>in</strong> <strong>Java</strong> (2)<br />
• Anmerkungen zu generischen Klassen und Interfaces<br />
◇ Die bei der Def<strong>in</strong>ition e<strong>in</strong>er generischen Klasse bzw Interfaces deklarierten formalen Typ-Parameter (Typ-Variable)<br />
können <strong>in</strong> der gesamten Klassendef<strong>in</strong>ition verwendet werden, e<strong>in</strong>schliesslich der Typ-Param-Deklaration selbst.<br />
(z.B. <strong>in</strong> der eigenen Typ-Begrenzung oder den Typ-Begrenzugen anderer Typ-Variabler)<br />
Innerhalb der Klassendef<strong>in</strong>ition können sie als Typ-Angabe für Datenkomponenten, Parameter- und Rückgabetyp<br />
von Memberfunktionen sowie <strong>in</strong> e<strong>in</strong>gebetteten Typen auftreten.<br />
Ausnahmen :<br />
▻ Typ-Parameter von generischen Klassen dürfen nicht verwendet werden :<br />
- für statische Datenkomponenten (e<strong>in</strong>schliesslich statischer Datenkomponenten e<strong>in</strong>gebetteter Typen)<br />
- <strong>in</strong> statischen Funktionskomponenten (e<strong>in</strong>schliesslich statischer Funktionskomponenten e<strong>in</strong>gebetteter Typen)<br />
- <strong>in</strong> statischen Initialisierungsblöcken (e<strong>in</strong>schliesslich statischer Initialisierungsblöcke e<strong>in</strong>gebetteter Typen)<br />
▻ Typ-Parameter von generischen Interfaces dürfen nicht verwendet werden :<br />
- für Datenkomponenten (s<strong>in</strong>d immer implizit static und f<strong>in</strong>al)<br />
- <strong>in</strong> e<strong>in</strong>gebetteten Typen<br />
◇ Durch Anwendung aktueller Typ-Parameter (Typ-Argumente) wird aus e<strong>in</strong>er generischen Klasse oder Interface e<strong>in</strong><br />
konkreter Typ erzeugt parameterisierter Typ<br />
◇ Alle aus e<strong>in</strong>er generischen Klasse erzeugbaren parameterisierten Typen teilen sich dieselbe Klasse<br />
der folgende Ausdruck liefert true :<br />
new Vector().getClass() == new Vector().getClass();<br />
◇ E<strong>in</strong>e generische Klasse sowie e<strong>in</strong> aus e<strong>in</strong>er generischen Klasse erzeugter parameterisierter Typ kann Basisklasse<br />
für andere generische und nicht-generische Klassen se<strong>in</strong>.<br />
Folgende Klassendef<strong>in</strong>itionen s<strong>in</strong>d somit pr<strong>in</strong>zipiell zulässig :<br />
public class GenVector extends Vector { ... }<br />
public class Menge extends Vector { ... }<br />
public class SpecVector extends Vector { ... }<br />
public class MyIntList extends L<strong>in</strong>kedList { ... }<br />
Analog können generische Interfaces und aus diesen gewonnene parameterisierten Typen von generischen und<br />
nicht-generischen Klassen implementiert werden<br />
◇ E<strong>in</strong>e generische Klasse darf weder direkt noch <strong>in</strong>direkt von Throwable abgeleitet se<strong>in</strong>.<br />
Exception-Klassen können nicht generisch se<strong>in</strong>.<br />
• Raw Types<br />
◇ Generische Klassen und Interfaces können auch ganz ohne Typ-Argumente verwendet werden.<br />
Der dadurch erhaltene Typ wird als Raw Type bezeichnet.<br />
◇ Innerhalb e<strong>in</strong>es Raw Types s<strong>in</strong>d alle Auftritte e<strong>in</strong>er Typ-Variablen (formaler Typ-Parameter) durch den Typ<br />
Object bzw – falls vorhanden – den ersten Typ e<strong>in</strong>er Typ-Begrenzung ersetzt.<br />
Alle eventuell enthaltenen Vorkommen von generischen Klassen/Interfaces sowie parameterisierten Typen werden<br />
durch ihre zugehörigen Raw Types ersetzt.<br />
Der zu dieser Ersetzung führende Mechanismus wird Type Erasure genannt.<br />
public <strong>in</strong>terface Iterator<br />
{ // ...<br />
E next();<br />
}<br />
Beispiel :<br />
mittels Type Erasure<br />
wird hieraus :<br />
public <strong>in</strong>terface Iterator<br />
{ // ...<br />
Object next();<br />
}<br />
◇ Raw Types ermöglichen die Kompatibilität zu nicht-generischem <strong>Java</strong>-Code<br />
Mit ihrer Anwendung geht allerd<strong>in</strong>gs auch die durch die Typ-Parameterisierung erreichte Typ-Sicherheit (Überprüfung<br />
durch den Compiler !) verloren. Der Programmierer ist wieder selbst für richtige Type Casts verantwortlich<br />
Raw Types sollten daher möglichst nur dort statt parameterisierter Typen verwendet werden, wo es aus Gründen der<br />
Kompatibilität zu altem (nicht-generischem ) Code notwendig ist.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 493 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Generische Klassen, Interfaces und Funktionen (Generics) <strong>in</strong> <strong>Java</strong> (3)<br />
• Anmerkungen zu generischen Methoden und Konstruktoren<br />
◇ Die Def<strong>in</strong>ition/Deklaration generischer Methoden und Konstruktoren ist unabhängig von e<strong>in</strong>er generischen Eigen-<br />
schaft ihrer jeweiligen Klasse/Interface.<br />
Generische Methoden/Konstruktoren lassen sich sowohl für generische als auch normale nicht-generische<br />
Klassen/Interfaces vere<strong>in</strong>baren.<br />
◇ Auch statische Methoden können generisch se<strong>in</strong>.<br />
◇ Die bei der Def<strong>in</strong>ition e<strong>in</strong>er generischen Methode bzw Konstruktors deklarierten Typ-Variablen (formale Typ-<br />
Parameter) können <strong>in</strong> der gesamten Funktionsdef<strong>in</strong>ition verwendet werden, e<strong>in</strong>schliesslich der Typ-Param-<br />
Deklaration selbst (z.B. <strong>in</strong> der eigenen Typ-Begrenzung oder den Typ-Begrenzugen anderer Typ-Variabler),<br />
Innerhalb der Funktionsdef<strong>in</strong>ition können sie als Typ-Angabe für lokale Variable, sowie Parameter- und Rück-<br />
gabetyp der Funktion auftreten.<br />
◇ Beispiele :<br />
public class GenericsDemo<br />
{<br />
public static <br />
T getMaxElement(Collection coll)<br />
{<br />
T mv = Collections.max(coll);<br />
return mv;<br />
}<br />
}<br />
public void fromArrayToCollection(T[] ar, Collection coll)<br />
{<br />
for (T elem : ar)<br />
coll.add(elem);<br />
}<br />
// ...<br />
◇ Aufruf generischer Methoden :<br />
▻ Im Normalfall kann e<strong>in</strong>e generische Funktion ohne explizite Angabe von aktuellen Typ-Parametern (Typ-Argu-<br />
mente) aufgerufen werden. Fast immer kann der Compiler die aktuellen Typ-Parameter mittels der sogenannten<br />
Type Inference implizit aus dem Funktionsaufruf und se<strong>in</strong>em Kontext ermitteln.<br />
▻ Falls die aktuellen Typ-Parameter explizit angegeben werden, was natürlich pr<strong>in</strong>zipiell immer möglich ist, müssen<br />
sie <strong>in</strong> spitzen Klammern e<strong>in</strong>geschlossen unmittelbar vor dem Methoden-/Konstruktor-Namen angegeben werden.<br />
Zusätzlich muss das Zielobjekt des Aufrufs (gegebenenfalls für das aktuelle Objekt this) bzw die Klasse (bei<br />
statischen Methoden) angegeben werden.<br />
▻ Beispiele :<br />
public class GenericsDemo<br />
{<br />
// ...<br />
}<br />
void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ ArrayList ali = new ArrayList();<br />
// ...<br />
System.out.pr<strong>in</strong>tln(getMaxElement(ali));<br />
System.out.pr<strong>in</strong>tln(GenericsDemo.getMaxElement(ali));<br />
Double[] da = {2.5, 3.5, 4.5, 0.5, 1.5};<br />
Vector dv = new Vector();<br />
GenericsDemo gendemo = new GenericsDemo();<br />
gendemo./**/fromArrayToCollection(da, dv);<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 494 – 00 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Generische Klassen, Interfaces und Funktionen (Generics) <strong>in</strong> <strong>Java</strong> (4)<br />
• Implementierung von Generics<br />
◇ Generics werden <strong>in</strong> <strong>Java</strong> alle<strong>in</strong> vom Compiler bearbeitet.<br />
Im erzeugten Bytecode (.class-Datei) ist jeglicher Auftritt von Generics entfernt : Er besteht nur aus nicht-gene-<br />
rischem Code.<br />
Zur Laufzeit steht ke<strong>in</strong>erlei Information über gegebenenfalls im Quellcode enthaltene generische Eigenschaften<br />
(den Typ-Parametern) von Klassen/Interfaces/Methoden/Konstruktoren zur Verfügung.<br />
Typ-Variable existieren nicht zur Laufzeit. Die JVM kennt ke<strong>in</strong>e Generics.<br />
◇ Bei der Übersetzung von generischem Quellcode entfernt der Compiler die Generics-Informationen mittels Type<br />
Erasure. Er erzeugt also den Byte-Code für Raw Types und "Raw Functions".<br />
Allerd<strong>in</strong>gs legt er die Generics-Informationen (Informationen über Typ-Parameter !) <strong>in</strong> sogenannten "Signatur-<br />
attributen" ab und bettet diese <strong>in</strong> dem erzeugten Byte-Code e<strong>in</strong>. Signaturattribute s<strong>in</strong>d aber ke<strong>in</strong> Bestandteil des Byte-<br />
Codes und werden von der JVM (sowie älteren Compilern) ignoriert. <strong>Java</strong>-Compiler ab dem JDK 5.0 werten sie jedoch<br />
bei der Verwendung der Klassen/Interfaces/Methoden/Konstruktoren durch anderen Code aus. Dadurch s<strong>in</strong>d sie <strong>in</strong> der<br />
Lage, auf die Verwendung richtiger Typen zu prüfen und die gegebenenfalls benötigten Type Casts zu erzeugen.<br />
◇ Die Tatsache, dass der Compiler für generische Klassen/Interfaces deren jeweiligen Raw Type erzeugt, erklärt auch,<br />
warum für alle erzeugbaren parameterisierten Typen immer nur e<strong>in</strong>e Klasse <strong>in</strong> der JVM existiert.<br />
Analoges gilt für generische Methoden/Konstruktoren. Unabhängig von den bei ihrem Aufruf verwendeten aktuellen<br />
Typ-Parametern ist jeweils nur e<strong>in</strong>e e<strong>in</strong>zige Version des Methoden-/Konstruktor-Codes <strong>in</strong> der JVM enthalten.<br />
• Grenzen <strong>in</strong> der Anwendung von Generics<br />
◇ Die Art der Implementierung von Generics (Reduzierung auf Raw Types und "Raw Functions" durch Type Erasure)<br />
bed<strong>in</strong>gt, dass mit Typ-Variablen nicht <strong>in</strong> jeder H<strong>in</strong>sicht genauso wie mit konkreten Datentypen umgegangen werden<br />
kann.<br />
◇ Typ-Argumente müssen immer Referenztypen se<strong>in</strong>.<br />
Statt e<strong>in</strong>facher Datentypen müssen daher ihre Wrapperklassen als Typ-Argumente e<strong>in</strong>gesetzt werden.<br />
Im übrigen ermöglicht Autobox<strong>in</strong>g, dass e<strong>in</strong>fache Datentypen wie Referenztypen (Wrapper-Klassen) verwendet werden<br />
können.<br />
◇ Typ-Variable dürfen nicht für/<strong>in</strong> statische Klassen- bzw Interface-Komponenten verwendet werden (s. oben)<br />
◇ Der <strong>in</strong>stanceof-Operator darf nicht verwendet werden für<br />
- Typ-Variable<br />
- Parameterisierte Typen<br />
Beispiele : Integer i = new Integer(25);<br />
if (i <strong>in</strong>stanceof T) // unzulässig (T sei Typ-Variable e<strong>in</strong>er generischen Klasse)<br />
// ...<br />
ArrayList ali = new ArrayList();<br />
if (ali <strong>in</strong>stanceof ArrayList
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 500 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel 5<br />
5. Graphische Benutzeroberflächen<br />
5.1. Grundpr<strong>in</strong>zip<br />
5.2. <strong>Java</strong> Foundation Classes – Überblick<br />
5.3. Basisklassen der JFC-Hierarchie<br />
5.4. Erstellung e<strong>in</strong>er GUI-Anwendung<br />
5.5. Bee<strong>in</strong>flussung des Ersche<strong>in</strong>ungsbildes<br />
5.6. Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen<br />
5.7. Ereignisverarbeitung
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 511 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Aufbau graphischer Benutzeroberflächen<br />
Grundpr<strong>in</strong>zip graphischer Benutzeroberflächen<br />
◇ E<strong>in</strong>e graphische Benutzeroberfläche (Graphical User Interface, GUI) ist typischerweise aus hierarchisch strukturier-<br />
ten Komponenten aufgebaut.<br />
◇ Die e<strong>in</strong>zelnen GUI-Komponenten – auch controls oder widgets ( = w<strong>in</strong>dow gadgets) genannt – erfüllen jeweils spezielle<br />
Aufgaben. Die meisten von ihnen ermöglichen es dem Benutzer, durch E<strong>in</strong>gaben mittels Maus, Tastatur oder e<strong>in</strong>em<br />
anderen E<strong>in</strong>gabegerät mit Ihnen und damit mit dem Programm zu <strong>in</strong>teragieren.<br />
◇ Die hierarchische Struktur e<strong>in</strong>er graphischen Benutzeroberfläche ergibt sich dadurch, dass e<strong>in</strong>ige GUI-Komponenten,<br />
Conta<strong>in</strong>er genannt, andere Komponenten enthalten können.<br />
An der "Spitze" jeder graphischen Benutzeroberfläche steht e<strong>in</strong> sogenannter Top-Level-Conta<strong>in</strong>er. Die <strong>in</strong> ihm enthal-<br />
tenen Komponenten können "elementare" Komponenten oder wiederum Conta<strong>in</strong>er se<strong>in</strong>, welche dann weitere Kom-<br />
ponenten enthalten können, usw.<br />
E<strong>in</strong>e an e<strong>in</strong>en Conta<strong>in</strong>er gerichtete Aufgabe (z.B. pa<strong>in</strong>t(), "zeichne Dich") führt dieser für sich – soweit zutreffend – aus<br />
und delegiert dann die weitere Ausführung an alle <strong>in</strong> ihm enthaltenen Komponenten.<br />
E<strong>in</strong>e derartige Struktur führt programmtechnisch zu e<strong>in</strong>er Implementierung des Entwurfsmusters Composite.<br />
◇ Beispiele für elementare GUI-Komponenten :<br />
▪ Beschriftung (Label)<br />
▪ Textfeld (Text Field)<br />
▪ Schaltfläche (Button)<br />
▪ Auswahlfeld (Check Box)<br />
▪ Auswahlliste (List, Combo Box)<br />
▪ Menue (Menu)<br />
◇ Beispiele für GUI-Conta<strong>in</strong>er<br />
▪ Fenster mit Rahmen (Frame)<br />
▪ Dialogbox (Dialog Box)<br />
▪ Menueleiste (Menu Bar)<br />
▪ Werkzeugleiste (Tool Bar)<br />
▪ Gruppierungsfeld (Panel)<br />
◇ Beispiel : Rahmenfenster (Frame) mit Schaltfläche (Button) und Beschriftung (Label)<br />
• Interaktion mit dem Benutzer<br />
◇ Die Interaktion mit dem Benutzer erfolgt ereignisgesteuert.<br />
Jede auf e<strong>in</strong>e GUI-Komponente fallende Benutzere<strong>in</strong>gabe (Mausklick, Mausbewegung, Tastature<strong>in</strong>gabe, Auswahl aus<br />
e<strong>in</strong>em Menu usw) wird als Ereignis bezeichnet.<br />
◇ Für jede Komponente kann festgelegt werden, auf welches Ereignis wie reagiert werden soll.<br />
◇ Beim E<strong>in</strong>tritt e<strong>in</strong>es Ereignisses wird die für die betreffende Komponente registrierte Reaktion ausgeführt.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 521 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Bestandteile der <strong>Java</strong> Foundation Classes (JFC)<br />
<strong>Java</strong> Foundation Classes – Überblick (1)<br />
◇ Mit den JFC stellt <strong>Java</strong> e<strong>in</strong>e breites Spektrum von Bibliotheks-Klassen zur Realisierung graphischer Funktionalität<br />
und zum Aufbau von GUIs zur Verfügung.<br />
◇ Die für die Anwendung <strong>in</strong> GUIs wichtigsten Klassen lassen sich im wesentlichen <strong>in</strong> die folgenden Gruppen e<strong>in</strong>teilen :<br />
▻ Klassen für elementare GUI-Komponenten<br />
▻ Klassen für GUI-Conta<strong>in</strong>er<br />
▻ Klassen zur Gestaltung der GUI-Komponenten (Layout-Manager, Farben und Fonts)<br />
▻ Klassen und Interfaces zur Ereignisverarbeitung (Listener, Adapter und Events)<br />
◇ Die JFC umfassen im wesentlichen zwei – sich teilweise ersetzende und teilweise ergänzende – Frameworks :<br />
▻ Abstract W<strong>in</strong>dows Toolkit (AWT) Package java.awt mit mehreren Unterpaketen<br />
▻ Die Sw<strong>in</strong>g-Klassen Package javax.sw<strong>in</strong>g mit mehreren Unterpaketen<br />
◇ Zusätzlich gehören zu den JFC :<br />
▻ <strong>Java</strong> 2D API (Klassen zur Realisierung fortgeschrittener 2D-Graphik, Bild- und Textbearbeitung sowie Drucken)<br />
▻ Accessibility API (Klassen zur Realisierung von Interfaces für Beh<strong>in</strong>derte)<br />
▻ Klassen zur Unterstützung <strong>in</strong>ternational e<strong>in</strong>setzbarer GUI-Applikationen, die sich leicht an die jeweilige Landes-<br />
sprache und nationalen Konventionen anpassen. Hierzu gehört u.a. das Input Method Framework API.<br />
• Abstract W<strong>in</strong>dows Toolkit (AWT)<br />
◇ Ursprüngliches GUI-Paket <strong>in</strong> <strong>Java</strong>. Seit dem JDK 1.0 enthalten<br />
Im JDK 1.1. wesentlich überarbeitet, <strong>in</strong>sbesondere bezüglich der Ereignis-Bearbeitung<br />
◇ Bildet auch die Grundlage für das spätere Sw<strong>in</strong>g-Paket.<br />
◇ Die Implementierung der AWT-Klassen für die GUI-Komponenten verwendet die durch die Graphik-und W<strong>in</strong>dow-<br />
Funktionalität des jeweiligen Betriebssystems zur Verfügung gestellten Komponenten ("heavyweight" components).<br />
Das bedeutet,<br />
- dass nur solche Funktionalitäten implementiert werden konnten, die auf allen wichtigen Plattformen, die <strong>Java</strong><br />
unterstützten, existierten ("kle<strong>in</strong>ster geme<strong>in</strong>samer Nenner")<br />
- dass das Aussehen und die Bedienbarkeit ("Look and Feel", LaF) e<strong>in</strong>er graphischen Benutzeroberfläche jeweils<br />
systemspezifisch ist. Die e<strong>in</strong>zelnen GUI-Komponenten werden <strong>in</strong> der durch das jeweilige Betriebssystems vorge-<br />
gebenen Art und Weise dargestellt.<br />
• Die Sw<strong>in</strong>g -Klassen<br />
◇ Framework zur Erstellung von GUI-Anwendungen mit erweiterter Funktionalität.<br />
Beim JDK 1.1 als Add-On verfügbar, seit dem JDK 1.2 fester Bestandteil der <strong>Java</strong> 2 Platform.<br />
◇ Die Sw<strong>in</strong>g-Klassen bauen auf dem AWT auf, nutzen vieler se<strong>in</strong>er Grundfunktionalitäten, u.a. das Model und die<br />
Klassen für die Ereignisbearbeitung, sowie die Klassen zur Gestaltung der GUI-Komponenten.<br />
◇ Die Implementierung der Klassen für die GUI-Komponenten – ausser den Top-Level-Conta<strong>in</strong>ern – greift nicht mehr auf<br />
die Komponentendarstellung des Betriebssystems zurück. Sie ist vielmehr – unter Verwendung graphischer Primitiv-<br />
Operationen ("lightweight components") vollkommen <strong>in</strong> <strong>Java</strong> realisiert. Das bedeutet, das das "Look and Feel" e<strong>in</strong>er mit<br />
Sw<strong>in</strong>g-Komponenten realisierten GUI unabhängig vom jeweiligen Betriebssystem und damit für alle Systeme gleich<br />
ist.<br />
◇ Andererseits kann der Programmierer und gegebenenfalls auch der Programmbenutzer das LaF e<strong>in</strong>er GUI-Anwendung<br />
selbst festlegen (Pluggable Look and Feel), wobei zwischen e<strong>in</strong>igen Standard-LaFs ausgewählt werden aber auch e<strong>in</strong><br />
eigenes LaF gestaltet werden kann. Es ist sogar möglich das LaF dynamisch während des Programmlaufs zu verän-<br />
dern. Defaultmäßig ist für alle GUI-Komponenten e<strong>in</strong> <strong>Java</strong> Look and Feel (Name "Metal") e<strong>in</strong>gestellt.<br />
◇ AWT- und Sw<strong>in</strong>g-Klassen für GUI-Komponenten dürfen nicht mite<strong>in</strong>ander gemischt verwendet werden.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 522 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
<strong>Java</strong> Foundation Classes – Überblick (2)<br />
• Hierarchie der JFC-Klassen für GUI-Komponenten (unvollständig)<br />
Conta<strong>in</strong>er<br />
JComponent<br />
JButton<br />
. . .<br />
Frame<br />
JFrame<br />
JPanel<br />
. . .<br />
AbstractButton<br />
JCheckBox<br />
Label<br />
W<strong>in</strong>dow<br />
Box<br />
JToggleButton<br />
JRadioButton<br />
Component<br />
JW<strong>in</strong>dow<br />
Button<br />
JDialog<br />
JScrollPane<br />
Box.Filler<br />
ScrollPane<br />
JMenu<br />
Checkbox<br />
Dialog<br />
FileDialog<br />
JComboBox<br />
JMenuItem<br />
JList<br />
JLabel<br />
. . .<br />
JRadioButtonMenuItem<br />
AWT Sw<strong>in</strong>g<br />
… weitere AWT-<br />
Komponenten<br />
Panel<br />
Applet<br />
JApplet<br />
JTable<br />
JTextArea<br />
JCheckBoxMenuItem<br />
MenuItem<br />
Menu<br />
JPopupMenu<br />
JTextComponent<br />
PopupMenu<br />
JTextField<br />
MenuComponent<br />
JToolBar<br />
JPasswordField<br />
MenuBar<br />
CheckBoxMenuItem<br />
JMenuBar<br />
. . .<br />
… weitere Sw<strong>in</strong>g-<br />
Komponenten<br />
JEditorPane<br />
JTextPane
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 523 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Top-Level-Conta<strong>in</strong>er<br />
• Elementare Komponenten (Auswahl)<br />
• "Innere" Conta<strong>in</strong>er (Auswahl)<br />
<strong>Java</strong> Foundation Classes – Überblick (3)<br />
AWT Sw<strong>in</strong>g<br />
Fenster mit Rahmen und Titelleiste Frame JFrame<br />
Fenster ohne Rahmen und Titelleiste W<strong>in</strong>dow JW<strong>in</strong>dow<br />
Dialog-Box Dialog JDialog<br />
Applet Applet JApplet<br />
AWT Sw<strong>in</strong>g<br />
Beschriftung Label JLabel<br />
Zeichenfläche Canvas<br />
Schaltknopf Button JButton<br />
Umschaltknopf (Schaltknopf mit zwei Zuständen) JToggleButton<br />
Auswahlfeld Checkbox JCheckBox<br />
Gruppe alternativer Auswahlfelder Checkbox JRadioButton<br />
(nur e<strong>in</strong> Feld kann ausgewählt werden) <strong>in</strong> Verb<strong>in</strong>dung mit <strong>in</strong> Verb<strong>in</strong>dung mit<br />
CheckboxGroup ButtonGroup<br />
Auswahlliste List JList<br />
aufklappbare Auswahlliste Choice JComboBox<br />
e<strong>in</strong>zeiliges Textfeld (editierbar) TextField JTextField<br />
mehrzeiliges Textfeld (editierbar) TextArea JTextArea<br />
Bildlaufleiste Scrollbar JScrollBar<br />
Bildlauffläche (horizontale u. vertikale Bildlaufleiste) ScrollPane JScrollPane<br />
Tabelle JTable<br />
Menüe<strong>in</strong>trag MenuItem JMenuItem<br />
AWT Sw<strong>in</strong>g<br />
Gruppierungsfeld Panel JPanel<br />
Gruppierungbox (festliegender Layout-Manager) Box<br />
Menüleiste MenuBar JMenuBar<br />
Menu Menu JMenu<br />
Werkzeugleiste JToolBar
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 524 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong> Foundation Classes – Überblick (4)<br />
• E<strong>in</strong>ige Sw<strong>in</strong>g-Komponenten (<strong>Java</strong> Look and Feel) (Klasse Sw<strong>in</strong>gCompDemo)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 531 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die abstrakte Klasse Component<br />
Basisklassen der JFC-Hierachie (1)<br />
◇ Diese – im Package java.awt enthaltene – Klasse steht an der Spitze der Hierarchie der GUI-Komponenten-<br />
Klassen.<br />
Sie def<strong>in</strong>iert grundlegende Methoden, die <strong>in</strong> fast allen AWT- und Sw<strong>in</strong>g-Komponenten-Klassen zur Verfügung<br />
stehen.<br />
Lediglich die AWT-Klassen für Menü-Komponenten bef<strong>in</strong>den sich <strong>in</strong> e<strong>in</strong>er hiervon unabhängigen Klassen-Hierarchie.<br />
◇ E<strong>in</strong>ige wesentliche Methoden :<br />
(die Methoden zum Registrieren von Listener-Objekten für die Event-Behandlung s<strong>in</strong>d nicht mit aufgeführt )<br />
public void setBackground(Color c) Setzen der H<strong>in</strong>tergrund-Farbe auf c<br />
public void setForeground(Color c) Setzen der Vordergrund-Farbe auf c<br />
public void setFont(Font f) Setzen der <strong>in</strong> der Komponente verwendeten Schriftart<br />
public void setSize(<strong>in</strong>t w, <strong>in</strong>t h) Setzen der Breite (auf w) und Höhe (auf h) der Komponente<br />
(Angabe <strong>in</strong> Pixel)<br />
public void setLocation(<strong>in</strong>t x, <strong>in</strong>t y) Setzen der Position der Komponente<br />
(l<strong>in</strong>ke obere Ecke auf (x,y), Angabe <strong>in</strong> Pixel)<br />
public void setVisible(boolean b) Anzeigen / Verbergen der Komponente<br />
(b==true : Komponente sichtbar, sonst unsichtbar)<br />
public void setEnabled(boolean b) Aktivierung / Deaktivierung der Reaktion der Komponente auf<br />
Benutzere<strong>in</strong>gaben (b==true : Komponente kann auf<br />
Benutzere<strong>in</strong>gaben reagieren (Events erzeugen))<br />
Defaultmässig s<strong>in</strong>d alle Komponenten aktiviert<br />
public Color getBackground() Rückgabe der H<strong>in</strong>tergrund-Farbe<br />
public Color getForeground() Rückgabe der Vordergrund-Farbe<br />
public Font getFont() Rückgabe der verwendeten Schriftart<br />
public <strong>in</strong>t getWidth() Rückgabe der aktuellen Breite der Komponente (<strong>in</strong> Pixel)<br />
public <strong>in</strong>t getHeight() Rückgabe der aktuellen Höhe der Komponente (<strong>in</strong> Pixel)<br />
public boolean isVisable() Rückgabe des Sichtbarkeits-Status der Komponente<br />
true, wenn Komponente sichtbar, false, wenn nicht<br />
public boolean isEnabled() Rückgabe des Aktivierungs-Status der Komponente<br />
true, wenn Komponente aktiviert, false, wenn nicht<br />
public void pa<strong>in</strong>t(Graphics g) Zeichnen der Komponente unter Verwendung des Graphik-<br />
Context-Objekts g.<br />
Wird vom System aufgerufen (Callback), z.B. wenn die Kom-<br />
ponente erstmals sichtbar gemacht wird oder e<strong>in</strong>e Zustands-<br />
(z.B. Größen-) änderung erfolgt ist<br />
public void repa<strong>in</strong>t() Aufforderung an das System, die Komponente neu zu zeichnen<br />
(mittels pa<strong>in</strong>t())<br />
Kann vom Anwender-Code aufgerufen werden, wenn sich der<br />
Zustand des GUI-Objekts geändert hat.<br />
public void validate() Sicherstellung, dass die Komponente e<strong>in</strong> gültiges Layout hat<br />
(Diese Methode ist <strong>in</strong>sbesondere für Conta<strong>in</strong>er vorgesehen)<br />
public void requestFocusInW<strong>in</strong>dow() Anforderung des Focus (wenn Top-Level-Cont. Focus besitzt )
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 532 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Die Klasse Conta<strong>in</strong>er<br />
Basisklassen der JFC-Hierachie (2)<br />
◇ Diese – im Package java.awt def<strong>in</strong>ierte – Klasse ist die Basisklasse aller GUI-Conta<strong>in</strong>er-Klassen.<br />
Auch die Klassen für e<strong>in</strong>fache Sw<strong>in</strong>g-Komponenten s<strong>in</strong>d – <strong>in</strong>direkt – von dieser Klasse abgeleitet.<br />
Sie ist selbst von der Klasse Component abgeleitet.<br />
◇ Sie stellt – über die von Component geerbten und teilweise überschriebenen Methoden h<strong>in</strong>aus – <strong>in</strong>sbesondere<br />
Methoden zur Verfügung, die das Verwalten (z.B. E<strong>in</strong>fügen, Entfernen) von GUI-Komponenten ermöglichen.<br />
◇ Die <strong>in</strong> e<strong>in</strong>em GUI-Conta<strong>in</strong>er-Objekt enthaltenen GUI-Komponenten werden <strong>in</strong> e<strong>in</strong>er Liste verwaltet, wobei die Reihen-<br />
folge der Listenelemente standardmässig durch die Reihenfolge ihres E<strong>in</strong>fügens festgelegt ist.<br />
Diese Reihenfolge bestimmt auch die Anordnungs-Reihenfolge der Komponenten entsprechend des jeweils festgeleg-<br />
ten Layout-Managers.<br />
Es ist aber auch möglich, die Reihenfolge der Komponenten (Position bezüglich des gewählten Layouts) durch e<strong>in</strong>en<br />
entsprechenden Parameter ("Index") der E<strong>in</strong>füge-Methode explizit zu bee<strong>in</strong>flussen.<br />
◇ Wenn <strong>in</strong> e<strong>in</strong>en Conta<strong>in</strong>er e<strong>in</strong>e Komponente neu e<strong>in</strong>gefügt oder entfernt wird, nachdem der Conta<strong>in</strong>er bereits sichtbar<br />
ist, muß die von Component geerbte – aber überschriebene – Methode validate() aufgerufen werden.<br />
Dadurch wird der Layout-Manager des Conta<strong>in</strong>ers veranlasst, das Layout entsprechend anzupassen.<br />
◇ Die von Component geerbte Methode pa<strong>in</strong>t() ist so überschrieben, dass für alle im Conta<strong>in</strong>er enthaltenen<br />
Komponenten deren pa<strong>in</strong>t()-Methode aufgerufen wird.<br />
◇ Die wichtigsten Methoden zur Komponentenverwaltung s<strong>in</strong>d :<br />
(die Methoden zum Registrieren von Listener-Objekten für die Event-Behandlung s<strong>in</strong>d nicht mit aufgeführt )<br />
public Component add(Component comp) E<strong>in</strong>fügen der Komponente comp am Ende des Conta<strong>in</strong>ers<br />
public Component add(Component comp, E<strong>in</strong>fügen der Komponente comp an der Position idx<br />
<strong>in</strong>t idx)<br />
public Component add(Component comp, E<strong>in</strong>fügen der Komponente comp unter Berücksichtigung<br />
Object constr) der durch constr festgelegten E<strong>in</strong>schränkungen<br />
public Component getComponent(<strong>in</strong>t idx) Ermitteln der Komponente an der Position idx<br />
public Component[] getComponents() Ermitteln aller Komponenten des Conta<strong>in</strong>ers<br />
public <strong>in</strong>t getComponentCount() Ermitteln der Anzahl der Komponenten im Conta<strong>in</strong>er<br />
public void remove(Component comp) Entfernen der Komponente comp aus dem Conta<strong>in</strong>er<br />
public void remove(<strong>in</strong>t idx) Entfernen der Komponente an der Position idx<br />
public void removeAll() Entfernen aller Komponenten aus dem Conta<strong>in</strong>er<br />
public void setLayout(LayoutManager mgr) Setzen des Layout-Managers mgr für den Conta<strong>in</strong>er<br />
public LayoutManager getLayout() Ermitteln des Layout-Managers des Conta<strong>in</strong>ers<br />
◇ E<strong>in</strong> Conta<strong>in</strong>er besitzt Randbereiche (<strong>in</strong>sets), die nicht für die Aufnahme von Komponenten zur Verfügung stehen<br />
(z.B. die Titelleiste).<br />
Die Randbereiche werden <strong>in</strong> e<strong>in</strong>em Objekt der Klasse Insets (Package java.awt) zusammengefasst.<br />
Die 4 Randbereiche (Angabe <strong>in</strong> Pixel) s<strong>in</strong>d zugänglich über public-<strong>in</strong>t-Datenkomponenten : top, left,<br />
bottom, right.<br />
Zur Ermittlung des Insets-Objekt e<strong>in</strong>es Conta<strong>in</strong>ers dient die Memberfunktion :<br />
public Insets getInsets() Ermittlung der Randbereiche des Conta<strong>in</strong>ers
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 533 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Die abstrakte Klasse JComponent<br />
Basisklassen der JFC-Hierachie (3)<br />
◇ Diese von Conta<strong>in</strong>er abgeleitete und im Package javax.sw<strong>in</strong>g enthaltene Klasse ist Basisklasse aller<br />
Sw<strong>in</strong>g-Komponenten-Klassen mit Ausnahme der Top-Level-Conta<strong>in</strong>er<br />
◇ Die Klasse passt e<strong>in</strong>ige der von Conta<strong>in</strong>er und Component geerbten Methoden an die Funktionalität und<br />
die speziellen Eigenschaften des Sw<strong>in</strong>g-Frameworks an.<br />
Zusätzlich def<strong>in</strong>iert sie Methoden, die speziell für Sw<strong>in</strong>g-Komponenten von Bedeutung s<strong>in</strong>d<br />
◇ U.a. besitzen Sw<strong>in</strong>g-Komponenten die folgenden bei AWT-Komponenten nicht vorhandenen Besonderheiten :<br />
▻ Sw<strong>in</strong>g-Komponenten können mit e<strong>in</strong>er Umrandung versehen werden.<br />
Die Umrandung wird durch e<strong>in</strong> Objekt e<strong>in</strong>er das Interface Border implementierenden Klasse festgelegt.<br />
Zur Erzeugung derartiger Border-Objekte stehen statische Methoden der Klasse BorderFactory zur<br />
Verfügung.<br />
▻ Der H<strong>in</strong>tergrund von Sw<strong>in</strong>g-Komponenten kann durchsichtig (nicht-opak) oder undurchsichtig (opak) se<strong>in</strong>.<br />
AWT-Komponenten besitzen immer e<strong>in</strong>en undurchsichtigen H<strong>in</strong>tergrund.<br />
In der Klasse JComponent ist als Default durchsichtig (nicht-opak) festgelegt.<br />
Allerd<strong>in</strong>gs hängt der tatsächliche Defaultwert dieser Eigenschaft bei den abgeleiteten Sw<strong>in</strong>g-Klassen i.a. von<br />
dem jeweils e<strong>in</strong>gesetzten LaF ab.<br />
▻ Sw<strong>in</strong>g-Komponenten können mit e<strong>in</strong>em Tooltip ausgestattet werden. Hierbei handelt es sich um e<strong>in</strong>en mit der<br />
Komponente verknüpften H<strong>in</strong>weistext, der angezeigt wird, wenn der Mauszeiger für kurze Zeit über der Kom-<br />
ponente verweilt.<br />
▻ Für Sw<strong>in</strong>g-Komponenten können die dem Layout-Manager als Dimensionierungsvorschläge dienenden Werte<br />
für die maximale, die m<strong>in</strong>imale und die bevorzugte Größe (Breite und Höhe) der Komponente sowie Vorschläge<br />
für die Ausrichtung e<strong>in</strong>er Komponente (<strong>in</strong> x- und y-Richtung) explizit gesetzt werden. Die entsprechenden Ermitt-<br />
lungs-Methoden (get...(), z.B. getMaximumSize()) s<strong>in</strong>d bereits <strong>in</strong> der Klasse Component def<strong>in</strong>iert.<br />
◇ Zu den wichtigsten der speziellen Sw<strong>in</strong>g-Komponenten-Methoden gehören :<br />
(die Methoden zum Registrieren von Listener-Objekten für die Event-Behandlung s<strong>in</strong>d nicht mit aufgeführt )<br />
public void setBorder(Border bord) Setzen des Border-Objekts bord als Umrandung für<br />
die Komponente<br />
public Border getBorder() Ermitteln der Umrandung der Komponente<br />
public void setOpaque(boolean opa) Setzen des H<strong>in</strong>tergrunds der Komponente auf undurch-<br />
sichtig (opa==true) bzw durchsichtig (opa==false)<br />
public boolean isOpaque() Ermitteln, ob H<strong>in</strong>tergrund der Komponente undurchsichtig<br />
oder durchsichtig ist<br />
true, wenn undurchsichtig, false, wenn durchsichtig<br />
public void setToolTipText(Str<strong>in</strong>g txt) Setzen des Tooltip-Textes für die Komponente<br />
public Str<strong>in</strong>g getToolTipText() Ermitteln des Tooltip-Textes der Komponente<br />
public void setMaximumSize(Dimension d) Setzen der maximalen Größe der Komponente auf die<br />
durch d gegebene Breite und Höhe.<br />
Erzeugung e<strong>in</strong>es Dimension-Objekts :<br />
new Dimension(breite, hoehe)<br />
public void setM<strong>in</strong>imumSize(Dimension d) Setzen der m<strong>in</strong>imalen Größe der Komponente auf d<br />
public void setPreferredSize(Dimension d) Setzen der bevorzugten Größe der Komponente auf d<br />
public void setAlignmentX(float align) Setzen der Ausrichtung <strong>in</strong> hor. Richtung (0.0 ... 1.0)<br />
public void setAlignmentY(float align) Setzen der Ausrichtung <strong>in</strong> vert. Richtung (0.0 ... 1.0)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 541 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zipielle Vorgehensweise<br />
Erstellung e<strong>in</strong>er GUI-Anwendung <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Jede GUI-Anwendung besitzt wenigstens e<strong>in</strong> Top-Level-Fenster, über das sie mit dem Anwender kommuniziert.<br />
E<strong>in</strong>e GUI-Anwendung kann auch mehrere Top-Level-Fenster besitzen.<br />
◇ Für jedes Top-Level-Fenster wird e<strong>in</strong>e eigene Klasse def<strong>in</strong>iert.<br />
Der Aufbau dieser Fenster-Erzeugungs-Klasse kann unterschiedlich se<strong>in</strong>.<br />
Neben anderen bieten sich folgende Hauptvarianten an :<br />
▻ Die Klasse <strong>in</strong>stanziert e<strong>in</strong> Objekt der e<strong>in</strong>gesetzten JFC-Top-Level-Conta<strong>in</strong>er-Klasse (i.a. <strong>in</strong> ihrem Konstruktor)<br />
Dieses kann sie gegebenenfalls über e<strong>in</strong>e Datenkomponente referieren.("has a conta<strong>in</strong>er")<br />
▻ Die Klasse ist von der e<strong>in</strong>gesetzten JFC-Top-Level-Conta<strong>in</strong>er-Klasse abgeleitet.<br />
Bei der Instanzierung der Klasse wird das Top-Level-Conta<strong>in</strong>er-Objekt als Teilobjekt angelegt ("is a conta<strong>in</strong>er").<br />
◇ Für normale Anwendungsprogramme werden als Top-Level-Conta<strong>in</strong>er-Klassen i.a. die Klassen Frame (für AWT-<br />
Anwendungen) bzw JFrame (für Sw<strong>in</strong>g-Anwendungen) e<strong>in</strong>gesetzt.<br />
◇ Die Konfigurierung e<strong>in</strong>es Top-Level-Fensters und damit der graphischen Oberfläche erfolgt typischerweise im<br />
Konstruktor der Fenster-Erzeugungs-Klasse bzw <strong>in</strong> speziellen von diesem aufgerufenen Memberfunktionen :<br />
▻ Gegebenenfalls explizite Erzeugung des Top-Level-Conta<strong>in</strong>er-Objekts (s. oben)<br />
▻ Festlegung des Ersche<strong>in</strong>ungsbildes (ohne LaF, das wird i.a. von ausserhalb , z.B <strong>in</strong> der ma<strong>in</strong>()-Methode der<br />
Start-Klasse, festgelegt) :<br />
▹ Setzen des Layout-Managers (wenn anders als Default)<br />
▹ Setzen der H<strong>in</strong>tergrund- und Vordergrundfarbe (wenn anders als Default)<br />
▹ Setzen der Schriftart (wenn überhaupt benötigt und anders als Default)<br />
▹ Setzen der (Ausgangs-)Größe des Fensters<br />
Wenn die Fenster-Erzeugungs-Klasse von der Top-Level-Conta<strong>in</strong>er-Klasse abgeleitet ist, wird das auch<br />
häufig von ausserhalb – nach der Instanziierung der Klasse – vorgenommen.<br />
▹ Setzen des Titels des Fensters<br />
Dieser kann entweder dem Konstruktor der Klasse Frame bzw JFrame übergeben werden oder<br />
mittels der Memberfunktion setTitle() festgelegt werden.<br />
Auch dies erfolgt häufig von ausserhalb des Konstruktors der Fenster-Erzeugungs-Klasse, wenn diese von der<br />
Top-Level-Conta<strong>in</strong>er-Klasse abgeleitet ist.<br />
▻ Erzeugen, Konfigurieren und E<strong>in</strong>fügen der Komponenten-Objekte des Conta<strong>in</strong>ers.<br />
Dies wird s<strong>in</strong>nvollerweise haeufig <strong>in</strong> e<strong>in</strong>e eigene Methode ausgelagert.<br />
Zur Konfigurierung e<strong>in</strong>er e<strong>in</strong>zufügenden GUI-Komponente s<strong>in</strong>d gegebenenfalls analoge Schritte wie bei der<br />
Konfigurierung des Top-Level-Fensters auszuführen.<br />
Je nach Komponente stehen u.U. noch zusätzliche Konfigurationsmöglichkeiten zur Verfügung (z. B. Setzen<br />
e<strong>in</strong>er Umrandung)<br />
Anmerkung zum E<strong>in</strong>fügen der Komponenten:<br />
In die AWT-Top-Level-Conta<strong>in</strong>er (Frame, Dialog, W<strong>in</strong>dow) werden Komponenten direkt e<strong>in</strong>gefügt<br />
(mittels add()).<br />
In die Sw<strong>in</strong>g-Top-Level-Conta<strong>in</strong>er ( JFrame, JDialog, JW<strong>in</strong>dow) dagegen werden die Komponenten<br />
nicht direkt e<strong>in</strong>gefügt. Sie verfügen über e<strong>in</strong>en speziellen E<strong>in</strong>füge-Conta<strong>in</strong>er, die sogenannte content pane, <strong>in</strong> die<br />
alle aufzunehmenden Komponenten mittels add() e<strong>in</strong>zufügen s<strong>in</strong>d.<br />
◇ Def<strong>in</strong>ition von Event-Listener-Klassen und Registrierung der Event-Listener-Objekte bei den e<strong>in</strong>zelnen<br />
Komponenten. Dies wird ebenfalls s<strong>in</strong>nvollerweise haeufig <strong>in</strong> e<strong>in</strong>e eigene Methode ausgelagert.<br />
Die Kommunikation mit dem Anwender und dem Rest des Anwendungsprogramms (Entity-Klassen) erfolgt nur<br />
über die durch die Event-Listener def<strong>in</strong>ierten Methoden (Callbacks !)<br />
◇ Anzeigen des Top-Level-Conta<strong>in</strong>ers (und aller <strong>in</strong> ihm enthaltenen Komponenten).<br />
Dies erfolgt durch E<strong>in</strong>schalten der Sichtbarkeit des Conta<strong>in</strong>ers (Aufruf von setVisible(true)).<br />
Dies kann entweder ebenfalls im Konstruktor der Fenster-Erzeugungs-Klasse oder – wenn diese von der Top-Level-<br />
Conta<strong>in</strong>er-Klasse abgeleitet ist – von ausserhalb erfolgen.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 542 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Beispiel e<strong>in</strong>er sehr e<strong>in</strong>fachen AWT-Anwendung<br />
Erstellung e<strong>in</strong>er GUI-Anwendung <strong>in</strong> <strong>Java</strong> (2)<br />
Top-Level-Fenster (abgeleitet von Frame) mit e<strong>in</strong>er Label-Komponente<br />
// AWTSimpleFrame.java<br />
import java.awt.*;<br />
public class AWTSimpleFrame extends Frame<br />
{<br />
public AWTSimpleFrame(Str<strong>in</strong>g title)<br />
{<br />
super(title);<br />
Label lab1 = new Label("Hallo !", Label.CENTER);<br />
add(lab1);<br />
addW<strong>in</strong>dowListener(new W<strong>in</strong>dowClos<strong>in</strong>gAdapter()); // Registrierung e<strong>in</strong>es<br />
// Event-Listeners<br />
// zum Schliessen des Fensters<br />
setSize(300,160);<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
AWTSimpleFrame fenster = new AWTSimpleFrame("E<strong>in</strong> sehr e<strong>in</strong>faches AWT-Fenster");<br />
fenster.setVisible(true);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 543 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Beispiel e<strong>in</strong>er sehr e<strong>in</strong>fachen Sw<strong>in</strong>g-Anwendung<br />
Erstellung e<strong>in</strong>er GUI-Anwendung <strong>in</strong> <strong>Java</strong> (3)<br />
Top-Level-Fenster (abgeleitet von JFrame) mit e<strong>in</strong>er JLabel-Komponente<br />
// Sw<strong>in</strong>gSimpleFrame.java<br />
import javax.sw<strong>in</strong>g.*;<br />
import java.awt.*;<br />
public class Sw<strong>in</strong>gSimpleFrame extends JFrame<br />
{<br />
private Conta<strong>in</strong>er c;<br />
}<br />
public Sw<strong>in</strong>gSimpleFrame(Str<strong>in</strong>g title)<br />
{<br />
super(title);<br />
JLabel lab1 = new JLabel("Hallo !", Sw<strong>in</strong>gConstants.CENTER);<br />
c = getContentPane();<br />
c.add(lab1);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
setSize(320, 160);<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Sw<strong>in</strong>gSimpleFrame fenster = new Sw<strong>in</strong>gSimpleFrame(<br />
"E<strong>in</strong> sehr e<strong>in</strong>faches Sw<strong>in</strong>g-Fenster");<br />
fenster.setVisible(true);<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 551 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Die Klasse Color (Package java.awt)<br />
◇ Objekte der Klasse Color dienen zur Beschreibung von Farben.<br />
Sie werden z.B. zum Setzen der H<strong>in</strong>tergrund- und Vordergrundfarbe von GUI-Komponenten benötigt<br />
◇ Objekte dieser Klasse legen e<strong>in</strong>e Farbe durch deren Rot- Grün- und Blau-Anteile (RGB-Werte) fest.<br />
Jeder Anteil wird durch e<strong>in</strong>en <strong>in</strong>t-Wert im Bereich 0 ... 255 repräsentiert. Er lässt sich auch durch e<strong>in</strong>en<br />
float-Wert im Bereich 0.0 ... 1.0 angeben.<br />
◇ E<strong>in</strong>e weitere Datenkomponente dient zur Beschreibung der Farb-Transparenz (Alpha-Wert).<br />
Auch dieser Wert wird entweder als <strong>in</strong>t-Wert (Bereich 0 ... 255) oder als float-Wert (Bereich 0.0 ...<br />
1.0) angegeben.<br />
Dabei bedeutet<br />
- der Wert 0 bzw 0.0 vollkommen durchsichtig (nicht opak),<br />
- der Wert 255 bzw 1.0 vollkommen undurchsichtig (opak)<br />
◇ Objekte für 13 häufig verwendete Farben s<strong>in</strong>d vordef<strong>in</strong>iert und stehen als Klassen-Konstante zur Verfügung :<br />
Von Color.BLACK über Color.GREEN bis Color.YELLOW<br />
• Konstruktoren<br />
◇ Beliebige Color-Objekte lassen sich unter Angabe der RGB-Werte und gegebenenfalls des Alpha-Werts mit Hilfe<br />
der folgenden Konstruktoren erzeugen:<br />
public Color(<strong>in</strong>t r, <strong>in</strong>t g, <strong>in</strong>t b) Erzeugung e<strong>in</strong>es Color-Objekts mit den angegebenen<br />
RGB-Werten und e<strong>in</strong>em Alpha-Wert von 255<br />
(vollkommen undurchsichtig)<br />
public Color(float r, float g, float b) Erzeugung e<strong>in</strong>es Color-Objekts mit den angegebenen<br />
RGB-Werten und e<strong>in</strong>em Alpha-Wert von 1.0<br />
(vollkommen undurchsichtig)<br />
public Color(<strong>in</strong>t r, <strong>in</strong>t g, <strong>in</strong>t b, Erzeugung e<strong>in</strong>es Color-Objekts mit den angegebenen<br />
<strong>in</strong>t a) RGB-Werten und dem angegebenen Alpha-Wert (a)<br />
public Color(float r, float g, float b, Erzeugung e<strong>in</strong>es Color-Objekts mit den angegebenen<br />
float a) RGB-Werten und dem angegebenen Alpha-Wert (a)<br />
• Memberfunktionen zur Ermittlung der Farb-Komponenten<br />
◇ Neben zahlreichen anderen Memberfunktionen existieren die folgenden Methoden zum Ermitteln der e<strong>in</strong>zelnen<br />
Farbkomponenten e<strong>in</strong>es Color-Objekts.<br />
public <strong>in</strong>t getRed() Ermittlung der Rot-Komponente im Bereich 0 ... 255<br />
public <strong>in</strong>t getGreen() Ermittlung der Grün-Komponente im Bereich 0 ... 255<br />
public <strong>in</strong>t getBlue() Ermittlung der Blau-Komponente im Bereich 0 ... 255<br />
public <strong>in</strong>t getAlpha() Ermittlung des Alpha-Werts im Bereich 0 ... 255
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 552 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Die Klasse Font (Package java.awt)<br />
◇ Objekte der Klasse Font repräsentieren Schriftarten.<br />
◇ Die Methode setFont() der Klasse Component dient zur Festlegung der <strong>in</strong> e<strong>in</strong>er GUI-Komponente zu ver-<br />
wendenden Schriftart. Ihr ist e<strong>in</strong> Font-Objekt als Parameter zu übergeben.<br />
Wird für e<strong>in</strong>e GUI-Komponente ke<strong>in</strong>e Schriftart explizit festgelegt (ke<strong>in</strong> Aufruf der Methode setFont() oder<br />
e<strong>in</strong> Aufruf mit null als aktuellem Parameter), so erbt diese Komponente die <strong>in</strong> ihrem Conta<strong>in</strong>er e<strong>in</strong>gesetzte Schriftart.<br />
Defaultmässig wird e<strong>in</strong> systemabhängiger Standard-Font verwendet.<br />
◇ E<strong>in</strong>e Schriftart wird durch drei Parameter festgelegt :<br />
▻ Font-(Familien-)Name<br />
▻ Schriftstil<br />
▻ Schriftgröße<br />
◇ Font-(Familien-)Name<br />
Als Font-(Familien-)Name wird i.a. e<strong>in</strong> Name für e<strong>in</strong>en logischen Font angegeben, der von der <strong>Java</strong>-Laufzeitumgebung<br />
auf e<strong>in</strong>en im System real vorhandenen Font (physikalischen Font) abgebildet wird.<br />
Von jedem <strong>Java</strong>-System werden die folgenden logischen Font-Familien-Namen unterstützt :<br />
▻ "Serif" systemspezifische Proportionalzeichensatz-Familie TimesRoman<br />
Umsetzung unter W<strong>in</strong>dows : True-Type-Font Times New Roman<br />
▻ "SansSerif" systemspezifische Proportionalzeichensatz-Familie Helvetica<br />
Umsetzung unter W<strong>in</strong>dows : True-Type-Font Arial<br />
▻ "Monospaced" systemspezifische Nichtproportionalzeichensatz-Familie Courier<br />
Umsetzung unter W<strong>in</strong>dows : True-Type-Font Courier New<br />
◇ Schriftstil<br />
Spezifizierung durch e<strong>in</strong>en <strong>in</strong>t-Wert. Hierfür s<strong>in</strong>d <strong>in</strong> der Klasse Font die folgenden Konstanten def<strong>in</strong>iert :<br />
▻ Font.PLAIN (0) normale Schrift<br />
▻ Font.BOLD (1) fette Schrift<br />
▻ Font.ITALIC (2) kursive Schrift<br />
Die Schriftstile Font.BOLD und Font.ITALIC können auch mite<strong>in</strong>ander komb<strong>in</strong>iert werden (Addition oder<br />
bitweis-Oder) fette und kursive Schrift.<br />
◇ Schriftgröße<br />
Angabe <strong>in</strong> Punkt (Pt) durch e<strong>in</strong>en <strong>in</strong>t-Wert. Übliche Punktgrößen für normale Textdarstellung : 10 oder 12 Pt.<br />
• Konstruktor<br />
◇ Font-Objekte können mit Hilfe des folgenden Konstruktors erzeugt werden :<br />
• Memberfunktionen zur Ermittlung der Font-Komponenten<br />
◇<br />
public Font(Str<strong>in</strong>g name, <strong>in</strong>t style, <strong>in</strong>t size) Erzeugung e<strong>in</strong>es neuen Font-Objekts mit dem<br />
Namen name, Stil style und Größe size<br />
public Str<strong>in</strong>g getName() Ermittlung des logischen Font-Familien-Namens<br />
public Str<strong>in</strong>g getFamily() Ermittlung des physikalischen Font-Familien-Namens<br />
public <strong>in</strong>t getStyle() Ermittlung des Schriftstils<br />
public <strong>in</strong>t getSize() Ermittlung der Schriftgröße <strong>in</strong> Punkt
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 553 – 01 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Layout-Manager <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Üblicherweise wird die Anordnung (Größe und Position) der <strong>in</strong> e<strong>in</strong>em Conta<strong>in</strong>er enthaltenen Komponenten durch<br />
e<strong>in</strong>en Layout-Manager vorgenommen.<br />
Pr<strong>in</strong>zipiell können die e<strong>in</strong>zelnen Komponenten zwar "H<strong>in</strong>weise" zu ihrer Größe, Position und Ausrichtung enthalten,<br />
diese müssen aber nicht vom Layout-Manager berücksichtigt werden. Vielmehr hat dieser das "letzte Wort" bezüglich<br />
der Anordnung.<br />
◇ Es ist auch möglich, auf e<strong>in</strong>en Layout-Manager zu verzichten und mit absoluter Positionierung zu arbeiten. Dies erfor-<br />
dert dann e<strong>in</strong>e genaue Festlegung der Größe und der Position jeder e<strong>in</strong>zelnen Komponente und führt zu Anpassungs-<br />
problemen, wenn die Größe des Top-Level-Conta<strong>in</strong>ers bzw die Ausführungs-Plattform verändert wird<br />
◇ E<strong>in</strong> Layout-Manager ist e<strong>in</strong> Objekt e<strong>in</strong>er Klasse, die das Interface LayoutManager (Package java.awt)<br />
implementiert.<br />
Dieses Interface def<strong>in</strong>iert Methoden, die für die Anordnung von GUI-Komponenten <strong>in</strong>nerhalb e<strong>in</strong>es Conta<strong>in</strong>ers benötigt<br />
werden.<br />
◇ Für erweiterte Layout-Fähigkeiten ist das von LayoutManager abgeleitete Interface LayoutManager2<br />
def<strong>in</strong>iert. Es enthält Methoden, die es e<strong>in</strong>em Layout-Manager ermöglichen, durch contra<strong>in</strong>ts-Objekte festgelegte Anord-<br />
nungs-Beschränkungen / -Vorgaben explizit zu berücksichtigen.<br />
contra<strong>in</strong>ts-Objekte (häufig Str<strong>in</strong>g-Objekte) spezifizieren wie und wo Komponenten <strong>in</strong> das Layout e<strong>in</strong>zufügen s<strong>in</strong>d.<br />
◇ Die <strong>Java</strong>-Bibliothek stellt e<strong>in</strong>e Reihe von Layout-Manager-Klassen zur Verfügung.<br />
Die e<strong>in</strong>zelnen Klassen unterscheiden sich <strong>in</strong>sbesondere h<strong>in</strong>sichtlich der Unterteilung der Gesamtfläche e<strong>in</strong>es Conta<strong>in</strong>ers<br />
<strong>in</strong> verschiedene Bereiche und die Zuordnung dieser Bereiche zu den im Conta<strong>in</strong>er enthaltenen Komponenten. E<strong>in</strong>ige<br />
Layout-Manager passen dabei die Komponenten <strong>in</strong> ihrer Groesse an oder fügen Zwischenräume zwischen ihnen e<strong>in</strong>.<br />
E<strong>in</strong>ige von ihnen implementieren nur das Interface LayoutManager, andere das Interface LayoutManager2.<br />
Layout-Manager-Klassen s<strong>in</strong>d sowohl im Package java.awt als auch im Package javax.sw<strong>in</strong>g def<strong>in</strong>iert<br />
Die am häufigsten verwendeten Layout-Manager-Klassen s<strong>in</strong>d :<br />
▻ BorderLayout (Package java.awt)<br />
▻ FlowLayout (Package java.awt)<br />
▻ GridLayout (Package java.awt)<br />
▻ BoxLayout (Package javax.sw<strong>in</strong>g)<br />
▻ GridBagLayout (Package java.awt)<br />
◇ Defaultmässig ist <strong>in</strong> den meisten GUI-Conta<strong>in</strong>er-Klassen das BorderLayout e<strong>in</strong>gestellt.<br />
Ausnahmen :<br />
- Für die Klassen Panel und JPanel ist FlowLayout vore<strong>in</strong>gestellt.<br />
- Für die Klasse Box (Package javax.sw<strong>in</strong>g) ist BoxLayout vore<strong>in</strong>gestellt<br />
E<strong>in</strong> anderer Layout-Manager kann mit der <strong>in</strong> der Klasse Conta<strong>in</strong>er def<strong>in</strong>ierten Methode<br />
void setLayout(LayoutManager mgr)<br />
für jedes Conta<strong>in</strong>er-Objekt <strong>in</strong>dividuell festgelegt werden<br />
Dabei lassen sich die im Package javax.sw<strong>in</strong>g def<strong>in</strong>ierten Layout-Manager-Klassen nur für Sw<strong>in</strong>g-Komponenten<br />
e<strong>in</strong>setzen, während die im Package java.awt enthaltenen Layout-Manager-Klassen sowohl für AWT- als auch<br />
für Sw<strong>in</strong>g-Komponenten Anwendung f<strong>in</strong>den.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 553 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Layout-Manager <strong>in</strong> <strong>Java</strong> (2)<br />
• Die Klasse BorderLayout (Package java.awt)<br />
◇ Dieser Layout-Manager teilt den Conta<strong>in</strong>er <strong>in</strong> fünf Gebiete e<strong>in</strong> : "Norden", "Süden", "Westen", Osten" und "Zentrum".<br />
In jedes dieser Gebiete kann er genau e<strong>in</strong>e Komponente e<strong>in</strong>fügen.<br />
◇ Die e<strong>in</strong>zelnen Komponenten werden <strong>in</strong> ihrer Größe so angepasst, dass sie <strong>in</strong>sgesamt den gesamten Conta<strong>in</strong>er ausfüllen.<br />
Allerd<strong>in</strong>gs können sowohl horizontale als auch vertikale Abstände zwischen den Komponenten festgelegt werden.<br />
Die Komponenten im "Norden" und "Süden" bekommen ihre bevorzugte Höhe und werden <strong>in</strong> der Breite an die Con-<br />
ta<strong>in</strong>ergröße angepasst<br />
Die Komponenten im "Westen" und "Osten" bekommen dagegen ihre bevorzugte Breite und werden <strong>in</strong> der Höhe an den<br />
Conta<strong>in</strong>er angepasst.<br />
Die Komponente im "Zentrum" wird sowohl <strong>in</strong> der Höhe als auch <strong>in</strong> der Breite an den verbleibenden Bereich angepasst.<br />
◇ Konstruktoren :<br />
public BorderLayout() Erzeugung e<strong>in</strong>es BorderLayout-Objekts, das die Kom-<br />
ponenten ohne Zwischenabstände anordnet<br />
public BorderLayout(<strong>in</strong>t hgap, <strong>in</strong>t vgap) Erzeugung e<strong>in</strong>es BorderLayout-Objekts, das die Kom-<br />
ponenten mit dem horizontalen Abstand hgap und dem<br />
vertikalen Abstand vgap anordnet (Abstaende <strong>in</strong> Pixel)<br />
◇ Beim E<strong>in</strong>fügen e<strong>in</strong>er Komponente <strong>in</strong> e<strong>in</strong>en Conta<strong>in</strong>er (mittels add()) ist üblicherweise das Gebiet, <strong>in</strong> dem sie platziert<br />
werden soll, anzugeben.<br />
Für diese Angabe s<strong>in</strong>d die folgenden <strong>in</strong> der Klasse BorderLayout def<strong>in</strong>ierten (Str<strong>in</strong>g-)Konstanten zu verwenden :<br />
- BorderLayout.NORTH<br />
- BorderLayout.SOUTH<br />
- BorderLayout.WEST<br />
- BorderLayout.EAST<br />
- BorderLayout.CENTER<br />
Beispiel : Panel p = new Panel();<br />
p.setLayout(new BorderLayout());<br />
p.add(new Button("Okay"), BorderLayout.SOUTH);<br />
Wird ke<strong>in</strong>e Gebietsangabe beim E<strong>in</strong>fügen angegeben, wird die Komponente im "Zentrum" platziert.<br />
◇ Wird die Größe des Conta<strong>in</strong>ers geändert (z.B. durch Ziehen mit der Maus), so bleibt die Höhe der Komponenten im<br />
"Norden" und "Süden" sowie die Breite der Komponenten im "Westen und "Osten" unverändert, während die jeweils<br />
andere Dimension dieser Komponenten sowie beide Dimensionen der Komponente im "Zentrum" an die Größe des<br />
Conta<strong>in</strong>ers angepasst werden.<br />
◇ Beispiel : Border-Layout e<strong>in</strong>es JFrame-Conta<strong>in</strong>ers mit fünf JButton-Komponenten
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 553 – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Layout-Manager <strong>in</strong> <strong>Java</strong> (3)<br />
• Demonstrationsbeispiel zu Layout-Manager (hier : BorderLayout)<br />
// LayoutDemo.java<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class LayoutDemo extends JFrame<br />
{<br />
Conta<strong>in</strong>er c;<br />
JButton[] ba;<br />
Str<strong>in</strong>g titel;<br />
}<br />
public LayoutDemo()<br />
{<br />
c=getContentPane();<br />
titel = "LayoutDemo : ";<br />
}<br />
ba = new JButton[5];<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 553 – 04 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse FlowLayout (Package java.awt)<br />
Layout-Manager <strong>in</strong> <strong>Java</strong> (4)<br />
◇ Dieser Layout-Manager fügt die Komponenten "fliessend" zeilenweise von l<strong>in</strong>ks nach rechts <strong>in</strong> den Conta<strong>in</strong>er e<strong>in</strong>.<br />
Dabei bedeutet "fliessend", dass die Komponenten solange <strong>in</strong> der Reihenfolge ihres E<strong>in</strong>fügens nebene<strong>in</strong>ander platziert<br />
werden, bis ke<strong>in</strong> Platz mehr für die nächste Komponente vorhanden ist. Dann wird das E<strong>in</strong>fügen analog <strong>in</strong> der nächsten<br />
Reihe fortgesetzt.<br />
◇ Die Komponenten werden <strong>in</strong> ihrer bevorzugten Größe (Breite und Höhe) dargestellt.<br />
Defaultmässig werden die <strong>in</strong> e<strong>in</strong>er Reihe bef<strong>in</strong>dlichen Komponenten zentriert ausgerichtet.<br />
Zwischen den Komponenten wird sowohl horizontal als auch vertikal e<strong>in</strong> Abstand von 5 Pixel gesetzt.<br />
Der vertikale Abstand bezieht sich dabei auf die Komponenten mit der jeweils größten Höhe.<br />
Sowohl die Ausrichtung als auch der Abstand <strong>in</strong> beiden Richtungen können geändert werden.<br />
◇ Konstruktoren :<br />
public FlowLayout() Erzeugung e<strong>in</strong>es FlowLayout-Objekts, mit den Default-<br />
e<strong>in</strong>stellungen (zentrierte Ausrichtung und vertikaler und<br />
horizontaler Abstand von 5 Pixel)<br />
public FlowLayout(<strong>in</strong>t align) Erzeugung e<strong>in</strong>es FlowLayout-Objekts, mit e<strong>in</strong>er durch<br />
align festgelegten Ausrichtung und e<strong>in</strong>em vertikalen und<br />
horizontalen Abstand von 5 Pixel<br />
public FlowLayout(<strong>in</strong>t align, <strong>in</strong>t hgap, Erzeugung e<strong>in</strong>es FlowLayout-Objekts, mit e<strong>in</strong>er durch<br />
<strong>in</strong>t vgap) align festgelegten Ausrichtung und e<strong>in</strong>em durch hgap<br />
(horizontal) und vgap (vertikal) gegebenen Abstand<br />
◇ Zur Angabe der Komponenten-Ausrichtung <strong>in</strong> den e<strong>in</strong>zelnen Zeilen (Konstruktor-Parameter align) stehen <strong>in</strong> der<br />
Klasse FlowLayout die folgenden Konstanten zur Verfügung :<br />
- FlowLayout.LEFT (Ausrichtung l<strong>in</strong>ksbündig)<br />
- FlowLayout.RIGHT (Ausrichtung rechtsbündig)<br />
- FlowLayout.CENTER (Ausrichtung zentriert, default)<br />
◇ Wird die Größe des Conta<strong>in</strong>ers geändert (z.B. durch Ziehen mit der Maus), so wird die Zuordnung der Komponen-<br />
ten zu den e<strong>in</strong>zelnen Zeilen entsprechend angepasst.<br />
◇ Beispiel : Flow-Layout e<strong>in</strong>es JFrame-Conta<strong>in</strong>ers mit fünf JButton-Komponenten<br />
(Ergänzung / Modifikation des obigen Demonstrationsprogramms)<br />
private void useFlowLayout()<br />
{ c.setLayout(new FlowLayout());<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 553 – 05 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse GridLayout (Package java.awt)<br />
Layout-Manager <strong>in</strong> <strong>Java</strong> (5)<br />
◇ Dieser Layout-Manager teilt die Conta<strong>in</strong>erfläche <strong>in</strong> gitter- bzw tabellenartig angeordnete Zellen auf.<br />
Die Zellen s<strong>in</strong>d Rechtecke gleicher Größe. Diese Größe ergibt sich aus der Conta<strong>in</strong>ergröße und der Anzahl von Zeilen<br />
und Spalten. In jedem dieser Rechtecke wird genau e<strong>in</strong>e Komponente platziert.<br />
Standardmässig (horizontale Ausrichtung,von l<strong>in</strong>ks nach rechts) werden die Komponenten <strong>in</strong> der Reihenfolge ihres<br />
E<strong>in</strong>fügens zeilenweise von l<strong>in</strong>ks nach rechts angeordnet.<br />
◇ Die Größe der Komponenten wird an die Zellen-Größe angepasst, so dass der <strong>in</strong> der Zelle verfügbare Platz voll ausge-<br />
nutzt wird. Alle Komponenten haben somit die gleiche Größe.<br />
Defaultmässig besteht zwischen den Zellen ke<strong>in</strong> Abstand. Es kann aber sowohl e<strong>in</strong> vertikaler als auch e<strong>in</strong> horizontaler<br />
Abstand festgelegt werden.<br />
◇ Die Anzahl der Zeilen und Spalten können angegeben werden (im Konstruktor oder mittels Memberfunktionen).<br />
Wenigstens e<strong>in</strong>er der beiden Werte muss von 0 verschieden se<strong>in</strong>. Der Wert 0 bedeutet "beliebig viele".<br />
Wenn beide Werte von 0 verschieden s<strong>in</strong>d, wird der Wert für die Anzahl der Spalten ignoriert. In diesem Fall wird<br />
die tatsächliche Anzahl der Spalten aus der festgelegten Anzahl der Zeilen und der Komponenten-Anzahl ermittelt.<br />
Die explizite Angabe e<strong>in</strong>er Spalten-Anzahl bee<strong>in</strong>flusst das Layout nur dann, wenn für die Anzahl der Zeilen 0 angege-<br />
ben wird. Wird weder die Anzahl der Zeilen noch die Anzahl der Spalten explizit festgelegt, wird die Zeilenzahl<br />
defaultmässig auf 1 gesetzt. Die Anzahl der Spalten ergibt sich dann aus der Anzahl der Komponenten.<br />
◇ Konstruktoren :<br />
public GridLayout() Erzeugung e<strong>in</strong>es GridLayout-Objekts, mit e<strong>in</strong>er Zeile,<br />
beliebig vielen Spalten, ke<strong>in</strong> Abstand zwischen den Zellen<br />
public GridLayout(<strong>in</strong>t rows, <strong>in</strong>t cols) Erzeugung e<strong>in</strong>es GridLayout-Objekts, mit rows Zeilen<br />
und cols Spalten (tatsächliche Auswirkung siehe oben),<br />
ke<strong>in</strong> Abstand zwischen den Zellen<br />
public GridLayout(<strong>in</strong>t rows, <strong>in</strong>t cols, Erzeugung e<strong>in</strong>es GridLayout-Objekts, mit rows Zeilen<br />
<strong>in</strong>t hgap, <strong>in</strong>t vgap) und cols Spalten (siehe oben), sowie e<strong>in</strong>em durch hgap<br />
(horizontal) und vgap (vertikal) gegebenen Zellen-Abstand<br />
◇ Wird die Größe des Conta<strong>in</strong>ers geändert (z.B. durch Ziehen mit der Maus), so wird – bei gleichbleibender Zeilen-<br />
und Spaltenzahl – die Größe der Zellen und damit die Größe der Komponenten an die jeweilige Gesamtgröße des<br />
Conta<strong>in</strong>ers angepasst.<br />
◇ Beispiel : Grid-Layout e<strong>in</strong>es JFrame-Conta<strong>in</strong>ers mit fünf JButton-Komponenten (3 Zeilen, 2 Spalten)<br />
(Ergänzung / Modifikation des obigen Demonstrationsprogramms)<br />
private void useGridLayout()<br />
{ c.setLayout(new GridLayout(3,2));<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 553 – 06 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Layout-Manager <strong>in</strong> <strong>Java</strong> (6)<br />
• Die Klasse BoxLayout (Package javax.sw<strong>in</strong>g)<br />
◇ Dieser Layout-Manager ordnet die Komponenten – gemäß ihrer E<strong>in</strong>füge-Reihenfolge - entweder horizontal <strong>in</strong> e<strong>in</strong>er<br />
Zeile oder vertikal <strong>in</strong> e<strong>in</strong>er Spalte an. Die Anordnungs-Achse ist jeweils festzulegen (ke<strong>in</strong> Default).<br />
◇ Er berücksichtigt hierbei sowohl die für die e<strong>in</strong>zelnen Komponenten e<strong>in</strong>gestellten Größen-Parameter (m<strong>in</strong>imale, maxi-<br />
male und bevorzugte Größe) als auch deren festgelegte vertikale und horizontale Ausrichtung.<br />
Grundsätzlich versucht er die Komponenten <strong>in</strong> ihrer bevorzugten Größe darzustellen.<br />
S<strong>in</strong>d bei vertikaler Anordnung die bevorzugten Breiten der Komponenten unterschiedlich, wird versucht, unter Be-<br />
rücksichtigung der jeweiligen maximalen Breiten, die Breite aller Komponenten an die größte bevorzugte Breite anzu-<br />
passen.<br />
Ist das nicht möglich, z.B. weil die maximalen Größen es nicht zulassen, werden die Komponenten <strong>in</strong> ihrer bevorzugten<br />
Breite dargestellt. Die horizontale Ausrichtung der Komponenten (sowohl untere<strong>in</strong>ander als auch <strong>in</strong>nerhalb des Contai-<br />
ners) richtet sich nach deren – defaultmässig vorgegebener bzw explizit gesetzter – horizontaler (X-) Ausrichtung.<br />
Analoges gilt für die horizontale Anordung.<br />
Werden die Komponenten mit unterschiedlicher Höhe dargestellt, richtet sich ihre vertikale Ausrichtung nach der<br />
für die e<strong>in</strong>zelnen Komponenten e<strong>in</strong>gestellten vertikalen (Y-) Ausrichtung (Default ist.i.a. zentriert)<br />
◇ Zwischen den Komponenten wird ke<strong>in</strong> Abstand e<strong>in</strong>gefügt.<br />
Zum Erzeugen von Abständen können spezielle unsichtbare Füll-Komponenten e<strong>in</strong>gesetzt werden.<br />
◇ Konstruktor :<br />
public BoxLayout(Conta<strong>in</strong>er con, <strong>in</strong>t axis) Erzeugung e<strong>in</strong>es BoxLayout-Objekts für das<br />
Conta<strong>in</strong>er-Objekt con mit der durch axis<br />
festgelegten Anordnungs-Achse<br />
◇ Zur Festlegung der Anordnungs-Achse (Konstruktor-Parameter axis) stehen <strong>in</strong> der Klasse BoxLayout die folgen-<br />
den Konstanten zur Verfügung :<br />
- BoxLayout.X_AXIS (horizontale Anordnung, <strong>in</strong> e<strong>in</strong>er Zeile)<br />
- BoxLayout.Y_AXIS (vertikale Anordnung, <strong>in</strong> e<strong>in</strong>er Spalte)<br />
- BoxLayout.LINE_AXIS (Bedeutung sprachabhängig, bei europäischen Sprachen : horizontale Anordnung)<br />
- BoxLayout.PAGE_AXIS (Bedeutung sprachabhängig, bei europäischen Sprachen : vertikale Anordnung)<br />
◇ Bei e<strong>in</strong>er Größenänderung des Conta<strong>in</strong>ers (z.B. durch Ziehen mit der Maus), behalten die Komponenten ihre ur-<br />
sprüngliche Größe, Anordnung und Ausrichtung (zue<strong>in</strong>ander und im Conta<strong>in</strong>er).<br />
◇ Beispiel : Box-Layout e<strong>in</strong>es JFrame-Conta<strong>in</strong>ers mit fünf JButton-Komponenten (vertikale Anordnung)<br />
(Ergänzung / Modifikation des obigen Demonstrationsprogramms)<br />
private void useBoxLayout()<br />
{ c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS));<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 554 – 01 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
Umrandungen für Sw<strong>in</strong>g-Komponenten <strong>in</strong> <strong>Java</strong> (1)<br />
• Umrandungen und das Interface Border (Package javax.sw<strong>in</strong>g.border)<br />
◇ Sw<strong>in</strong>g-GUI-Komponenten (genauer : Objekte aller von JComponent abgeleiteten Klassen) können mit e<strong>in</strong>er<br />
Umrandung versehen werden.<br />
Derartige Umrandungen können u.a. dazu dienen :<br />
- GUI-Komponenten mit e<strong>in</strong>er Dekoration zu versehen<br />
- um rahmenlose GUI-Komponenten e<strong>in</strong>en Rahmen zu zeichnen<br />
- für GUI-Komponenten e<strong>in</strong>en Namen anzugeben<br />
- GUI-Komponenten mit Abstandsflächen zu versehen.<br />
◇ Umrandungen werden durch Border-Objekte beschrieben.<br />
Zum Setzen e<strong>in</strong>er Umrandung muß die <strong>in</strong> JComponent def<strong>in</strong>ierte Memberfunktion setBorder() mit e<strong>in</strong>em<br />
Border-Objekt als Parameter für das entsprechende GUI-Komponenten-Objekt aufgerufen werden.<br />
◇ Border-Objekte s<strong>in</strong>d Objekte von Klassen, die das Interface Border implementieren.<br />
• Klassen für Border-Objekte<br />
◇ In der <strong>Java</strong>-Standard-Bibliothek – u.a. im Package javax.sw<strong>in</strong>g.border – s<strong>in</strong>d zahlreiche Klassen, die das<br />
Interface Border implementieren, def<strong>in</strong>iert.<br />
E<strong>in</strong>ige der im Package javax.sw<strong>in</strong>g.border enthaltenen Klassen s<strong>in</strong>d :<br />
▻ AbstractBorder abstrakte Basisklasse für konkrete Border-Klassen<br />
▻ EmptyBorder Klasse für "leere" Umrandungen Abstandsflächen<br />
▻ L<strong>in</strong>eBorder Klasse für Umrahmungen mit "normalen" L<strong>in</strong>ien<br />
▻ EtchedBorder Klasse für Umrahmungen mit e<strong>in</strong>geprägten bzw herausgearbeiteten L<strong>in</strong>ien<br />
▻ TitledBorder Klasse für mit e<strong>in</strong>em Titel versehene Umrandungen<br />
▻ CompoundBorder Klasse zur Zusammenfassung von zwei Umrandungen zu e<strong>in</strong>er e<strong>in</strong>zigen<br />
◇ Es ist auch möglich eigene Border-Klassen zu def<strong>in</strong>ieren.<br />
Diese s<strong>in</strong>d zweckmässigerweise von der Klasse AbstractBorder abzuleiten.<br />
• Anwendungung von Umrandungen<br />
◇ Pr<strong>in</strong>zipiell können Umrandungen um jedes Objekt e<strong>in</strong>er von JComponent abgeleiteten Klasse gesetzt werden.<br />
◇ Jedoch arbeitet die LaF-Implementierung vieler Standard-Sw<strong>in</strong>g-Komponenten nicht sehr gut mit explizit gesetzten<br />
Umrandungen.<br />
Es wird daher empfohlen, Umrandungen grundsätzlich nur für JPanel- und JLabel-Komponenten zu verwenden.<br />
Bei Komponenten dieser Klassen treten ke<strong>in</strong>e Probleme auf.<br />
◇ Sollen andere Sw<strong>in</strong>g-Komponenten mit e<strong>in</strong>er Umrandung versehen werden, so sollten diese zweckmässigerweise <strong>in</strong><br />
jeweils e<strong>in</strong>e JPanel-Komponente e<strong>in</strong>gebettet werden und um diese dann die Umrandung gesetzt werden.<br />
• Erzeugung von Border-Objekten<br />
◇ E<strong>in</strong> Border-Objekt kann von mehreren GUI-Komponenten-Objekten geme<strong>in</strong>sam genutzt werden.<br />
Daher ist es üblich und zweckmässig , Border-Objekte nicht mittels e<strong>in</strong>es new-Ausdrucks zu erzeugen, sondern<br />
hierfür statische Erzeugungs-Methoden der Klasse BorderFactory (Package javax.sw<strong>in</strong>g) e<strong>in</strong>zusetzen<br />
(Verwendung von Border-Objekten als S<strong>in</strong>gletons).
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 554 – 02 – TH – 05<br />
------------------------------------------------------------------------------------<br />
Umrandungen für Sw<strong>in</strong>g-Komponenten <strong>in</strong> <strong>Java</strong> (2)<br />
• Die Klasse BorderFactory (Package javax.sw<strong>in</strong>g)<br />
◇ Die Klasse BorderFactory stellt u.a. die folgenden statischen Erzeugungs-Methoden für Border-Objekte<br />
bereit (Auswahl) :<br />
public static Border createEmptyBorder(<strong>in</strong>t top, <strong>in</strong>t left, <strong>in</strong>t bottom, <strong>in</strong>t right)<br />
Erzeugung e<strong>in</strong>es EmptyBorder-Objekts mit den durch die Parameter festgelegten Größen (<strong>in</strong> Pixel)<br />
public static Border createL<strong>in</strong>eBorder(Color col, <strong>in</strong>t thick)<br />
Erzeugung e<strong>in</strong>es L<strong>in</strong>eBorder-Objekts, das die Farbe col und die L<strong>in</strong>ien-Stärke thick (<strong>in</strong> Pixel) verwendet<br />
public static Border createL<strong>in</strong>eBorder(Color col)<br />
Erzeugung e<strong>in</strong>es L<strong>in</strong>eBorder-Objekts, das die Farbe col und e<strong>in</strong>en Defaultwert für die L<strong>in</strong>ien-Stärke verwendet<br />
public static Border createEtchedBorder()<br />
Erzeugung e<strong>in</strong>es EtchedBorder-Objekts für e<strong>in</strong>geprägte (etched-<strong>in</strong>) Umrandungen, das die aktuelle H<strong>in</strong>tergrundfarbe<br />
des zu umrandenden Objekts für Hervorhebungen und Abschattungen verwendet<br />
public static Border createEtchedBorder(<strong>in</strong>t type)<br />
Erzeugung e<strong>in</strong>es EtchedBorder-Objekts für den durch type festgelegten Umrandungstyp, das die aktuelle H<strong>in</strong>ter-<br />
grundfarbe des zu umrandenden Objekts für Hervorhebungen und Abschattungen verwendet<br />
Zulässige Werte für type : EtchedBorder.RAISED herausgearbeitete Umrandung (etched-out)<br />
EtchedBorder.LOWERED e<strong>in</strong>geprägte Umrandung (etched-<strong>in</strong>)<br />
public static Border createEtchedBorder(<strong>in</strong>t type, Color highlight, Color shadow)<br />
Erzeugung e<strong>in</strong>es EtchedBorder-Objekts für den durch type festgelegten Umrandungstyp, das die Farbe<br />
highlight für Hervorhebungen und die Farbe shadow für Abschattungen verwendet<br />
public static TitledBorder createTitledBorder(Str<strong>in</strong>g str)<br />
Erzeugung e<strong>in</strong>es TitledBorder-Objekts, das die Beschriftung str und Defaultwerte für die übrigen Kenngrößen<br />
verwendet.<br />
Diese Defaultwerte s<strong>in</strong>d : e<strong>in</strong>geprägte (?) Umrandung, Text auf oberem Rand, l<strong>in</strong>ksbündig, Font und Textfarbe durch die<br />
Defaultwerte des aktuellen LaF bestimmt<br />
public static TitledBorder createTitledBorder(Border bord, Str<strong>in</strong>g str)<br />
Erzeugung e<strong>in</strong>es TitledBorder-Objekts aus dem existierenden Border-Objekt bord, das die Beschriftung<br />
str sowie Defaultwerte für die Textposition (oberer Rand), die Textausrichtung (l<strong>in</strong>ksbündig) und Font und Textfarbe<br />
(Defaultwerte des aktuellen LaF) verwendet.<br />
public static TitledBorder createTitledBorder(Border bord, Str<strong>in</strong>g str, <strong>in</strong>t just,<br />
<strong>in</strong>t pos)<br />
Erzeugung e<strong>in</strong>es TitledBorder-Objekts aus dem existierenden Border-Objekt bord, das die Beschriftung<br />
str sowie die Textposition pos, die Textausrichtung just und Defaultwerte für Font und Textfarbe (Defaultwerte<br />
des aktuellen LaF) verwendet. Zulässige Werte für just und pos siehe <strong>Java</strong>-API-Doc<br />
public static TitledBorder createTitledBorder(Border bord, Str<strong>in</strong>g str, <strong>in</strong>t just,<br />
<strong>in</strong>t pos, Font fnt, Color col)<br />
Erzeugung e<strong>in</strong>es TitledBorder-Objekts aus dem existierenden Border-Objekt bord, das die Beschriftung<br />
str sowie die Textposition pos, die Textausrichtung just, den Font fnt und die Farbe col verwendet.<br />
Zulässige Werte für just und pos siehe <strong>Java</strong>-API-Doc<br />
public static CompoundBorder createCompoundBorder(Border out, Border <strong>in</strong>)<br />
Erzeugung e<strong>in</strong>es CompoundBorder-Objekts aus den existierenden Border-Objekten out (äussere Umrandung)<br />
und <strong>in</strong> (<strong>in</strong>nere Umrandung)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 554 – 03 – TH – 02<br />
------------------------------------------------------------------------------------<br />
• Demonstrationsprogramm zu Umrandungen<br />
// MultiBorderDemo.java<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
import javax.sw<strong>in</strong>g.border.*;<br />
Umrandungen für Sw<strong>in</strong>g-Komponenten <strong>in</strong> <strong>Java</strong> (3)<br />
public class MultiBorderDemo extends JFrame<br />
{ Conta<strong>in</strong>er c;<br />
JButton[] ba;<br />
Str<strong>in</strong>g titel;<br />
}<br />
public MultiBorderDemo(<strong>in</strong>t sel)<br />
{ c=getContentPane();<br />
c.setLayout(new FlowLayout());<br />
titel = "MultiBorderDemo";<br />
JPanel[] pa = new JPanel[5];<br />
}<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 554 – 04 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Umrandungen für Sw<strong>in</strong>g-Komponenten <strong>in</strong> <strong>Java</strong> (4)<br />
• Beispiele für Umrandungen (vom Demonstrationsprogramm MultiBorderDemo erzeugte Fenster)<br />
ke<strong>in</strong>e Umrandung Umrandung mit EmptyBorder<br />
Umrandung mit EtchedBorder Umrandung mit TitledBorder<br />
Umrandung mit CompoundBorder aus Etchedborder und L<strong>in</strong>eBorder
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 561 – 00 – TH – 07<br />
------------------------------------------------------------------------------------<br />
• Die Klasse JFrame (Package javax.sw<strong>in</strong>g)<br />
◇ Wichtigste Sw<strong>in</strong>g-Top-Level-Conta<strong>in</strong>er-Klasse<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (1)<br />
◇ Im Unterschied zur AWT-Top-Level-Conta<strong>in</strong>er-Klasse Frame, von der JFrame abgeleitet ist, werden <strong>in</strong> e<strong>in</strong>en<br />
JFrame-Conta<strong>in</strong>er die Komponenten nicht direkt e<strong>in</strong>gefügt. Vielmehr besitzt jeder JFrame-Conta<strong>in</strong>er, wie jeder<br />
andere Sw<strong>in</strong>g-Top-Level-Conta<strong>in</strong>er, e<strong>in</strong>en speziellen E<strong>in</strong>füge-Conta<strong>in</strong>er, die sogenannte content pane.<br />
Die content pane umfasst den gesamten "normalen" E<strong>in</strong>füge-Bereich des Top-Level-Conta<strong>in</strong>ers. In den Top-Level-<br />
Conta<strong>in</strong>er aufzunehmende Komponenten werden <strong>in</strong> se<strong>in</strong>e content pane e<strong>in</strong>gefügt.<br />
Auch das Setzen e<strong>in</strong>es Layout-Managers erfolgt <strong>in</strong> der content pane und nicht direkt im JFrame-Conta<strong>in</strong>er.<br />
Anmerkung : Ab dem JDK 5.0 s<strong>in</strong>d die Methoden add(), remove() und setLayout() für die Klasse<br />
JFrame so überschrieben, dass sie implizit die content pane verwenden. Sie können damit direkt für JFrame-<br />
Conta<strong>in</strong>er aufgerufen werden.<br />
◇ Zusätzlich kann e<strong>in</strong> JFrame-Conta<strong>in</strong>er über e<strong>in</strong>e Menü-Leiste verfügen. Falls vorhanden, bef<strong>in</strong>det sich diese ausser-<br />
halb der content pane. Sie wird direkt <strong>in</strong> den Top-Level-Conta<strong>in</strong>er e<strong>in</strong>gefügt.<br />
Weiterh<strong>in</strong> kann e<strong>in</strong> JFrame-Conta<strong>in</strong>er e<strong>in</strong>e Werkzeugleiste besitzen.<br />
Diese wird analog zu anderen Komponenten <strong>in</strong> die content pane e<strong>in</strong>gefügt.<br />
◇ Als weiterer Unterschied zur AWT-Klasse Frame ist <strong>in</strong> der Klasse JFrame bereits – ohne explizite Registrierung<br />
e<strong>in</strong>es W<strong>in</strong>dow-Listeners – e<strong>in</strong>e Reaktions-Funktionalität auf das Schliessen des Fensters implementiert.<br />
Die genaue Reaktion kann mittels der Memberfunktion<br />
public void setDefaultCloseOperation(<strong>in</strong>t op)<br />
festgelegt werden.<br />
Als gültige Werte für den Parameter op können die folgenden Konstanten verwendet werden :<br />
- W<strong>in</strong>dowConstants.DO_NOTHING_ON_CLOSE ke<strong>in</strong>e Reaktion<br />
- W<strong>in</strong>dowConstants.HIDE_ON_CLOSE das Fenster verstecken (unsichtbar machen), Default<br />
- W<strong>in</strong>dowConstants.DISPOSE_ON_CLOSE das Fenster verstecken und zerstören<br />
- JFrame.EXIT_ON_CLOSE das Programm beenden (mittels System.exit(0))<br />
◇ Konstruktoren (Auswahl)<br />
public JFrame() Erzeugung e<strong>in</strong>es JFrame-Objekts ohne Titel, das durch das Objekt repräsen-<br />
tierte Fenster ist unsichtbar<br />
public JFrame(Str<strong>in</strong>g title) Erzeugung e<strong>in</strong>es JFrame-Objekts mit dem Titel title, das durch das<br />
Objekt repräsentierte Fenster ist unsichtbar<br />
◇ Memberfunktionen (Auswahl) *) geerbt von Frame **) geerbt von W<strong>in</strong>dow<br />
public Conta<strong>in</strong>er getContentPane() Ermitteln der content pane<br />
public void setDefaultCloseOperation(<strong>in</strong>t op) Setzen der Reaktion auf das Schliessen des Fensters<br />
public void setJMenuBar(JMenuBar menu) E<strong>in</strong>fügen der Menuleiste menu<br />
public void setTitle(Str<strong>in</strong>g title) *) Setzen des Titels auf title<br />
public void dispose() **) Zerstören des Fensters<br />
public void pack() Anpassen der Fenstergröße so, dass alle dar<strong>in</strong> enthaltenen Komponenten gerade Platz haben<br />
**) (Berechnung des Platzbedarfs an Hand der bevorzugten Größe der Komponenten)<br />
◇ Beispiel zum E<strong>in</strong>fügen von Komponenten<br />
JFrame frame = new JFrame();<br />
Conta<strong>in</strong>er c = frame.getContentPane();<br />
c.setLayout(new FlowLayout()); // ab JDK 5.0 auch : frame.setLayout(...)<br />
c.add(new JLabel("Hallo")); // ab JDK 5.0 auch : frame.add(...)
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 562 – 00 – TH – 08<br />
------------------------------------------------------------------------------------<br />
• Die Klasse JDialog (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (2)<br />
◇ Diese Top-Level-Conta<strong>in</strong>er-Klasse wird typischerweise dazu benutzt, temporär auf dem Bildschirm ersche<strong>in</strong>ende<br />
Fenster zu erzeugen, die für e<strong>in</strong>en kurzen Dialog mit dem Benutzer vorgesehen s<strong>in</strong>d ( Dialog-Fenster, Dialog-Box)<br />
◇ E<strong>in</strong> Dialog-Fenster ist üblicherweise an e<strong>in</strong>en JFrame-Conta<strong>in</strong>er oder e<strong>in</strong> anderes Dialog-Fenster gebunden<br />
("Besitzer" des Dialog-Fensters). Es wird zusammen mit se<strong>in</strong>em "Besitzer" ikonifiziert/de-ikonifiziert oder geschlossen.<br />
◇ Dialog-Fenster können modal gestaltet werden.<br />
Das bedeutet, dass während der Sichtbarkeit e<strong>in</strong>es Dialog-Fensters alle anderen Fenster des Programms (also auch<br />
se<strong>in</strong> "besitzendes" Fenster) für Benutzere<strong>in</strong>gaben gesperrt ist.<br />
Die anderen Fenster können erst wieder verwendet werden, wenn der Dialog abgewickelt, d.h. das Dialog-Fenster wieder<br />
geschlossen ist.<br />
◇ Wie e<strong>in</strong> JFrame-Objekt besitzt auch e<strong>in</strong> JDialog-Objekt e<strong>in</strong>e content pane.<br />
In diese – und nicht direkt <strong>in</strong> das JDialog-Objekt – müssen aufzunehmende Komponenten e<strong>in</strong>gefügt werden.<br />
Auch e<strong>in</strong> eventueller Layout-Manager ist ebenfalls <strong>in</strong> der content pane zu setzen.<br />
Anmerkung : ab dem JDK 5.0 erfolgt dies implizit durch die für JDialog entsprechend überladenen Methoden<br />
add() und setLayout() (sowie das Entfernen durch remove())<br />
◇ E<strong>in</strong> JDialog-Objekt kann auch e<strong>in</strong>e Menue-Leiste besitzen. Diese wird – wie bei JFrame-Objekten – direkt <strong>in</strong><br />
den Top-Level-Conta<strong>in</strong>er und nicht <strong>in</strong> die content pane e<strong>in</strong>gefügt.<br />
◇ Konstruktoren (Auswahl)<br />
public JDialog() Erzeugung e<strong>in</strong>es nicht-modalen JDialog-Objekts ohne Titel und ohne<br />
explizit spezifizierten "Besitzer".<br />
E<strong>in</strong> verborgenes Frame-Objekt wird implizit als "Besitzer" gesetzt<br />
public JDialog(Frame owner) Erzeugung e<strong>in</strong>es nicht-modalen JDialog-Objekts ohne Titel und dem<br />
Frame-(JFrame-)Objekt owner als "Besitzer"<br />
public JDialog(Frame owner, Erzeugung e<strong>in</strong>es nicht-modalen JDialog-Objekts mit dem Titel tit und<br />
Str<strong>in</strong>g tit) dem Frame-(JFrame-)Objekt owner als "Besitzer"<br />
public JDialog(Frame owner, Erzeugung e<strong>in</strong>es JDialog-Objekts ohne Titel und dem Frame-(JFrame-)<br />
boolean mod) Objekt owner als "Besitzer". Der Parameter mod bestimmt die Modalität :<br />
modal, wenn true, nicht-modal, wenn false<br />
public JDialog(Frame owner, Erzeugung JDialog-Objekts mit dem Titel tit und dem Frame-<br />
Str<strong>in</strong>g tit, (JFrame-) Objekt owner als "Besitzer". Der Parameter mod bestimmt die<br />
boolean mod) Modalität : modal, wenn true, nicht-modal, wenn false<br />
Es existieren weitere Konstruktoren, mit denen statt e<strong>in</strong>es Frame-(JFrame)-Objekts e<strong>in</strong> Dialog-(JDialog-)<br />
Objekt als "Besitzer" festgelegt wird.<br />
◇ Memberfunktionen (Auswahl)<br />
Die als Auswahl bei der Klasse JFrame angegebenen Memberfunktionen existieren auch für die Klasse JDialog :<br />
public Conta<strong>in</strong>er getContentPane()<br />
public void setDefaultCloseOperation(<strong>in</strong>t op) Der Wert EXIT_ON_CLOSE für op ist nicht zulässig<br />
public void setJMenuBar(JMenuBar menu)<br />
public setTitle(Str<strong>in</strong>g title) *) geerbt von Dialog<br />
public void dispose() **) geerbt von W<strong>in</strong>dow<br />
public void pack() **) geerbt von W<strong>in</strong>dow<br />
E<strong>in</strong>ige weitere Memberfunktionen (geerbt von Dialog) :<br />
public void setModal(boolean mod) Setzen der Modalität auf modal, wenn mod == true<br />
public boolean isModal() Ermittlung der Modalität,<br />
Rückgabewert : true, wenn modal, false andernfalls
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 563 – 01 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (3-1)<br />
• Die Klasse JOptionPane (Package javax.sw<strong>in</strong>g)<br />
◇ Diese Klasse ermöglicht auf relativ e<strong>in</strong>fache Art und Weise die Erzeugung e<strong>in</strong>facher Standard-Dialog-Fenster.<br />
◇ Die erzeugbaren Standard-Dialog-Fenster <strong>in</strong>formieren den Programmbenutzer über irgendetwas und/oder fordern ihn zu<br />
e<strong>in</strong>er E<strong>in</strong>gabe auf.<br />
◇ Die erzeugbaren Standard-Dialog-Fenster s<strong>in</strong>d modal und können <strong>in</strong> der Größe nicht verändert werden.<br />
◇ Als e<strong>in</strong>fachste Möglichkeit zur Dialog-Fenster-Erzeugung stehen e<strong>in</strong>e Reihe statischer Methoden zur Verfügung.<br />
Diese Methoden<br />
▻ erzeugen e<strong>in</strong> weitgehend vorkonfiguriertes Dialog-Fenster, stellen es dar,<br />
▻ warten auf e<strong>in</strong>e zum Schliessen des Fensters führende Benutzeraktion (Schaltknopf-Betätigung, Str<strong>in</strong>g-E<strong>in</strong>gabe)<br />
▻ und liefern gegebenenfalls das Ergebnis der Benutzeraktion als Funktionswert zurück.<br />
◇ E<strong>in</strong>ige statische Klassen-Methoden als Beispiele :<br />
Der bei allen Methoden vorhandene Parameter parent legt die Komponente fest, für die der Dialog jeweils aus-<br />
geführt wird (null ist zulässig)<br />
public static void showMessageDialog(Component parent, Object msg,<br />
Str<strong>in</strong>g title, <strong>in</strong>t typeMsg)<br />
Erzeugen e<strong>in</strong>es Meldungs-Dialog-Fensters mit dem Titel title, das die Meldung msg (meist e<strong>in</strong> Str<strong>in</strong>g) ausgibt und<br />
e<strong>in</strong> durch den Meldungs-Typ typeMsg festgelegtes Default-Icon darstellt.<br />
Zulässige Werte für den Meldungs-Typ typeMsg : JOptionPane.ERROR_MESSAGE<br />
JOptionPane.INFORMATION_MESSAGE<br />
JOptionPane.WARNING_MESSAGE<br />
JOptionPane.QUESTION_MESSAGE<br />
JOptionPane.PLAIN_MESSAGE (ke<strong>in</strong> Icon)<br />
public static void showMessageDialog(Component parent, Object msg)<br />
Erzeugen e<strong>in</strong>es Meldungs-Dialog-Fensters mit dem Titel "Message", das die Meldung msg (meist e<strong>in</strong> Str<strong>in</strong>g) aus-<br />
gibt und das Default-Icon für den Typ INFORMATION_MESSAGE darstellt<br />
public static <strong>in</strong>t showConfirmDialog(Component parent, Object msg,<br />
Str<strong>in</strong>g title, <strong>in</strong>t typeOpt)<br />
Erzeugen e<strong>in</strong>es Bestätigungs-Dialog-Fensters mit dem Titel title, das die Meldung msg (meist e<strong>in</strong> Str<strong>in</strong>g) ausgibt<br />
und das Icon für QUESTION_MESSAGE sowie die durch den Options-Typ typeOpt festgelegten Options-Schalt-<br />
knöpfe darstellt und auf die Auswahl e<strong>in</strong>es Schaltknopfes wartet.<br />
Zulässige Werte für den Options-Typ typeOpt : JOptionsPane.YES_NO_CANCEL_OPTION<br />
JOptionsPane.YES_NO_OPTION<br />
JOptionsPane.OK_CANCEL_OPTION<br />
JOptionsPane.DEFAULT_OPTION (nur OK)<br />
Der vom Benutzer ausgewählte Options-Schaltknopf bestimmt den zurückgegebenen Funktioswert (z.B. YES_OPTION)<br />
public static <strong>in</strong>t showConfirmDialog(Component parent, Object msg)<br />
Erzeugen e<strong>in</strong>es Bestätigungs-Dialog-Fensters mit e<strong>in</strong>em Default-Titel, das die Meldung msg (meist e<strong>in</strong> Str<strong>in</strong>g) ausgibt<br />
und das Icon für QUESTION_MESSAGE sowie die Schaltknöpfe für den Options-Typ YES_NO_CANCEL_OPTION<br />
darstellt und auf die Auswahl e<strong>in</strong>es Schaltknopfes wartet.<br />
Der vom Benutzer ausgewählte Options-Schaltknopf bestimmt den zurückgegebenen Funktioswert (z.B. YES_OPTION)<br />
public static Str<strong>in</strong>g showInputDialog(Component parent, Object msg)<br />
Erzeugen e<strong>in</strong>es Frage-Dialog-Fensters mit dem Titel "Input" (bzw "E<strong>in</strong>gabe"), das die Meldung msg (meist<br />
e<strong>in</strong> Str<strong>in</strong>g) ausgibt, das Icon für QUESTION_MESSAGE darstellt und auf die E<strong>in</strong>gabe e<strong>in</strong>es Str<strong>in</strong>gs wartet.<br />
Der vom Benutzer e<strong>in</strong>gegebene Str<strong>in</strong>g wird als Funktionswert zurückgegeben.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 563 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (3-2)<br />
• Beispiele für von JOptionPane erzeugte Standard-Dialog-Fenster<br />
// Meldungs-Dialog : Fehler-Meldung<br />
JOptionPane.showMessageDialog(this,<br />
"Lesefehler !",<br />
"E<strong>in</strong>e Fehler-Meldung",<br />
JOptionPane.ERROR_MESSAGE);<br />
// Meldungs-Dialog : Information<br />
JOptionPane.showMessageDialog(this,<br />
"Die Festplatte ist zerstoert!",<br />
"E<strong>in</strong>e Information",<br />
JOptionPane.INFORMATION_MESSAGE);<br />
// Meldungs-Dialog : Warnung<br />
JOptionPane.showMessageDialog(this,<br />
"Hoeren Sie auf !",<br />
"E<strong>in</strong>e Warnung",<br />
JOptionPane.WARNING_MESSAGE);<br />
// Meldungs-Dialog : Frage<br />
JOptionPane.showMessageDialog(this,<br />
"Wollen Sie das wirklich ?",<br />
"E<strong>in</strong>e Frage",<br />
JOptionPane.QUESTION_MESSAGE);<br />
// Bestätigungs-Dialog<br />
// Default-Titel und<br />
// Default-Options-Typ<br />
<strong>in</strong>t opt;<br />
opt = JOptionPane.showConfirmDialog(this,<br />
"Was wollen Sie ?");<br />
// Frage-Dialog<br />
// Default-Titel<br />
Str<strong>in</strong>g name;<br />
name = JOptionPane.showInputDialog(this,<br />
"Ihr Name ? ");
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 564 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse JLabel (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (4)<br />
◇ Diese Klasse dient zur Erzeugung von Beschriftungs-Objekten.<br />
◇ Im Unterschied zu den AWT-Label-Objekten können JLabel-Objekte nicht nur Text, sondern auch Bilder dar-<br />
stellen (auch beides komb<strong>in</strong>iert)<br />
◇ Die Ausrichtung sowohl des Textes als auch des Bildes <strong>in</strong>nerhalb des Darstellungsbereichs e<strong>in</strong>es JLabel-Objekts<br />
kann festgelegt werden.<br />
Default-Ausrichtung für Text : horizontal l<strong>in</strong>ksbündig, vertikal zentriert<br />
Default-Ausrichtung für Bilder : horizontal und vertikal zentriert<br />
Explizite Festlegung der Ausrichtung : Sw<strong>in</strong>gConstants.CENTER (zentriert)<br />
Sw<strong>in</strong>gConstants.RIGHT (rechtsbündig)<br />
Sw<strong>in</strong>gConstants.LEFT (l<strong>in</strong>ksbündig)<br />
Sw<strong>in</strong>gConstants.TOP (obenbündig)<br />
Sw<strong>in</strong>gConstants.BOTTOM (untenbündig)<br />
◇ JLabel-Objekte können nicht auf vom Benutzer ausgelöste Ereignisse (E<strong>in</strong>gaben) reagieren.<br />
◇ Konstruktoren (Auswahl)<br />
public JLabel(Str<strong>in</strong>g text) Erzeugung e<strong>in</strong>es JLabel-Objekts mit dem Text text,<br />
der Text ist horizontal l<strong>in</strong>ksbündig ausgerichtet<br />
public JLabel(Str<strong>in</strong>g text, <strong>in</strong>t halign) Erzeugung e<strong>in</strong>es JLabel-Objekts mit dem Text text,<br />
der Text ist horizontal gemäß halign ausgerichtet<br />
public JLabel(Icon image) Erzeugung e<strong>in</strong>es JLabel-Objekts mit dem Bild image,<br />
das Bild ist horizontal zentriert ausgerichtet<br />
public JLabel(Icon image, <strong>in</strong>t halign) Erzeugung e<strong>in</strong>es JLabel-Objekts mit dem Bild image,<br />
das Bild ist horizontal gemäß halign ausgerichtet<br />
◇ Memberfunktionen (Auswahl)<br />
public Str<strong>in</strong>g getText() Rückgabe des dargestellten Textes<br />
public Icon getIcon() Rückgabe des dargestellten Bildes<br />
public void setText(Str<strong>in</strong>g text) Setzen des darzustellenden Textes auf text<br />
public void setIcon(Icon image) Setzen des darzustellenden Bildes auf image<br />
public void setHorizontalAlignment(<strong>in</strong>t halign) Setzen der horizontalen Ausrichtung<br />
gemäß halign (für Text und Bild)<br />
public void setVerticalAlignment(<strong>in</strong>t valign) Setzen der vertikalen Ausrichtung<br />
gemäß valign (für Text und Bild)<br />
◇ Anmerkungen zu darzustellenden Bildern<br />
▻ Bilder werden als Instanzen des Interfaces Icon (Package javax.sw<strong>in</strong>g) referiert.<br />
Im Regelfall handelt es sich bei Ihnen um Objekte der dieses Interface implementierenden Klasse ImageIcon<br />
▻ Objekte der Klasse ImageIcon (Package javax.sw<strong>in</strong>g) können aus e<strong>in</strong>er Bild-Datei erzeugt werden mit dem<br />
Konstruktor :<br />
public ImageIcon(Str<strong>in</strong>g dateipfad)<br />
Der Parameter dateipfad spezifiziert die Bild-Datei.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 565 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse JButton (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (5)<br />
◇ Diese Klasse dient zur Erzeugung von e<strong>in</strong>fachen Schaltknöpfen (Schaltflächen).<br />
◇ Auch JButton-Objekte können – im Unterschied zu den AWT-Button-Objekten – sowohl Text als auch e<strong>in</strong> Bild<br />
(auch beides komb<strong>in</strong>iert) darstellen.<br />
◇ Auch bei JButton-Objekten kann die Ausrichtung sowohl des Textes als auch des Bildes <strong>in</strong>nerhalb ihres Darstel-<br />
lungsbereichs festgelegt werden.<br />
Default-Ausrichtung für Text und Bilder : horizontal rechtsbündig, vertikal zentriert<br />
Explizite Festlegung der Ausrichtung : Sw<strong>in</strong>gConstants.CENTER (zentriert)<br />
Sw<strong>in</strong>gConstants.RIGHT (rechtsbündig)<br />
Sw<strong>in</strong>gConstants.LEFT (l<strong>in</strong>ksbündig)<br />
Sw<strong>in</strong>gConstants.TOP (obenbündig)<br />
Sw<strong>in</strong>gConstants.BOTTOM (untenbündig)<br />
◇ Im Unterschied zu JLabel-Objekten können JButton-Objekte (Schaltknöpfe !) vom Benutzer veranlasste Ereig-<br />
nisse auslösen. E<strong>in</strong> Schaltknopf kann auch den Focus besitzen und dann auch Tastatur-E<strong>in</strong>gaben empfangen.<br />
E<strong>in</strong> Schaltknopf kann vom Benutzer – z.B. durch e<strong>in</strong>en Mausklick oder bei vorhandenen Focus durch die Leertaste –<br />
betätigt ("gedrückt") werden. E<strong>in</strong> "gedrückter" Schaltknopf ändert se<strong>in</strong>e H<strong>in</strong>tergrundfarbe.<br />
◇ Konstruktoren (Auswahl)<br />
public JButton() Erzeugung e<strong>in</strong>es JButton-Objekts ohne "Inhalt"<br />
public JButton(Str<strong>in</strong>g text) Erzeugung e<strong>in</strong>es JButton-Objekts das mit dem Text<br />
text beschriftet ist (horizontal rechtsbündig ausgerichtet)<br />
public JButton(Icon image) Erzeugung e<strong>in</strong>es JButton-Objekts, das mit dem Bild<br />
image versehen ist (horizontal rechtsbündig ausgerichtet)<br />
public JButton(Str<strong>in</strong>g text, Icon image) Erzeugung e<strong>in</strong>es JButton-Objektsd, das mit dem Text<br />
text beschriftet und mit dem Bild image versehen ist<br />
◇ Der überwiegende Teil der von der Klasse JButton angebotenen Schnittstelle ist geerbt von der Klasse<br />
AbstractButton.<br />
Teilweise werden die gleichen Memberfunktionen – mit gleicher Funktionalität – wie bei der Klasse JLabel<br />
zur Verfügung gestellt<br />
Memberfunktionen (von AbstractButton geerbt, Auswahl)<br />
public Str<strong>in</strong>g getText() Rückgabe des dargestellten Textes<br />
public Icon getIcon() Rückgabe des dargestellten Bildes<br />
public void setText(Str<strong>in</strong>g text) Setzen des darzustellenden Textes auf text<br />
public void setIcon(Icon image) Setzen des darzustellenden Bildes auf image<br />
public void setHorizontalAlignment(<strong>in</strong>t halign) Setzen der horizontalen Ausrichtung<br />
gemäß halign (für Text und Bild)<br />
public void setVerticalAlignment(<strong>in</strong>t valign) Setzen der vertikalen Ausrichtung<br />
gemäß valign (für Text und Bild)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 566 – 00 – TH – 05<br />
------------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (6)<br />
• Die Klasse JTextField (Package javax.sw<strong>in</strong>g)<br />
◇ Diese Klasse ist von der abstrakten Basisklasse JTextComponent (Package javax.sw<strong>in</strong>g.text) abgeleitet.<br />
Sie dient zur Erzeugung von editierbaren e<strong>in</strong>zeiligen Textfeldern.<br />
Die Editierbarkeit kann e<strong>in</strong>- und ausgeschaltet werden (Default nach Objekt-Erzeugung : e<strong>in</strong>geschaltet).<br />
◇ JTextField-Objekte können sowohl zur Ausgabe als auch zur E<strong>in</strong>gabe (wenn die Editierbarkeit e<strong>in</strong>geschaltet ist)<br />
von Text verwendet werden.<br />
◇ Die Größe e<strong>in</strong>es Textfeldes (= Anzahl der dargestellten Zeichenpositionen) kann kle<strong>in</strong>er (und natürlich auch größer)<br />
als die Textlänge se<strong>in</strong>. Das heisst, dass auch Text e<strong>in</strong>gegeben werden kann, desen Länge die Anzahl der darstellbaren<br />
Positionen überschreitet.<br />
◇ Die horizontale Ausrichtung des Textes <strong>in</strong>nerhalb des dargestellten Zeilenfensters kann festgelegt werden.<br />
Hierfür stehen die folgenden Konstanten zur Verfügung :<br />
- JTextField.LEFT (l<strong>in</strong>ksbündig)<br />
- JTextField.RIGHT (rechtsbündig)<br />
- JTextField.CENTER (zentriert)<br />
- JTextField.LEADING (Darstellung der führenden Zeichen, wenn Feldlänge kle<strong>in</strong>er als Textlänge, default)<br />
- JTextField.TRAILING (Darstellung der Zeichen am Ende, wenn Feldlänge kle<strong>in</strong>er als Textlänge)<br />
◇ Die Editierfunktionalität umfasst auch die Zusammenarbeit mit dem Clipboard : Text kann aus dem Clipboard e<strong>in</strong>ge-<br />
fügt bzw im Textfeld markiert und – ausgeschnitten oder kopiert – <strong>in</strong> das Clipboard e<strong>in</strong>gefügt werden.<br />
◇ Konstruktoren (Auswahl)<br />
public JTextField() Erzeugung e<strong>in</strong>es "leeren" JTextField-Objekts, die Feldgröße = 0<br />
public JTextField(Str<strong>in</strong>g text) Erzeugung e<strong>in</strong>es JTextField-Objekts, das mit text <strong>in</strong>itialisiert ist,<br />
die Feldgröße wird durch die Länge von text bestimmt.<br />
public JTextField(<strong>in</strong>t cols) Erzeugung e<strong>in</strong>es "leeren" JTextField-Objekts,<br />
die Feldgröße ist durch cols festgelegt.<br />
public JTextField(Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es JTextField-Objekts, das mit text <strong>in</strong>itialisiert ist,<br />
<strong>in</strong>t cols) die Feldgröße ist durch cols festgelegt<br />
◇ Memberfunktionen (Auswahl)<br />
Die meisten der nachfolgend aufgeführten Memberfunktionen s<strong>in</strong>d von der Klasse JTextComponent geerbt.<br />
public void setColumns(<strong>in</strong>t cols) Setzen der Feldgröße auf cols, das Layout wird ungültig gesetzt<br />
public Str<strong>in</strong>g getText() *) Rückgabe des im Textfeld enthaltenen Textes<br />
public Str<strong>in</strong>g getSelectedText() *) Rückgabe des markierten Teils des im Textfeld enthaltenen Textes<br />
public void setText(Str<strong>in</strong>g text) *) Setzen des im Textfeld enthaltenen Textes auf text<br />
public void setEditable(boolean b) Setzen / Aufheben der Editierbarkeit des Textfeldes gemäß b<br />
*) b==true : Setzen der Editierbarkeit, andernfalls Aufheben<br />
public boolean isEditable() *) Ermittelung der Editierbarkeit des Textfeldes<br />
Rückgabewert ==true : editierbar, andernfalls nicht editierbar<br />
public void setHorizontalAlignment(<strong>in</strong>t halign) Setzen der horizontalen Ausrichtung des<br />
Textfeldes auf halign<br />
*) geerbt von JTextComponent (Package javax.sw<strong>in</strong>g.text)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 567 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse JTextArea (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (7-1)<br />
◇ Diese Klasse ist ebenfalls von der Klasse JTextComponent abgeleitet.<br />
Sie dient zur Darstellung editierbarer mehrzeiliger Textfelder.<br />
Wie bei der Klasse JTextField kann die Editierbarkeit e<strong>in</strong>- und ausgeschaltet werden (Default nach Objekt-<br />
Erzeugung : e<strong>in</strong>geschaltet).<br />
◇ JTextArea-Objekte können sowohl zur Ausgabe als auch zur E<strong>in</strong>gabe (bei e<strong>in</strong>geschalteter Editierbarkeit) von Text,<br />
der mehrere Zeilen umfassen kann, e<strong>in</strong>gesetzt werden.<br />
Die Größe des im JTextArea-Objektes darzustellenden Textes kann sich damit dynamisch ändern.<br />
◇ Auch bei dieser Klasse schliesst die Editierfunktionalität die Verwendung des Clipboards e<strong>in</strong> : Text kann aus dem Clip-<br />
board e<strong>in</strong>gefügt bzw im Textfeld markiert und – ausgeschnitten oder kopiert – <strong>in</strong> das Clipboard e<strong>in</strong>gefügt werden.<br />
◇ Die Klasse JTextArea stellt mehrere Methoden zur Verfügung, mit denen der dargestellte Text auch vom Programm<br />
aus editiert werden kann.<br />
U.a. existieren Methoden zum zeilenweisen Text-Zugriff sowie zum E<strong>in</strong>fügen und Anhängen von Text.<br />
◇ Die Größe des im JTextArea-Objektes darzustellenden Textes kann sich <strong>in</strong>folge des benutzer-<strong>in</strong>itiierten oder pro-<br />
gramm-<strong>in</strong>itiierten Editierens dynamisch ändern.<br />
◇ Es ist möglich, für e<strong>in</strong> JTextArea-Objekt die Anzahl der Zeilen und Spalten festzulegen. Diese dienen zur Ermitt-<br />
lung se<strong>in</strong>er bevorzugten Größe (preferred size), die aber nicht der Größe des tatsächlich dargestellten Textfensters<br />
(Darstellungsbereich) entsprechen muß. Diese wird vielmehr durch den e<strong>in</strong>gesetzten Layout-Manager gegebenenfalls<br />
unter Berücksichtigung der Größe des umfassenden Conta<strong>in</strong>ers festgelegt.<br />
◇ Für den Fall, dass e<strong>in</strong>e darzustellende Zeile länger als die dargestellte Textfenster-Breite ist, kann e<strong>in</strong> automatischer<br />
Zeilenumbruch e<strong>in</strong>geschaltet werden<br />
Bei e<strong>in</strong>geschalteten Zeilenumbruch kann festgelegt werden, ob e<strong>in</strong> Umbruch nach jedem Zeichen (zeichenweiser Um-<br />
bruch) oder nur an e<strong>in</strong>er Wortgrenze (wortweiser Umbruch) erfolgen kann.<br />
Defaultmässig ist der Zeilenumbruch ausgeschaltet. Der nicht <strong>in</strong> das dargestellte Fenster passende Zeilenteil ist dann<br />
nicht sichtbar.<br />
Analoges gilt, wenn die tatsächliche Anzahl der darzustellenden Textzeilen größer als die durch das dargestellte Text-<br />
fenster gegebene Zeilenzahl ist.<br />
◇ JTextArea-Objekte besitzen ke<strong>in</strong>e Scroll-Fähigkeiten (Unterschied zu der AWT-Klasse TextArea).<br />
Diese lassen sich aber durch das E<strong>in</strong>betten e<strong>in</strong>es JTextArea-Objektes <strong>in</strong> e<strong>in</strong> JScrollPane-Objekt realisieren.<br />
In diesem Fall wird für den Scrollbereich die durch Zeilen- und Spaltenzahl festgelegte bevorzugte Größe berücksichtigt.<br />
◇ Konstruktoren (Auswahl)<br />
public JTextArea() Erzeugung e<strong>in</strong>es "leeren" JTextArea-Objekts (Die Referenz auf den<br />
enthaltenen Str<strong>in</strong>g ist null)<br />
Die Werte für die Anzahl der Zeilen und Spalten werden auf 0 gesetzt<br />
public JTextArea(Str<strong>in</strong>g text) Erzeugung e<strong>in</strong>es JTextArea-Objekts, das mit text <strong>in</strong>itialisiert ist,<br />
Die Werte für die Anzahl der Zeilen und Spalten werden auf 0 gesetzt<br />
public JTextArea(<strong>in</strong>t rows, Erzeugung e<strong>in</strong>es "leeren" JTextArea-Objekts,<br />
<strong>in</strong>t cols) Die Anzahl der Zeilen ist durch rows, die Anzahl der Spalten durch<br />
cols festgelegt.<br />
public JTextArea(Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es JTextArea-Objekts, das mit text <strong>in</strong>itialisiert ist,<br />
<strong>in</strong>t rows, Die Anzahl der Zeilen ist durch rows, die Anzahl der Spalten durch<br />
<strong>in</strong>t cols) cols festgelegt.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 567 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (7-2)<br />
• Die Klasse JTextArea (Package javax.sw<strong>in</strong>g), Forts.<br />
◇ Memberfunktionen (Auswahl)<br />
Wie <strong>in</strong> der Klasse JTextField werden zahlreiche Memberfunktionen von der Klasse JTextComponent geerbt.<br />
Zusätzlich def<strong>in</strong>iert die Klasse JTextArea e<strong>in</strong>e Reihe eigener Methoden<br />
public Str<strong>in</strong>g getText() *) Rückgabe des im Textfeld enthaltenen Textes<br />
public Str<strong>in</strong>g getSelectedText() *) Rückgabe des markierten Teils des im Textfeld enthaltenen Textes<br />
public void setText(Str<strong>in</strong>g text) *) Setzen des im Textfeld enthaltenen Textes auf text<br />
public void setEditable(boolean b) Setzen / Aufheben der Editierbarkeit des Textfeldes gemäß b<br />
*) b==true : Setzen der Editierbarkeit, andernfalls Aufheben<br />
public boolean isEditable() *) Ermittlung der Editierbarkeit des Textfeldes<br />
Rückgabewert ==true : editierbar, andernfalls nicht editierbar<br />
public void setRows(<strong>in</strong>t rows) Setzen der Anzahl Zeilen auf rows<br />
public void setColumns(<strong>in</strong>t cols) Setzen der Anzahl Spalten auf cols<br />
public <strong>in</strong>t getRows() Ermittlung der festgelegten Zeilen-Anzahl<br />
public <strong>in</strong>t getColumns() Ermittlung der festgelegten Spalten-Anzahl<br />
public <strong>in</strong>t getL<strong>in</strong>eCount() Ermittlung der tatsächlich im Text vorhandenen Zeilenzahl<br />
public void setL<strong>in</strong>eWrap(boolean b) Setzen/Aufheben des automatischen Zeilenumbruchs gemäß b<br />
b==true : Setzen des Zeilenumbruchs, andernfalls Aufheben<br />
public boolean getL<strong>in</strong>eWrap() Ermittlung, ob automatischer Zeilenumbruch gesetzt ist<br />
Rückgabewert ==true : Zeilenumbruch ist gesetzt<br />
public void setWrapStyleWord(boolean b) Setzen der Art des Zeilenumbruchs gemäß b<br />
b==true : wortweiser Zeilenumbruch<br />
b==false : zeichenweiser Zeilenumbruch (Default)<br />
public boolean getWrapStyleWord() Ermittlung der Art des Zeilenumbruchs<br />
Rückgabewert ==true : wortweiser Zeilenumbruch<br />
Rückgabewert ==false : zeichenweiser Zeilenumbruch<br />
void append(Str<strong>in</strong>g str) Anhängen des Str<strong>in</strong>gs str an das Ende des dargestellten Textes<br />
void <strong>in</strong>sert(Str<strong>in</strong>g str, <strong>in</strong>t pos) E<strong>in</strong>fügen des Str<strong>in</strong>gs str an der Position pos im Text<br />
void replaceRange(Str<strong>in</strong>g str, Ersetzen des Textes zwischen den Positionen beg und end<br />
<strong>in</strong>t beg, <strong>in</strong>t end) durch den Str<strong>in</strong>g str<br />
*) geerbt von JTextComponent (Package javax.sw<strong>in</strong>g.text)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 567 – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (7-3)<br />
• Demonstrationsprogramm zur Klasse JTextArea (JTextAreaDemo)<br />
// JTextAreaDemo.java<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
import java.io.*;<br />
public class JTextAreaDemo extends JFrame<br />
{<br />
private f<strong>in</strong>al static Str<strong>in</strong>g DEF_FILE_NAME = "schlechterwitz.txt";<br />
private Conta<strong>in</strong>er c;<br />
private JTextField tf;<br />
private JTextArea ta;<br />
}<br />
public JTextAreaDemo(Str<strong>in</strong>g dname)<br />
{ super("JTextAreaDemo");<br />
tf = new JTextField("Inhalt der Datei \"" + dname + '\"');<br />
tf.setHorizontalAlignment(JTextField.CENTER);<br />
tf.setFont(new Font("SansSerif", Font.BOLD, 14));<br />
tf.setBackground(Color.YELLOW);<br />
c=getContentPane();<br />
ta = new JTextArea(20, 50);<br />
if (dname!=null)<br />
fillTextAreaFromFile(dname);<br />
ta.setFont(new Font("SansSerif", Font.PLAIN, 13));<br />
//ta.setL<strong>in</strong>eWrap(true); // Setzen des automatischen Zeilenumbruchs<br />
//ta.setWrapStyleWord(true); // Setzen der Umbruchsart auf wortweise<br />
c.add(tf, BorderLayout.NORTH);<br />
c.add(ta);<br />
setSize(360, 270);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
}<br />
private void fillTextAreaFromFile(Str<strong>in</strong>g dname)<br />
{ try<br />
{ BufferedReader bfr = new BufferedReader(new FileReader(dname));<br />
Str<strong>in</strong>g l<strong>in</strong>e;<br />
while ((l<strong>in</strong>e=bfr.readL<strong>in</strong>e()) != null)<br />
ta.append(l<strong>in</strong>e + '\n');<br />
bfr.close();<br />
}<br />
catch(IOException ex)<br />
{ System.out.pr<strong>in</strong>tln("Exception " + ex.getMessage());<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Str<strong>in</strong>g fname;<br />
if (args.length==0)<br />
fname = DEF_FILE_NAME;<br />
else<br />
fname = args[0];<br />
new JTextAreaDemo(fname).setVisible(true);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 567 – 04 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (7-4)<br />
• Ausgabe des Demonstrationsprogramms zur Klasse JTextArea (JTextAreaDemo)<br />
◇ Automatischer Zeilenumbruch nicht gesetzt (default)<br />
◇ Automatischer Zeilenumbruch gesetzt (zeichenweiser Umbruch)<br />
◇ Automatischer Zeilenumbruch gesetzt (wortweiser Umbruch)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 568 – 01 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (8-1)<br />
• Die Klasse JScrollPane (Package javax.sw<strong>in</strong>g)<br />
◇ Objekte dieser Klasse dienen zur E<strong>in</strong>bettung anderer GUI-Komponenten <strong>in</strong> e<strong>in</strong>en scrollbaren Darstellungsbereich.<br />
Statt die GUI-Komponente direkt <strong>in</strong> e<strong>in</strong>en Conta<strong>in</strong>er e<strong>in</strong>zufügen, wird sie <strong>in</strong> e<strong>in</strong> JScrollPane-Objekt e<strong>in</strong>gebettet<br />
und dieses dann <strong>in</strong> den Conta<strong>in</strong>er e<strong>in</strong>gefügt.<br />
◇ JScrollPane-Objekte verwalten e<strong>in</strong>en Darstellungsbereich (viewport), <strong>in</strong> dem die e<strong>in</strong>gebettete GUI-Komponente<br />
e<strong>in</strong>geblendet wird.<br />
Wenn die e<strong>in</strong>gebettete Komponente größer als der zur Verfügung stehende Darstellungsbereich ist, wird sie nur aus-<br />
schnittsweise angezeigt. Mit Hilfe von zwei Schiebereglern (scroll bars, horizontale und vertikale Bildlaufleiste) kann<br />
der dargestellte Ausschnitt dynamisch verändert werden.<br />
◇ Es kann festgelegt werden, wann die Bildlaufleisten sichtbar se<strong>in</strong> sollen (Scroll Bar Policy) :<br />
▻ nur sichtbar, wenn nötig (default)<br />
▻ immer sichtbar<br />
▻ nie sichtbar<br />
Dies kann – getrennt für die vertikale und horizontale Bildlaufleiste – im Konstruktor bei der JScrollPane-Objekt-<br />
Erzeugung oder später mittels spezieller Memberfunktionen erfolgen.<br />
Zur Festlegung stehen die folgenden – im implementierten Interface ScrollPaneConstants (Package<br />
javax.sw<strong>in</strong>g) def<strong>in</strong>ierten – Konstanten zur Verfügung :<br />
- JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED (vertikale Bildlaufleiste nur bei Bedarf sichtbar)<br />
- JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED (horizontale Bildlaufleiste nur bei Bedarf sichtbar)<br />
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS (vertikale Bildlaufleiste immer sichtbar)<br />
- JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS (horizontale Bildlaufleiste immer sichtbar)<br />
- JScrollPane.VERTICAL_SCROLLBAR_NEVER (vertikale Bildlaufleiste nie sichtbar)<br />
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER (horizontale Bildlaufleiste nie sichtbar)<br />
◇ Pr<strong>in</strong>zipiell kann jede beliebige GUI-Komponente <strong>in</strong> e<strong>in</strong> JScrollPane-Objekt e<strong>in</strong>gebettet werden.<br />
Diese kann im Konstruktor angegeben oder mittels e<strong>in</strong>er entsprechenden Memberfunktion festgelegt werden.<br />
◇ Für e<strong>in</strong> JScrollPane-Objekt können zusätzlich e<strong>in</strong> Zeilen-Header, e<strong>in</strong> Spalten-Header und Eck-Komponenten<br />
festgelegt werden.<br />
◇ Konstruktoren (Auswahl)<br />
public JScrollPane() Erzeugung e<strong>in</strong>es "leeren" JScrollPane-Objekts.<br />
Beide Bildlaufleisten werden nur bei Bedarf dargestellt<br />
public JScrollPane(Component view) Erzeugung e<strong>in</strong>es JScrollPane-Objekts, <strong>in</strong> dem das GUI-<br />
Komponenten-Objekt view e<strong>in</strong>gebettet ist.<br />
Beide Bildlaufleisten werden nur bei Bedarf dargestellt<br />
public JScrollPane(Component view, Erzeugung e<strong>in</strong>es JScrollPane-Objekts, <strong>in</strong> dem das GUI-<br />
<strong>in</strong>t vsbPol, <strong>in</strong>t hsbPol) Komponenten-Objekt view e<strong>in</strong>gebettet ist<br />
Die Sichtbarkeit der Bildlaufleisten wird durch vsbPol (vertikal<br />
und hsbPol (horizontal) festgelegt<br />
◇ Memberfunktionen (Auswahl)<br />
public void setVerticalScrollBarPolicy(<strong>in</strong>t pol) Setzen der ScrollBarPolicy für die vertikale<br />
Bildlaufleiste auf pol<br />
public void setHorizontalScrollBarPolicy(<strong>in</strong>t pol) Setzen der ScrollBarPolicy für die horizontale<br />
Bildlaufleiste auf pol<br />
public void setViewportView(Component view) E<strong>in</strong>bettung des GUI-Komponenten-Objekts view
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 568 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (8-2)<br />
• Demonstrationsprogramm zur Klasse JScrollPane (JScrollPaneDemo)<br />
// JScrollPaneDemo.java<br />
// E<strong>in</strong>bettung e<strong>in</strong>es JTextArea-Objekts <strong>in</strong> e<strong>in</strong> JScrollPane-Objekt<br />
// Modifikation des Demonstrations-Programms zur Klasse JTextArea<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
import java.io.*;<br />
public class JScrollPaneDemo extends JFrame<br />
{<br />
f<strong>in</strong>al static Str<strong>in</strong>g DEF_FILE_NAME = /*"beispiel.txt"*/"schlechterwitz.txt";<br />
private Conta<strong>in</strong>er c;<br />
private JTextField tf;<br />
private JTextArea ta;<br />
private JScrollPane sp;<br />
}<br />
public JScrollPaneDemo(Str<strong>in</strong>g dname)<br />
{ super("JScrollPaneDemo");<br />
tf = new JTextField("Inhalt der Datei \"" + dname + '\"');<br />
tf.setHorizontalAlignment(JTextField.CENTER);<br />
tf.setFont(new Font("SansSerif", Font.BOLD, 14));<br />
tf.setBackground(Color.YELLOW);<br />
c=getContentPane();<br />
ta = new JTextArea(20,50);<br />
if (dname!=null)<br />
fillTextAreaFromFile(dname);<br />
ta.setFont(new Font("SansSerif", Font.PLAIN, 13));<br />
sp = new JScrollPane(ta);<br />
c.add(tf, BorderLayout.NORTH);<br />
c.add(sp);<br />
setSize(380, 250);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
}<br />
private void fillTextAreaFromFile(Str<strong>in</strong>g dname)<br />
{ try<br />
{ BufferedReader bfr = new BufferedReader(new FileReader(dname));<br />
Str<strong>in</strong>g l<strong>in</strong>e;<br />
while ((l<strong>in</strong>e=bfr.readL<strong>in</strong>e()) != null)<br />
ta.append(l<strong>in</strong>e + '\n');<br />
bfr.close();<br />
}<br />
catch(IOException ex)<br />
{ System.out.pr<strong>in</strong>tln("Exception " + ex.getMessage());<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Str<strong>in</strong>g fname;<br />
if (args.length==0)<br />
fname = DEF_FILE_NAME;<br />
else<br />
fname = args[0];<br />
new JScrollPaneDemo(fname).setVisible(true);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 568 – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (8-3)<br />
• Ausgabe des Demonstrationsprogramms zur Klasse JScrollPane (JScrollPaneDemo)<br />
◇ Automatischer Zeilenumbruch für das e<strong>in</strong>gebettete JTextArea-Objekt nicht gesetzt (default)<br />
◇ Automatischer Zeilenumbruch für das e<strong>in</strong>gebettete JTextArea-Objekt gesetzt (wortweiser Umbruch)<br />
◇ Automatischer Zeilenumbruch für das e<strong>in</strong>gebettete JTextArea-Objekt nicht gesetzt (default)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 568 – 04 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (8-4)<br />
• Weiteres Demonstrationsprogramm zur Klasse JScrollPane (JScrollPaneDemo2)<br />
// JScrollPaneDemo2.java<br />
// E<strong>in</strong>bettung e<strong>in</strong>es JButton-Objekts mit e<strong>in</strong>em Bild <strong>in</strong> e<strong>in</strong> JScrollPane-Objekt<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
import java.io.*;<br />
public class JScrollPaneDemo2 extends JFrame<br />
{<br />
f<strong>in</strong>al static Str<strong>in</strong>g DEF_FILE_NAME = "UnixCountry.jpg";<br />
private Conta<strong>in</strong>er c;<br />
private JButton but; // alternativ : JLabel but;<br />
private JTextField tf;<br />
private JScrollPane sp;<br />
}<br />
public JScrollPaneDemo2(Str<strong>in</strong>g dname)<br />
{ super("JScrollPaneDemo2");<br />
tf = new JTextField("Inhalt der Datei \"" + dname + '\"');<br />
tf.setHorizontalAlignment(JTextField.CENTER);<br />
tf.setFont(new Font("SansSerif", Font.BOLD, 14));<br />
tf.setBackground(Color.YELLOW);<br />
c=getContentPane();<br />
Icon pict = new ImageIcon(dname);<br />
but = new JButton(pict); // alternativ : but = new JLabel(pict);<br />
sp = new JScrollPane(but);<br />
c.add(tf, BorderLayout.NORTH);<br />
c.add(sp);<br />
setSize(550, 350);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Str<strong>in</strong>g fname;<br />
if (args.length==0)<br />
fname = DEF_FILE_NAME;<br />
else<br />
fname = args[0];<br />
new JScrollPaneDemo2(fname).setVisible(true);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 568 – 05 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (8-5)<br />
• Ausgabe des weiteren Demonstrationsprogramms zur Klasse JScrollPane (JScrollPaneDemo2)<br />
◇ verschiedene Stellungen der Schieberegler (Bildlaufleiste)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 569 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse JCheckBox (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (9)<br />
◇ Diese Klasse dient zur Erzeugung von Auswahlfeldern.<br />
E<strong>in</strong> Auswahlfeld (check box) ist e<strong>in</strong> kle<strong>in</strong>es Kästchen, das bei der Anwahl selektiert und deselektiert werden kann.<br />
Der jeweilige Selektionszustand wird angezeigt :<br />
De-selektiert ist das Kästchen leer, selektiert enthält es e<strong>in</strong>en kle<strong>in</strong>en Haken.<br />
◇ E<strong>in</strong> JCheckBox-Objekt dient i.a. zur Darstellung e<strong>in</strong>es logischen Wertes (boolean) auf e<strong>in</strong>er GUI-Oberfläche.<br />
◇ In e<strong>in</strong>er Gruppe von JCheckBox-Objekten (Auswahlfeldern) können beliebig viele selektiert se<strong>in</strong><br />
◇ E<strong>in</strong> JCheckBox-Objekt kann mit e<strong>in</strong>em Text beschriftet oder/und mit e<strong>in</strong>em Bild versehen werden.<br />
E<strong>in</strong> Bild ersetzt dabei das Auswahlfeld-Kästchen <strong>in</strong> der Darstellung. E<strong>in</strong>e eventuelle Selektion kann dann optisch nicht<br />
mehr erkannt werden.<br />
◇ Die Klasse ist von der Klasse JToggleButton abgeleitet, die ihrerseits die abstrakte Klasse AbstractButton<br />
als direkte Basisklasse hat.<br />
◇ Konstruktoren (Auswahl)<br />
public JCheckBox() Erzeugung e<strong>in</strong>es nicht selektierten JCheckBox-Objekts<br />
ohne Text und ohne Bild<br />
public JCheckBox(Str<strong>in</strong>g text) Erzeugung e<strong>in</strong>es nicht selektierten JCheckBox-Objekts,<br />
mit dem Text text beschriftet<br />
public JCheckBox(Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es JCheckBox-Objekts, dessen Anfangs-<br />
boolean select) Selektionszustand durch select festgelegt ist<br />
(select==true : selektiert), Beschriftung mit Text text<br />
public JCheckBox(Icon image) Erzeugung e<strong>in</strong>es nicht selektierten JCheckBox-Objekts,<br />
mit dem Bild image versehen<br />
public JCheckBox(Icon image, Erzeugung e<strong>in</strong>es JCheckBox-Objekts, dessen Anfangs-<br />
boolean select) Selektionszustand durch select festgelegt ist<br />
(select==true : selektiert), mit dem Bild image versehen<br />
public JCheckBox(Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es nicht selektierten JCheckBox-Objekts,<br />
Icon image) mit dem Text text beschriftet und dem Bild image versehen<br />
public JCheckBox(Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es JCheckBox-Objekts, dessen Anfangs-<br />
Icon image, Selektionszustand durch select festgelegt ist<br />
boolean select) (select==true : selektiert), mit dem Text text beschriftet<br />
und mit dem Bild image versehen<br />
◇ Memberfunktionen :<br />
E<strong>in</strong> großer Teil der angebotenen Schnittstelle ist von der Klasse AbstractButton geerbt,<br />
u.a. :<br />
public void setSelected(boolean b) Setzen des Selektionszustands gemäß b<br />
b==true : selektiert, andernfalls nicht selektiert<br />
public boolean isSelected() Ermittlung des Selektionszustands<br />
Rückgabewert ==true : selektiert,<br />
==false : nicht selektiert
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 56A – 01 – TH – 04<br />
------------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (10-1)<br />
• Die Klasse JRadioButton (Package javax.sw<strong>in</strong>g)<br />
◇ Diese Klasse dient ebenfalls zur Erzeugung von Auswahlfeldern.<br />
JRadioButton-Objekte können somit auch zur Darstellung logischer Werte (boolean) auf e<strong>in</strong>er GUI-Oberfläche<br />
e<strong>in</strong>gesetzt werden.<br />
◇ Im Unterschied zur Klasse JCheckBox werden aber mehrere JRadioButton-Objekte meist so zu e<strong>in</strong>er Gruppe<br />
zusammengefasst, dass immer nur e<strong>in</strong> Auswahlfeld aus der Gruppe selektiert werden soll (und kann) (Gruppe alter-<br />
nativer Auswahlfelder).<br />
◇ E<strong>in</strong> Auswahlfeld der Klasse JRadioButton wird durch e<strong>in</strong>en kle<strong>in</strong>en Kreis dargestellt. Im unselektierten Zustand<br />
ist der Kreis leer, bei Selektion ersche<strong>in</strong>t e<strong>in</strong> Punkt im Kreis.<br />
◇ Die Klasse JRadioButton ist ebenfalls von der Klasse JToggleButton und damit auch von der abstrakten<br />
Klasse AbstractButton abgeleitet.<br />
◇ Auch e<strong>in</strong> JRadioButton-Objekt kann mit e<strong>in</strong>em Text beschriftet oder/und mit e<strong>in</strong>em Bild versehen werden.<br />
E<strong>in</strong> Bild ersetzt dabei den Auswahlfeld-Kreis <strong>in</strong> der Darstellung. E<strong>in</strong>e eventuelle Selektion kann dann optisch nicht<br />
mehr erkannt werden.<br />
◇ Konstruktoren (Auswahl)<br />
public JRadioButton() Erzeugung e<strong>in</strong>es nicht selektierten JRadioButton-Objekts<br />
ohne Text und ohne Bild<br />
public JRadioButton (Str<strong>in</strong>g text) Erzeugung e<strong>in</strong>es nicht selektierten JRadioButton -Objekts,<br />
mit dem Text text beschriftet<br />
public JRadioButton (Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es JRadioButton -Objekts, dessen Anfangs-<br />
boolean select) Selektionszustand durch select festgelegt ist<br />
(select==true : selektiert), Beschriftung mit Text text<br />
public JRadioButton (Icon image) Erzeugung e<strong>in</strong>es nicht selektierten JRadioButton -Objekts,<br />
mit dem Bild image versehen<br />
public JRadioButton (Icon image, Erzeugung e<strong>in</strong>es JRadioButton -Objekts, dessen Anfangs-<br />
boolean select) Selektionszustand durch select festgelegt ist<br />
(select==true : selektiert), mit dem Bild image versehen<br />
public JRadioButton (Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es nicht selektierten JRadioButton -Objekts,<br />
Icon image) mit dem Text text beschriftet und dem Bild image versehen<br />
public JRadioButton (Str<strong>in</strong>g text, Erzeugung e<strong>in</strong>es JRadioButton -Objekts, dessen Anfangs-<br />
Icon image, Selektionszustand durch select festgelegt ist<br />
boolean select) (select==true : selektiert), mit dem Text text beschriftet<br />
und mit dem Bild image versehen<br />
◇ Memberfunktionen :<br />
Die angebotene Schnittstelle entspricht weitgehend – soweit sie von der Klasse AbstractButton geerbt ist –<br />
der Schnittstelle der Klasse JCheckBox.<br />
U.a. stehen somit auch die folgenden Methoden zur Verfügung :<br />
public void setSelected(boolean b) Setzen des Selektionszustands gemäß b<br />
b==true : selektiert, andernfalls nicht selektiert<br />
public boolean isSelected() Ermittlung des Selektionszustands<br />
Rückgabewert ==true : selektiert,<br />
==false : nicht selektiert
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 56A – 02 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (10-2)<br />
• Die Klasse ButtonGroup (Package javax.sw<strong>in</strong>g)<br />
◇ Objekte dieser Klasse dienen zur logischen Zusammenfassung mehrerer JRadioButton-Objekte zu e<strong>in</strong>er Gruppe,<br />
<strong>in</strong> der immer nur e<strong>in</strong> Objekt selektiert werden kann.<br />
◇ Sie stellen selbst ke<strong>in</strong>e GUI-Komponenten dar und ersche<strong>in</strong>en deshalb auch nicht auf der GUI-Oberfläche.<br />
◇ Nach der Erzeugung e<strong>in</strong>es ButtonGroup-Objekts und dem H<strong>in</strong>zufügen der JRadioButton-Objekte, die zusam-<br />
mengefasst werden sollen, s<strong>in</strong>d alle JRadioButton-Objekte zunächst de-selektiert.<br />
Nach der erstmaligen Selektion e<strong>in</strong>es JRadioButton-Objekts ist immer genau e<strong>in</strong> Objekt der Gruppe selektiert.<br />
Es gibt danach ke<strong>in</strong>e Möglichkeit mehr, alle Objekte gleichzeitig <strong>in</strong> den de-selektierten Zustand zu versetzen.<br />
◇ Konstruktor :<br />
public ButtonGroup() Erzeugung e<strong>in</strong>e neuen ButtonGroup-Objekts<br />
◇ Memberfunktionen :<br />
public void add(AbstractButton b) H<strong>in</strong>zufügen des Buttons (konkret JRadioButton-Objekts) b<br />
zur Gruppe<br />
public void remove(AbstractButton b) Entfernen des Buttons (konkret JRadioButton-Objekts) b<br />
aus der Gruppe<br />
public <strong>in</strong>t getButtonCount() Rückgabe der Anzahl <strong>in</strong> der Gruppe enthaltenen<br />
AbstractButton-(konkret JRadioButton-)Objekte<br />
public Enumeration Rückgabe aller <strong>in</strong> der Gruppe enthaltenen AbstractButton-<br />
getElements() (konkret JRadioButton-)Objekte<br />
◇ Anmerkung :<br />
▻ Genaugenommen können durch e<strong>in</strong> ButtonGroup-Objekt nicht nur JRadioButton-Objekte sondern Objekte<br />
jeder von AbstractButton abgeleiteten Klasse zusammengefasst werden (Parameter von add() !!!).<br />
Allerd<strong>in</strong>gs ist e<strong>in</strong>e derartige Zusammenfassung nicht immer s<strong>in</strong>nvoll.<br />
▻ Beispielsweise lassen sich auch JCheckBox-Objekte derartig zu e<strong>in</strong>er Gruppe zusammenfassen. Diese Gruppe<br />
ver hält sich dann wie e<strong>in</strong>e JRadioButton-Gruppe (nur e<strong>in</strong>e Checkbox kann jeweils alternativ selektiert werden),<br />
was aber der typischen Anwendung von JCheckBox-Objekten wiederspricht.<br />
▻ Bei Objekten e<strong>in</strong>iger von AbstractButton abgeleiteten Klassen (z.B. JButton und JMenuItem) macht<br />
die Zusammenfassung zu e<strong>in</strong>er Gruppe schon deshalb ke<strong>in</strong>en S<strong>in</strong>n, weil sie den jeweiligen Selektionszustand nicht<br />
anzeigen.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 56A – 03 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (10-3)<br />
• Demonstrationsprogramm zu den Klassen JCheckBox und JRadioButton<br />
// AuswahlfeldDemo.java<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class AuswahlfeldDemo extends JFrame<br />
{<br />
private Conta<strong>in</strong>er c;<br />
private JCheckBox[] cba;<br />
private JRadioButton[] rba;<br />
}<br />
public AuswahlfeldDemo(<strong>in</strong>t anz)<br />
{<br />
setTitle("AuswahlfeldDemo");<br />
c = getContentPane();<br />
c.setLayout(new GridLayout(2,0));<br />
cba = new JCheckBox[anz];<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 56B – 01 – TH – 05<br />
------------------------------------------------------------------------------------<br />
• Die Klasse JPanel (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (11-1)<br />
◇ Diese Klasse dient zur Erzeugung von Gruppierungsfeldern.<br />
E<strong>in</strong> Gruppierungsfeld ist e<strong>in</strong> "<strong>in</strong>nerer" Conta<strong>in</strong>er, der <strong>in</strong> erster L<strong>in</strong>ie zur strukturierten Gestaltung des Inhalts von<br />
Fensterbereichen dient.<br />
Mit e<strong>in</strong>em Gruppierungsfeld lassen sich mehrere Komponenten zu e<strong>in</strong>er Komponente zusammenfassen, die dann wie-<br />
derum <strong>in</strong> e<strong>in</strong>en anderen Conta<strong>in</strong>er (Top-Level-Conta<strong>in</strong>er oder e<strong>in</strong> weiterer "<strong>in</strong>nerer" Conta<strong>in</strong>er) e<strong>in</strong>gefügt werden kann.<br />
◇ Die Klasse JPanel ist von der Klasse JComponent abgeleitet.<br />
◇ Wie andere Conta<strong>in</strong>er auch, verwenden JPanel-Objekte e<strong>in</strong>en Layout-Manager. Im Unterschied zu den Top-Level-<br />
Conta<strong>in</strong>ern ist bei ihnen Flow-Layout als Default e<strong>in</strong>gestellt.<br />
E<strong>in</strong> anderes Layout lässt sich gegebenenfalls bei der Objekt-Erzeugung im Konstruktor oder mittels der – von der<br />
Klasse Conta<strong>in</strong>er geerbten – Methode setLayout() setzen.<br />
Allerd<strong>in</strong>gs ist e<strong>in</strong> Setzen des BoxLayouts bei der Objekterzeugung ist nicht möglich.<br />
Die folgende Anweisung<br />
JPanel mpan = new JPanel(new BoxLayout(mpan, BoxLayout.Y_AXIS));<br />
führt zur der Compiler-Fehlermeldung "Variable mpan ist nicht <strong>in</strong>itialisiert worden".<br />
◇ JPanel-Objekte verfügen von Haus aus über ke<strong>in</strong>e Umrandung.<br />
Bei Bedarf lassen sich aber Umrandungen mit der von der Klasse JComponent geerbten Methode setBorder()<br />
setzen.<br />
◇ Konstruktoren (Auswahl)<br />
public JPanel() Erzeugung e<strong>in</strong>es JPanel-Objekts<br />
(Flow-Layout vore<strong>in</strong>gestellt)<br />
public JPanel(LayoutManager layout) Erzeugung e<strong>in</strong>es JPanel-Objekts mit dem durch layout<br />
festgelegten Layout-Manager<br />
◇ Memberfunktionen<br />
Die Klasse JPanel stellt die Methoden ihrer direkten und <strong>in</strong>direkten Basisklassen JComponent, Conta<strong>in</strong>er<br />
und Component zur Verfügung.<br />
Sie fügt nur wenige weitere – für die Anwendung i.a. nicht wesentliche – Methoden h<strong>in</strong>zu.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 56B – 02 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Demonstrationsprogramm zur Klasse JPanel<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
import javax.sw<strong>in</strong>g.border.*;<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (11-2)<br />
public class JPanelDemo extends JFrame<br />
{ Conta<strong>in</strong>er c;<br />
JPanel pan1, pan2, pan3;<br />
}<br />
public JPanelDemo()<br />
{ super("JPanelDemo");<br />
c=getContentPane();<br />
pan1 = new JPanel();<br />
pan2 = new JPanel();<br />
pan3 = new JPanel(new GridLayout(2,3));<br />
for (<strong>in</strong>t i=1; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 56C – 01 – TH – 01<br />
------------------------------------------------------------------------------------<br />
• Die Klasse Box (Package javax.sw<strong>in</strong>g)<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (12-1)<br />
◇ Diese – direkt von JComponent abgeleitete – Klasse ist e<strong>in</strong>e weitere "<strong>in</strong>nere" Conta<strong>in</strong>er-Klasse. Sie dient eben-<br />
falls zur Erzeugung von Gruppierungsfeldern.<br />
◇ Defaultmässig ist Box-Layout e<strong>in</strong>gestellt. Dieses Layout kann jedoch nicht verändert werden<br />
Die – <strong>in</strong>direkt von Conta<strong>in</strong>er geerbte – Methode setLayout(...) ist so überschrieben, dass sie immer e<strong>in</strong>e<br />
AWTError-Exception wirft.<br />
Gruppierungs-Box.<br />
◇ Die Anordnungs-Achse des verwendeten Box-Layouts (vertikal oder horizontal) ist bei der Objekt-Erzeugung<br />
anzugeben.<br />
◇ Bezüglich der Verwendung als Gruppierungsfelder können Box-Objekte im wesentlichen wie JPanel-Objekte<br />
e<strong>in</strong>gesetzt werden.<br />
Auch Box-Objekte verfügen von Haus aus über ke<strong>in</strong>e Umrandung. Mittels der von JComponent geerbten<br />
Methode setBorder(...) lassen sich jederzeit gewünschte Umrandungen setzen.<br />
◇ Als zusätzliche Besonderheit stellt die Klasse Box e<strong>in</strong>e Reihe von statischen Methoden zur Verfügung, mit denen<br />
unsichtbare GUI-Komponenten erzeugt werden können, die sich als Abstands- und Füll-Komponenten im Box-<br />
Layout – auch <strong>in</strong> Nicht-Box-Conta<strong>in</strong>ern – e<strong>in</strong>setzen lassen.<br />
Diese Komponenten s<strong>in</strong>d Objekte der Klasse Box.Filler (<strong>in</strong>nere Klasse von Box), die ebenfalls direkt von der<br />
Klasse JComponent abgeleitet ist.<br />
Pr<strong>in</strong>zipiell können diese Komponenten auch <strong>in</strong> anderen Layouts verwendet werden, aber ihre wesentliche Bedeutung<br />
haben sie beim BoxLayout.<br />
◇ Konstruktor<br />
public Box(<strong>in</strong>t axis) Erzeugung e<strong>in</strong>es Box-Objekts dessen Layout, die durch axis festgelegte<br />
Anordnungs-Achse besitzt.<br />
Folgende Konstante s<strong>in</strong>d zulässige Werte für axis :<br />
- BoxLayout.X_AXIS (horizontale Anordnung, <strong>in</strong> e<strong>in</strong>er Zeile)<br />
- BoxLayout.Y_AXIS (vertikale Anordnung, <strong>in</strong> e<strong>in</strong>er Spalte)<br />
- BoxLayout.LINE_AXIS (für europäische Sprachen : horizontale Anordnung)<br />
- BoxLayout.PAGE_AXIS (für europäische Sprachen : vertikale Anordnung)<br />
◇ Statische Methoden zur Objekterzeugung<br />
public static Box createHorizontalBox() Erzeugung e<strong>in</strong>es Box-Objekts mit horizontaler<br />
Anordnungs-Achse se<strong>in</strong>es Layouts<br />
public static Box createVerticalBox() Erzeugung e<strong>in</strong>es Box-Objekts mit vertikaler<br />
Anordnungs-Achse se<strong>in</strong>es Layouts<br />
◇ Statische Methoden zur Erzeugung unsichtbarer GUI-Komponenten (Auswahl)<br />
public static Component createRigidArea(Dimension d) Erzeugung e<strong>in</strong>es Box.Filler-Objekts<br />
das die durch d def<strong>in</strong>ierte feste Grösse<br />
besitzt ( Abstands-Komponente)<br />
public static Component createHorizontalGlue() Erzeugung e<strong>in</strong>es Box.Filler-Objekts variabler<br />
anpassbarer Breite ( horizontale Füll-Komponente)<br />
public static Component createVerticalGlue() Erzeugung e<strong>in</strong>es Box.Filler-Objekts variabler<br />
anpassbarer Höhe ( vertikale Füll-Komponente)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 56C – 03 – TH – 01<br />
------------------------------------------------------------------------------------<br />
Ausgewählte Sw<strong>in</strong>g-Komponenten-Klassen (12-3)<br />
• Demonstrationsprogramm zur Klasse Box (und zu unsichtbaren GUI-Komponenten)<br />
import javax.sw<strong>in</strong>g.*;<br />
import javax.sw<strong>in</strong>g.border.*;<br />
import java.awt.*;<br />
public class BoxDemo extends JFrame<br />
{<br />
public BoxDemo()<br />
{ super("BoxDemo");<br />
Box mbox = new Box(BoxLayout.Y_AXIS);<br />
Box box1 = Box.createHorizontalBox(); // = new Box(BoxLayout.X_AXIS);<br />
Box box2 = Box.createVerticalBox(); // = new Box(BoxLayout.Y_AXIS);<br />
mbox.setBorder(BorderFactory.createL<strong>in</strong>eBorder(Color.BLACK,3));<br />
box1.setBorder(BorderFactory.createL<strong>in</strong>eBorder(Color.GREEN,3));<br />
box2.setBorder(BorderFactory.createL<strong>in</strong>eBorder(Color.RED,3));<br />
box1.setAlignmentX(CENTER_ALIGNMENT);<br />
box2.setAlignmentX(CENTER_ALIGNMENT);<br />
for (<strong>in</strong>t i=1; i
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 571 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Delegation Event Model<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (1)<br />
◇ In Programmen mit e<strong>in</strong>em grafischen Benutzer<strong>in</strong>terface f<strong>in</strong>det die Kommunikation zwischen dem Benutzer und dem<br />
Programm mittels Ereignissen (events) statt.<br />
◇ Benutzer<strong>in</strong>teraktionen mit der graphischen Oberfläche (wie z.B. Anwählen e<strong>in</strong>es Schaltknopfes oder Auswahl e<strong>in</strong>es<br />
Menue-E<strong>in</strong>trags mittels Maus oder Tastatur, Schliessen e<strong>in</strong>es Fensters, sonstige Mausbewegungen und Mausklicks,<br />
sonstige Tastature<strong>in</strong>gaben usw) lösen Ereignisse aus, die als Nachrichten vom Betriebssystem an das Programm gesandt<br />
werden.<br />
Auch Änderungen der Größe, der Lage, des Inhalts und des sonstigen Zustands von GUI-Komponenten können zu Ereig-<br />
nissen <strong>in</strong> diesem S<strong>in</strong>ne führen.<br />
Ereignisse können also von unterschiedlichem Typ se<strong>in</strong>.<br />
◇ Innerhalb e<strong>in</strong>es <strong>Java</strong>-Programms werden die durch Nachrichten angezeigten Ereignisse als Objekte spezieller Ereignis-<br />
Klassen (event objects) dargestellt.<br />
Diese Ereignis-Objekte kapseln Informationen über das jeweilige Ereignis (z.B. die Ereignisquelle, spezielle Para-<br />
meter, wie Mauskoord<strong>in</strong>aten, Tastatur-Codes usw)<br />
◇ Die GUI-Komponente an der oder durch die e<strong>in</strong> Ereignis erzeugt wurde, wird als Ereignisquelle (event source)<br />
bezeichnet. Pr<strong>in</strong>zipiell kann jede Komponente e<strong>in</strong>er graphischen Oberfläche e<strong>in</strong>e derartige Ereignisquelle se<strong>in</strong>.<br />
◇ Zuständig für die Reaktion auf das Ereignis s<strong>in</strong>d spezielle Ereignisempfänger, die sogenannten Event-Listener.<br />
Dies s<strong>in</strong>d Objekte, die e<strong>in</strong> zum jeweiligen Ereignis passendes Bearbeitungs-Interface implementieren.<br />
Damit e<strong>in</strong> Event-Listener-Objekt die von e<strong>in</strong>er bestimmten Ereignisquelle verursachten Ereignisse empfangen kann,<br />
muß es bei dieser Ereignisquelle als Listener registriert se<strong>in</strong> (Design Pattern Observer !).<br />
Dabei werden e<strong>in</strong>em Listener nur die Ereignisse mitgeteilt, die zu se<strong>in</strong>em Typ passen, d.h. für die er e<strong>in</strong> passendes<br />
Bearbeitungs-Interface implementiert hat.<br />
◇ Das Zustellen der e<strong>in</strong>zelnen Ereignisse an die jeweils registrierten Event-Listener erfolgt durch den Aufruf der für den<br />
Ereignis-Typ zuständigen Bearbeitungsfunktion des Listeners (Call Back !). Dieser wird das Ereignis-Objekt als Para-<br />
meter übergeben.<br />
In jedem GUI-Programm ist hierfür e<strong>in</strong> eigener Thread zuständig, der event-dispatch<strong>in</strong>g thread.<br />
◇ Zwischen e<strong>in</strong>er Ereignisquelle und e<strong>in</strong>em Event-Listener muß ke<strong>in</strong>e 1:1-Beziehung bestehen.<br />
Bei e<strong>in</strong>er Ereignisquelle können durchaus mehrere Event-Listener registriert se<strong>in</strong> – sogar für den gleichen Ereignis-Typ.<br />
Das Ereignis wird dann allen bei der Quelle für den jeweiligen Ereignis-Typ registrierten Event-Listenern zugestellt.<br />
Andererseits kann e<strong>in</strong> Event-Listener auch gleichzeitig bei mehreren Ereignisquellen registriert se<strong>in</strong>.<br />
Ereignisquelle 1 event Event-Listener 1<br />
Ereignisquelle 2<br />
Ereignisquelle 3<br />
event<br />
event<br />
event<br />
Event-Listener 2<br />
Event-Listener 3<br />
Event-Listener 4<br />
◇ Das <strong>in</strong> <strong>Java</strong> seit dem JDK 1.1 implementierte Delegation Event Model wird sowohl für AWT-Komponenten als auch<br />
Sw<strong>in</strong>g-Komponenten angewendet.<br />
◇ Es ermöglicht e<strong>in</strong>e klare Trennung zwischen dem Programmcode zur Oberflächengestaltung (GUI-Klassen !) und<br />
dem Code zur Ereignisverarbeitung (Event-Listener-Klassen) als Schnittstelle zur Anwendungslogik.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 572 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Ereignis-Klassen<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (2)<br />
◇ Auszug aus der Hierarchie der Ereignisklassen<br />
AWTEvent<br />
(java.awt)<br />
ComponentEvent<br />
(java.awt.event)<br />
InputEvent<br />
(java.awt.event)<br />
KeyEvent<br />
(java.awt.event)<br />
AWT Sw<strong>in</strong>g<br />
ChangeEvent<br />
(javax.sw<strong>in</strong>g.event)<br />
ActionEvent<br />
(java.awt.event)<br />
Conta<strong>in</strong>erEvent<br />
(java.awt.event)<br />
MouseEvent<br />
(java.awt.event)<br />
EventObject<br />
(java.util)<br />
ListSelectionEvent<br />
(javax.sw<strong>in</strong>g.event)<br />
ItemEvent<br />
(java.awt.event)<br />
W<strong>in</strong>dowEvent<br />
(java.awt.event)<br />
CaretEvent<br />
(javax.sw<strong>in</strong>g.event)<br />
AncestorEvent<br />
(javax.sw<strong>in</strong>g.event)<br />
FocusEvent<br />
(java.awt.event)<br />
MenuEvent<br />
(javax.sw<strong>in</strong>g.event)<br />
. . . weitere Event-<br />
Klassen<br />
. . . weitere Event-<br />
Klassen<br />
◇ Die verschiedenen Event-Klassen implementieren jeweils Memberfunktionen mit denen Informationen, die mit dem<br />
jeweiligen Event-Objekt verknüpft s<strong>in</strong>d, ermittelt werden können.<br />
◇ Die Klasse EventObject, Basisklasse aller Ereignis-Klassen, stellt die folgende Methode zur Verfügung :<br />
public Object getSource() Ermittlung der ursprünglichen Ereignisquelle<br />
Diese Methode wird von allen anderen Ereignis-Klassen geerbt und kann damit für alle Event-Objekte aufgerufen<br />
werden.<br />
◇ Die verschiedenen Ereignis-Klassen s<strong>in</strong>d jeweils bestimmten Ereignisse auslösenden Aktionen zugeordnet.<br />
Beispielsweise wird e<strong>in</strong> ActionEvent-Objekt durch folgende Aktionen erzeugt :<br />
- Betätigung e<strong>in</strong>es Schaltknopfes<br />
- Selektierung e<strong>in</strong>es Auswahlfeldes<br />
- Auswahl e<strong>in</strong>es Menue- oder Auswahllisten-E<strong>in</strong>trags<br />
- Betätigung der RET-Taste<br />
. . . weitere Event-<br />
Klassen<br />
◇ In vielen Fällen kann bei e<strong>in</strong>er Komponente e<strong>in</strong>er bestimmten GUI-Klasse e<strong>in</strong> Objekt e<strong>in</strong>er bestimmten Ereignis-Klasse<br />
nur durch e<strong>in</strong>e e<strong>in</strong>zige Aktionsart erzeugt werden.<br />
Diese Aktionsart kann bei den verschiedenen GUI-Klassen durchaus unterschiedlich se<strong>in</strong>.<br />
Es gibt aber auch Ereignis-Klassen, die für mehrere verschiedene Aktionsarten bei der gleichen Komponente zuständig<br />
s<strong>in</strong>d.<br />
Beispielsweise ist die Klasse MouseEvent sowohl für Mausbewegungen (mouse motion events) als auch für alle<br />
sonstigen Mausereignisse (mouse events, wie Knopfbetätigung, Maus-E<strong>in</strong>tritt, Maus-Austritt <strong>in</strong> Komponente) zuständig
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 573 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Ereignis-Klassen, Forts.<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (3)<br />
◇ Da auf den verschiedenen GUI-Komponenten jeweils nur spezifische Aktionen ausgeführt werden können, können<br />
diese auch nur Ereignisse ganz bestimmter Klassen auslösen.<br />
E<strong>in</strong>ige Ereignis-Klassen werden bereits <strong>in</strong> den Basisklassen der JFC-Hierarchie unterstützt. Entsprechende Ereignisse<br />
können daher <strong>in</strong> allen Komponenten der davon abgeleiteten Klassen ausgelöst werden.<br />
E<strong>in</strong>ige GUI-Komponenten und die von ihnen unterstützen Ereignis-Klassen :<br />
GUI-Klasse unterstützte Ereignis-Klasse auslösende Aktionn<br />
Component ComponentEvent Position, Größe oder Sichtbarkeit wurden geändert<br />
FocusEvent Focus wurde erhalten oder verloren<br />
KeyEvent Tastatur wurde betätigt<br />
MouseEvent Maus wurde betätigt oder bewegt<br />
Conta<strong>in</strong>er Conta<strong>in</strong>erEvent Conta<strong>in</strong>er-Inhalt wurde verändert<br />
W<strong>in</strong>dow W<strong>in</strong>dowEvent Status des Fensters hat sich geändert<br />
JComponent AncestorEvent Umgebender Conta<strong>in</strong>er hat sich verändert<br />
JButton ActionEvent Schaltknopf wurde betätigt<br />
ChangeEvent Zustand des Schaltknopfes hat sich geändert<br />
JTextField ActionEvent RET-Taste wurde betätigt<br />
CaretEvent Cursorposition hat sich geändert<br />
JTextArea CaretEvent Cursorposition hat sich geändert<br />
JCheckBox ActionEvent Auswahlfeld wurde betätigt<br />
und ChangeEvent Zustand des Auswahlfelds hat sich geändert<br />
JRadioButton ItemEvent Selektionszustand hat sich geändert<br />
JComboBox ActionEvent E<strong>in</strong>trag wurde ausgewählt oder editiert<br />
ItemEvent ausgewählter E<strong>in</strong>trag hat sich geändert<br />
◇ Memberfunktionen (Auswahl) e<strong>in</strong>iger Ereignis-Klassen zur Informationsermittlung über das Ereignis :<br />
▻ Klasse AWTEvent<br />
public <strong>in</strong>t getID() Ermittlung der auslösenden Aktionsart (Klassenkonstante !)<br />
▻ Klasse ActionEvent<br />
public Str<strong>in</strong>g getActionCommand() Ermittlung der für das Ereignis festgelegten Aktionskennung<br />
▻ Klasse ItemEvent<br />
public Object getItem() Ermittlung des vom Ereignis betroffenen Objekts<br />
public <strong>in</strong>t getStateChange() Ermittlung des geänderten Zustands (selektiert oder nicht selektiert)<br />
▻ Klasse W<strong>in</strong>dowEvent<br />
public W<strong>in</strong>dow getW<strong>in</strong>dow() Ermittlung des Fensters, das das Ereignis ausgelöst hat
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 574 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Listener-Interfaces<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (4)<br />
◇ Die beim Auftritt e<strong>in</strong>es Ereignisses <strong>in</strong>formierten Event-Listener müssen jeweils ereignisspezifisch reagieren können.<br />
E<strong>in</strong> Ereignis e<strong>in</strong>er bestimmten Klasse kann nur e<strong>in</strong> Listener empfangen, der bestimmte zur Ereignis-Klasse passende<br />
Reaktions-Methoden bereitstellt.<br />
Jeder Listener muß e<strong>in</strong> bestimmtes Interface implementieren.<br />
◇ Zu jeder Ereignis-Klasse ist m<strong>in</strong>destens e<strong>in</strong> passendes Listener-Interface def<strong>in</strong>iert. Für e<strong>in</strong>ige Ereignis-Klassen gibt es<br />
auch mehrere Listener-Interfaces.<br />
Allgeme<strong>in</strong> gilt :<br />
Zur Ereignis-Klasse AbcEvent existiert das Listener-Interface AbcListener.<br />
Beispiele : Ereignisklasse ActionEvent Listener-Interface ActionListener<br />
Ereignisklasse ItemEvent Listener-Interface ItemListener<br />
Bei mehreren mit e<strong>in</strong>er Ereignis-Klasse korrespondierenden Listener-Interfaces gilt :<br />
Zur Ereignis-Klasse AbcEvent existieren Listener-Interfaces AbcXyzListener<br />
Beispiel : Ereignis-Klasse W<strong>in</strong>dowEvent Listener-Interface W<strong>in</strong>dowListener<br />
W<strong>in</strong>dowFocusListener<br />
W<strong>in</strong>dowStateListener<br />
◇ Die verschiedenen Interfaces s<strong>in</strong>d def<strong>in</strong>iert <strong>in</strong> den Packages java.awt.event und javax.sw<strong>in</strong>g.event.<br />
◇ Alle Listener-Interfaces s<strong>in</strong>d vom Interface EventListener (Package java.util) abgeleitet.<br />
Dieses deklariert ke<strong>in</strong>e Methoden sondern ist e<strong>in</strong> re<strong>in</strong>es Marker-Interface.<br />
◇ E<strong>in</strong>ige Interfaces deklarieren genau e<strong>in</strong>e Methode. Sie s<strong>in</strong>d i.a. sogenannten semantischen Ereignissen zugeordnet.<br />
Andere Interfaces, die i.a. sogenannten Low-Level-Ereignissen zugeordnet s<strong>in</strong>d, deklarieren mehrere Methoden.<br />
E<strong>in</strong>e Event-Listener-Klasse muß alle Methoden des Interfaces, das sie implementiert, def<strong>in</strong>ieren.<br />
Die jeweilige Methode enthält den vom Programm als Reaktion auf das Ereignis auszuführenden Code<br />
( Event-Handler)<br />
Die Information e<strong>in</strong>es Event-Listeners über e<strong>in</strong> e<strong>in</strong>getretenes Ereignis erfolgt durch den Aufruf e<strong>in</strong>er dieser Methoden<br />
als Callback.<br />
◇ Alle Methoden besitzen genau e<strong>in</strong>en Parameter von der jeweiligen zugehörigen Ereignis-Klasse.<br />
Beim Aufruf e<strong>in</strong>er Methode wird ihr das ausgelöste Ereignis-Objekt als aktueller Parameter übergeben.<br />
◇ E<strong>in</strong>ige Listener-Interfaces als Beispiele :<br />
▻ Interface ActionListener (Package java.awt.event)<br />
public void actionPerformed(ActionEvent e) aufgerufen, wenn e<strong>in</strong> ActionEvent auftritt<br />
▻ Interface ItemListener (Package java.awt.event)<br />
public void itemStateChanged(ItemEvent e) aufgerufen, wenn e<strong>in</strong> ItemEvent auftritt<br />
▻ Interface W<strong>in</strong>dowListener (Package java.awt.event), unvollständig<br />
public void w<strong>in</strong>dowClos<strong>in</strong>g(W<strong>in</strong>dowEvent e) aufgerufen, wenn Fenster geschlossen werden soll<br />
public void w<strong>in</strong>dowClosed(W<strong>in</strong>dowEvent e) aufgerufen, wenn Fenster geschlossen wurde<br />
public void w<strong>in</strong>dowActivated(W<strong>in</strong>dowEvent e) aufgerufen, wenn Fenster aktiviert wurde<br />
public void w<strong>in</strong>dowDeactivated(W<strong>in</strong>dowEvent e) aufgerufen, wenn Fenster deaktiviert wurde<br />
public void w<strong>in</strong>dowIconified(W<strong>in</strong>dowEvent e) aufgerufen, wenn Fenster m<strong>in</strong>imiert wurde
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 575 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Listener-Adapter-Klassen<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (5)<br />
◇ E<strong>in</strong>e Klasse, die e<strong>in</strong> Listener-Interface implementiert, dass mehrere Methoden deklariert, muss sämtliche Metho-<br />
den def<strong>in</strong>ieren, auch wenn <strong>in</strong> der speziellen Anwendung nur e<strong>in</strong>e von ihnen benötigt wird.<br />
◇ Zur Vere<strong>in</strong>fachung der Def<strong>in</strong>ition von Listener-Klassen existieren für derartige Interfaces Adapter-Klassen.<br />
Es handelt sich bei Ihnen um abstrakte Klassen, die sämtliche Methoden des Interfaces mit leerer Funktionalität<br />
implementieren.<br />
Statt e<strong>in</strong>e Listener-Klasse das jeweilige Listener-Interface direkt implementieren zu lassen, leitet man die Klasse von<br />
der zugehörigen Adapter-Klasse ab. Die Klasse muß dann lediglich die im konkreten Fall benötigte Methode über-<br />
schreiben.<br />
◇ Wenn zum Listener-Interface AbcListener e<strong>in</strong>e Adapter-Klasse existiert, lautet ihr Name AbcAdapter.<br />
Beispiel : Listener-Interface W<strong>in</strong>dowListener Listener-Adapter W<strong>in</strong>dowAdapter<br />
• Listener-Klassen<br />
◇ Sie müssen das Listener-Interface, das zu der Ereignis-Klasse, deren Objekte sie empfangen sollen, gehört, implemen-<br />
tieren.<br />
E<strong>in</strong>e Listener-Klasse kann auch mehrere Listener-Interfaces implementieren und damit auf Ereignisse unterschied-<br />
licher Klassen reagieren.<br />
◇ E<strong>in</strong>e Listener-Klasse kann das oder die Listener-Interfaces<br />
▻ entweder direkt implementieren<br />
▻ oder von e<strong>in</strong>er zugehörigen Adapter-Klasse abgeleitet werden.<br />
◇ Zur programmtechnischen Realisierung e<strong>in</strong>e Listener-Klasse existieren folgende Möglichkeiten :<br />
▻ Realisierung der Listener-Klasse als <strong>in</strong>nere Klasse<br />
▻ Realisierung der Listener-Klasse als lokale Klasse oder anonyme Klasse<br />
▻ Realisierung der Listener-Klasse als Top-Level-Klasse<br />
▻ Verwendung der Conta<strong>in</strong>er-Klasse als Listener-Klasse<br />
• Implementierung e<strong>in</strong>er Ereignisverarbeitung im Anwender-Code<br />
◆ Def<strong>in</strong>ition e<strong>in</strong>er geeigneten Event-Listener-Klasse.<br />
In der (bzw den) zu implementierenden Interface-Methode(n) (Event-Handler) ist die Programmfunktionalität zu<br />
realisieren, die als Reaktion auf den E<strong>in</strong>tritt e<strong>in</strong>es Ereignisses der betreffenden Art vorgesehen ist.<br />
◆ Erzeugung e<strong>in</strong>es Objekts dieser Event-Listener-Klasse (Event-Listener-Objekt).<br />
◆ Registrierung des Event-Listener-Objekts bei der auf Ereignisse zu "überwachenden" GUI-Komponente.<br />
Hierfür stellen die GUI-Komponenten für die von ihnen unterstützten Listener-Typen entsprechende Registrierungs-<br />
funktionen zur Verfügung :<br />
Für EventListener vom Typ AbcListener Funktion void addAbcListener(AbcListener lis)<br />
Beispiel : Klasse JButton für ActionListener-Objekte (geerbt von der Klasse AbstractButton) :<br />
public void addActionListener(ActionListener lis) Registrierung des Action-Listener-Objects lis<br />
◆ Gegebenenfalls Festlegung von spezifischen Informationen, die e<strong>in</strong>em Ereignis-Objekt übergeben werden.<br />
Beispiel : Klasse JButton : Setzen e<strong>in</strong>er Aktionskennung (action command) für ActionListener-Objekte<br />
(geerbt von der Klasse AbstractButton) :<br />
public void setActionCommand(Str<strong>in</strong>g cmd) Setzen der Aktionskennung cmd
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 576 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (6)<br />
• Demonstrationsprogramm zum Interface ActionListener<br />
// ColorChangeDemo.java<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class ColorChangeDemo extends JFrame<br />
{<br />
Conta<strong>in</strong>er c;<br />
JButton but;<br />
}<br />
public ColorChangeDemo()<br />
{<br />
super("ColorChangeDemo");<br />
c=getContentPane();<br />
c.setLayout(new FlowLayout());<br />
but = new JButton("Change Backgroundcolor");<br />
c.add(but);<br />
}<br />
// ActionListener-Klasse als anonyme Klasse<br />
ActionListener actlis = new ActionListener()<br />
{<br />
public void actionPerformed(ActionEvent e)<br />
{<br />
float rwert = (float)Math.random();<br />
float gwert = (float)Math.random();<br />
float bwert = (float)Math.random();<br />
c.setBackground(new Color(rwert, gwert, bwert));<br />
}<br />
};<br />
but.addActionListener(actlis);<br />
setSize(300, 200);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
new ColorChangeDemo().setVisible(true);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 577 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Ereignisverarbeitung <strong>in</strong> JFC-GUI-Komponenten (6)<br />
• Demonstrationsprogramm zur Adapter-Klasse W<strong>in</strong>dowAdapter<br />
// W<strong>in</strong>dowClos<strong>in</strong>gDemo.java<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class W<strong>in</strong>dowClos<strong>in</strong>gDemo extends JFrame<br />
{ Conta<strong>in</strong>er c;<br />
JLabel lab;<br />
JCheckBox cb1, cb2;<br />
}<br />
public W<strong>in</strong>dowClos<strong>in</strong>gDemo()<br />
{ super("W<strong>in</strong>dow Clos<strong>in</strong>g Demo");<br />
c = getContentPane();<br />
c.setLayout(new FlowLayout());<br />
lab = new JLabel("Zum Schliessen des Fensters bitte " +<br />
"beide Auswahlfelder selektieren");<br />
lab.setBorder(BorderFactory.createEmptyBorder(10, 0, 25, 0));<br />
cb1 = new JCheckBox("Auswahl 1");<br />
cb2 = new JCheckBox("Auswahl 2");<br />
c.add(lab);<br />
c.add(cb1);<br />
c.add(cb2);<br />
addW<strong>in</strong>dowListener(new Clos<strong>in</strong>gListener());<br />
setSize(400, 150);<br />
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);<br />
}<br />
// W<strong>in</strong>dowListener-Klasse als <strong>in</strong>nere Klasse<br />
public class Clos<strong>in</strong>gListener extends W<strong>in</strong>dowAdapter<br />
{<br />
public void w<strong>in</strong>dowClos<strong>in</strong>g(W<strong>in</strong>dowEvent e)<br />
{ if (cb1.isSelected() && cb2.isSelected())<br />
{ e.getW<strong>in</strong>dow().dispose();<br />
System.exit(0);<br />
}<br />
else<br />
JOptionPane.showMessageDialog(c, "Vor dem Schliessen " +<br />
"beide Auswahlfelder selektieren");<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ new W<strong>in</strong>dowClos<strong>in</strong>gDemo().setVisible(true);<br />
}
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 600 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
6. Applets<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel 6<br />
6.1. Aufbau und Funktionsweise<br />
6.2. Applet-Tag im HTML-Code<br />
6.3. <strong>Java</strong>-Applet-API<br />
6.4. Sicherheitsbeschränkungen
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 611 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zip e<strong>in</strong>es Applets<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (1)<br />
◇ E<strong>in</strong> Applet ist e<strong>in</strong> – i.a. kle<strong>in</strong>eres – <strong>Java</strong>-Programm, das nicht eigenständig durch e<strong>in</strong>e JVM ausgeführt wird sondern<br />
<strong>in</strong>nerhalb e<strong>in</strong>es <strong>Java</strong>-fähigen Web-Browsers bzw e<strong>in</strong>es Applet-Viewers abläuft.<br />
◇ Als Applet-Viewer steht z.B. das im JDK enthaltene Programm appletviewer zur Verfügung.<br />
◇ E<strong>in</strong> Applet besitzt immer e<strong>in</strong>e graphische Benutzeroberfläche.<br />
Das diese Oberfläche bereitstellende Top-Level-Fenster ist aber nicht eigenständig, sondern bef<strong>in</strong>det sich <strong>in</strong>nerhalb<br />
des Browser-Fensters.<br />
◇ Üblicherweise bef<strong>in</strong>det sich der Applet-Code auf e<strong>in</strong>em Server. Er kann nur aus e<strong>in</strong>er HTML-Seite heraus gestartet<br />
werden. Hierfür muß die Start-Klasse des Applets durch e<strong>in</strong> -Tag <strong>in</strong> der HTML-Seite referiert werden..<br />
◇ Stößt der Browser (bzw. der Applet-Viewer) bei der Interpretation der HTML-Seite auf e<strong>in</strong> -Tag, so<br />
startet er se<strong>in</strong>e – direkt <strong>in</strong>tegrierte oder als Plug-In e<strong>in</strong>gebundene – e<strong>in</strong>e JVM enthaltene <strong>Java</strong>-Laufzeit-Umgebung<br />
(JRE – <strong>Java</strong> Runtime Environment). Diese lädt die Start-Klasse vom Server, <strong>in</strong>stanziert sie und beg<strong>in</strong>nt die Abarbei-<br />
tung ihres Codes durch den Aufruf spezieller Methoden.<br />
◇ Die Funktionalität e<strong>in</strong>es als Applet realisierten <strong>Java</strong>-Programms ist nicht auf die Start-Klasse begrenzt. Ausgehend<br />
von der Start-Klasse können – wie bei e<strong>in</strong>em <strong>Java</strong>-Applikations-Programm – weitere Klassen geladen und <strong>in</strong>stanziert<br />
werden.<br />
Trotzdem bezieht man den Begriff Applet häufig nur auf die Start-Klasse bzw auf das von ihr im Browser <strong>in</strong>stan-<br />
zierte Objekt.<br />
• Die Klassen Applet und JApplet<br />
◇ Die Start-Klasse e<strong>in</strong>es Applets muß von der Klasse Applet (Package java.applet) abgeleitet se<strong>in</strong>.<br />
Diese Klasse ist ihrerseits über die Klasse Panel von der Klasse Conta<strong>in</strong>er abgeleitet. Sie verfügt daher über<br />
die allen AWT-Komponenten- und Conta<strong>in</strong>er-Klassen geme<strong>in</strong>samen Fähigkeiten zum Aufbau graphischer Ober-<br />
flächen (e<strong>in</strong>schliesslich des Event-Handl<strong>in</strong>g-Mechanismus für Benutzere<strong>in</strong>gaben). Die Klasse Applet selbst ergänzt<br />
diese durch die besonderen Fähigkeiten und Funktionalitäten, die für Applets benötigt werden.<br />
Das von der Browser-JVM <strong>in</strong>stanzierte Objekt der Applet-Start-Klasse bildet e<strong>in</strong>en Conta<strong>in</strong>er, <strong>in</strong> den AWT-GUI-<br />
Komponenten e<strong>in</strong>gefügt werden können. Defaultmässig besitzt dieser Conta<strong>in</strong>er e<strong>in</strong> BorderLayout.<br />
◇ Wenn die vom Applet dargebotene Benutzeroberfläche aus Sw<strong>in</strong>g-GUI-Komponenten bestehen soll, muß se<strong>in</strong>e Start-<br />
Klasse von der Klasse JApplet (Package javax.sw<strong>in</strong>g) abgeleitet se<strong>in</strong>.<br />
Diese ist selbst direkt von der Klasse Applet abgeleitet und ergänzt diese um die besonderen Fähigkeiten und<br />
Eigenschaften des Sw<strong>in</strong>g-Frameworks.<br />
Das von der Browser-JVM <strong>in</strong>stanzierte Objekt e<strong>in</strong>er von JApplet abgeleiteten Start-Klasse bildet somit e<strong>in</strong>en<br />
Conta<strong>in</strong>er für Sw<strong>in</strong>g-GUI-Komponenten. Dieser besitzt – wie e<strong>in</strong> JFrame-Conta<strong>in</strong>er – e<strong>in</strong>e Content Pane, <strong>in</strong> die<br />
Komponenten e<strong>in</strong>zufügen s<strong>in</strong>d. Defaultmässig besitzt die Content Pane e<strong>in</strong> BorderLayout.<br />
• Wesentliche Unterschiede zwischen Applets und Applikationsprogrammen<br />
Applet Applikationsprogramm<br />
Start-Klasse von Applet bzw JApplet abgeleitet beliebige Klasse,<br />
ke<strong>in</strong>e ma<strong>in</strong>()-Methode statische ma<strong>in</strong>()-Methode<br />
Programmstart Laden Start-Klasse <strong>in</strong> Browser-JVM, Laden Start-Klasse <strong>in</strong> JVM,<br />
Instanzierung, Aufruf spezieller API-Methoden Aufruf von deren ma<strong>in</strong>()-Methode<br />
Benutzerschnittstelle graphisch Konsole oder graphisch<br />
Zugriff zum lokalen durch Security-Manager <strong>in</strong> Browser-JVM Lesen, Schreiben, Ausführen von<br />
Dateisystem i.a. verh<strong>in</strong>dert (Lesen, Schreiben, Ausführen) Dateien i.a. zulässig
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 612 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (2)<br />
• Demonstrationsbeispiel e<strong>in</strong>es sehr e<strong>in</strong>fachen Applets<br />
◇ Applet-Code (Datei HelloWorldApplet.java)<br />
import java.applet.Applet;<br />
import java.awt.Graphics;<br />
public class HelloWorldApplet extends Applet<br />
{<br />
public void pa<strong>in</strong>t(Graphics g)<br />
{ super.pa<strong>in</strong>t(g);<br />
g.drawStr<strong>in</strong>g("This Applet just says : \"Hello world !\"", 70, 25);<br />
}<br />
}<br />
◇ E<strong>in</strong>bettende HTML-Datei (HelloWorldApplet.html)<br />
<br />
<br />
A Simple Applet <br />
<br />
<br />
<br />
E<strong>in</strong> sehr e<strong>in</strong>faches Applet :<br />
<br />
<br />
<br />
<br />
<br />
◇ Darstellung des Applets im Browser<br />
◇ Darstellung des Applets durch :<br />
appletviewer<br />
HelloWorldApplet.html
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 613 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Der Lebenszyklus e<strong>in</strong>es Applets<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (3)<br />
◇ E<strong>in</strong> Applet durchläuft während se<strong>in</strong>er Lebensdauer mehrere Zustände :<br />
no-arg-Konstruktor<br />
<strong>in</strong>it() start()<br />
<strong>in</strong>stanziert <strong>in</strong>itialisiert<br />
gestartet<br />
stop() start()<br />
angehalten<br />
pa<strong>in</strong>t()<br />
destroy()<br />
zerstört<br />
◇ Zur Instanzierung e<strong>in</strong>es Applets (genauer : e<strong>in</strong>es Objekts der Applet-Start-Klasse) wird von der JRE des Browsers/<br />
Applet-Viewers der no-arg-Konstruktor der Applet-Start-Klasse aufgerufen.<br />
Normalerweise wird für diese e<strong>in</strong> derartiger Konstruktor nicht explizit def<strong>in</strong>iert, stattdessen wird der Default-nor-arg-<br />
Konstruktor verwendet. Dieser ruft lediglich den no-arg-Konstruktor der Basisklasse (Applet oder JApplet)<br />
auf. Applets werden also üblicherweise durch ihren Konstruktor nicht <strong>in</strong>itialisiert.<br />
◇ Der Übergang zwischen den verschiedenen Applet-Zuständen wird durch spezielle Memberfunktionen der Klasse<br />
Applet, die <strong>in</strong> der Applet-Start-Klasse gegebenenfalls geeignet überschrieben werden müssen, begleitet.<br />
Diese Memberfunktionen werden durch die JRE des Browsers/Applet-Viewers automatisch <strong>in</strong> verschiedenen Situati-<br />
onen aufgerufen. Nach ihrer Ausführung bef<strong>in</strong>det sich das Applet im jeweils neuen Zustand.<br />
◇ Unmittelbar nach der erfolgreichen Instanzierung e<strong>in</strong>es Objekts der Applet-Start-Klasse wird dessen Methode <strong>in</strong>it()<br />
aufgerufen. Diese dient zur Initialisierung des Applets und überführt es somit <strong>in</strong> den Zustand "<strong>in</strong>itialisiert"<br />
In ihr werden Anweisungen ausgeführt, die normalerweise <strong>in</strong> Konstruktoren enthalten s<strong>in</strong>d, also nur e<strong>in</strong>mal während<br />
der Lebensdauer e<strong>in</strong>es Applets ausgeführt werden sollen. Typischerweise werden durch diese Methode Datenkompo-<br />
nenten <strong>in</strong>itialisiert, die vom Applet dargestellte graphische Oberfläche aufgebaut sowie sonstige dauernd benötigte<br />
Resourcen alloziert.<br />
◇ Nach se<strong>in</strong>er erfolgreichen Initialisierung gelangt das Applet durch Aufruf der Methode start() <strong>in</strong> den Zustand<br />
"gestartet" (aktiv).<br />
Diese Methode wird auch immer dann aufgerufen, wenn das im Zustand "angehalten" bef<strong>in</strong>dliche Applet erneut<br />
aktiviert wird. Dies kann z.B. dann der Fall se<strong>in</strong>, wenn die HTML-Seite, <strong>in</strong> die das Applet e<strong>in</strong>gebettet ist, nach dem<br />
kurzzeitigen Laden e<strong>in</strong>er anderen Seite erneut angezeigt wird oder das Browser/Applet-Viewer-Fenster nach vorüber-<br />
gehender Ikonifizierung wieder voll dargestellt wird.<br />
Grundsätzlich kann e<strong>in</strong> Applet also während se<strong>in</strong>er Lebensdauer mehrmals zwischen den Zuständen "gestartet" und<br />
angehalten" wechseln.<br />
Allerd<strong>in</strong>gs verhalten sich viele Browser <strong>in</strong> derartigen Situation anders : Im ersten Fall vernichten sie das Applet und<br />
<strong>in</strong>stanzieren es erneut. Im zweiten Fall verbleibt das Applet auch während der Ikonifizierung im Zustand "gestartet".<br />
In der Methode start() sollten alle Aktionen gestartet werden, die zur Ausführung des Applets notwendig s<strong>in</strong>d<br />
(z.B. Erzeugung und Start von Animations-Threads, Allokation von nur temporär benötigten Resourcen usw)<br />
◇ Die Methode stop() überführt das Applet <strong>in</strong> den Zustand "angehalten" (<strong>in</strong>aktiv). Sie wird unmittelbar vor der Zer-<br />
störung e<strong>in</strong>es Applets aufgerufen. Ausserdem kann sie immer dann aufgerufen werden, wenn das Applet vorübergehend<br />
nicht dargestellt wird (Laden e<strong>in</strong>er anderen HTML-Seite, Ikonifizierung des Browser-Fensters, s. oben).<br />
Die <strong>in</strong> der Methode start() begonnenen Aktionen und vorgenommenen Allokationen sollen <strong>in</strong> der Methode<br />
stop() wieder angehalten bzw freigegeben werden ( Verh<strong>in</strong>derung unnötigen Resourcenverbrauchs)<br />
◇ Die Methode destroy() wird aufgerufen, wenn das Applet mit Sicherheit nicht mehr benötigt wird. Es gelangt <strong>in</strong><br />
den Zustand "zerstört". Danach wird es endgültig beseitigt (aus dem Browser und dem Speicher entfernt).<br />
In dieser Methode sollten die <strong>in</strong> der <strong>in</strong>it()-Methode durchgeführten Allokationen – soweit notwendig – wieder<br />
aufgehoben werden ( Funktionalität e<strong>in</strong>es Destruktors !).<br />
◇ Die Standard-Implementierung der vier Lebenszyklus-Methoden (methods for milestones) <strong>in</strong> der Klasse Applet<br />
enthält e<strong>in</strong>en leeren Funktionsrumpf.<br />
Bei Bedarf müssen sie <strong>in</strong> e<strong>in</strong>er Applet-Start-Klasse geeignet überschrieben werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 614 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Die Methode pa<strong>in</strong>t()<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (4)<br />
◇ Die Klasse Applet erbt von der Klasse Conta<strong>in</strong>er (Package java.awt) u.a. die Methode<br />
public void pa<strong>in</strong>t(Graphics g)<br />
◇ Diese Methode wird vom JRE des Browsers/Applet-Viewers immer dann aufgerufen, wenn das Applet-Fenster neu<br />
gezeichnet werden muß.<br />
Dies ist z.B. immer dann der Fall,<br />
- wenn das Browser/Applet-Viewer-Fenster und damit das e<strong>in</strong>gebettete Applet-Fenster zum ersten Mal dargestellt<br />
wird (Aufruf von pa<strong>in</strong>t() nach start())<br />
- wenn das Browser/Applet-Viewer-Fenster wegen e<strong>in</strong>er Größenänderung neu gezeichnet wird<br />
- wenn das Applet-Fenster durch andere Fenster überdeckt war und wieder sichtbar wird<br />
- wenn im Applet-Code durch den Aufruf von repa<strong>in</strong>t() e<strong>in</strong> Neuzeichnen veranlasst wird.<br />
◇ Die Methode wird häufig <strong>in</strong> Applet-Start-Klassen überschrieben, um gezielt bestimmte Graphik-Ausgaben(e<strong>in</strong>schliess-<br />
lich Text) direkt <strong>in</strong> das Applet-Fenster vorzunehmen.<br />
(z.B. g.drawStr<strong>in</strong>g("Hallo") statt E<strong>in</strong>fügen e<strong>in</strong>er Label-(bzw JLabel-)Komponente mit dem Text<br />
"Hallo" <strong>in</strong> das Applet-Objekt)<br />
Um e<strong>in</strong>e e<strong>in</strong>wandfreie Funktion sicherzustellen sollte die überschreibende pa<strong>in</strong>t()-Funktion als erstes die von<br />
Conta<strong>in</strong>er geerbte pa<strong>in</strong>t()-Funktion aufrufen ( erste Anweisung : super.pa<strong>in</strong>t(g))<br />
• Anmerkungen zum Erstellen / Testen von Applets<br />
◇ Während ihrer Entwicklung sollten Applets grundsätzlich mit dem JDK-Programm appletviewer getestet<br />
werden.<br />
Bei diesem Programm ist sichergestellt, dass die HTML-Seite und damit das auszuführende Applet bei jedem Aufruf<br />
neu geladen wird. Damit wird immer die neueste Version des Applets ausgeführt.<br />
◇ Browser dagegen speichern den e<strong>in</strong>mal geladenen Code e<strong>in</strong>es Applets im Arbeitsspeicher und besitzen darüberh<strong>in</strong>aus<br />
e<strong>in</strong>en Seiten-Cache.<br />
Dadurch wird nach Änderung des Quellcodes e<strong>in</strong>es Applets und se<strong>in</strong>er Neu-Übersetzung gegebenenfalls nicht die da-<br />
durch neu entstandene Version des Applets sondern die im Arbeitsspeicher bzw Cache vorhandene alte Version ausge-<br />
führt.<br />
Selbst das Neuladen der HTML-Seite aktualisiert nicht das im Arbeitssspeicher vorhandene Applet.<br />
◇ Das Programm appletviewer stellt allerd<strong>in</strong>gs nur das Applet und nicht die übrigen Elemente der HTML-Seite dar.<br />
• Vere<strong>in</strong>igung von Applet und Applikations-Programm<br />
◇ Es ist möglich, <strong>Java</strong>-Programme zu erstellen, die sowohl als Applet als auch als Applikations-Programm gestartet<br />
werden können.<br />
◇ Um dies zu realisieren, muß die Start-Klasse<br />
▻ sowohl von der Klasse Applet abgeleitet se<strong>in</strong> und gegebenenfalls die Lebenszyklus-Methoden implementieren<br />
▻ als auch e<strong>in</strong>e geeignete ma<strong>in</strong>()-Methode def<strong>in</strong>ieren<br />
◇ Damit das Applet und das Applikations-Programm die gleiche GUI besitzen, sollte der Aufbau derselben <strong>in</strong> e<strong>in</strong>er<br />
eigenen Memberfunktion implementiert se<strong>in</strong>, die sowohl von der <strong>in</strong>it()-funktion als auch der ma<strong>in</strong>()-Funktion<br />
(bzw gegebenenfalls auch von e<strong>in</strong>em geeigneten Konstruktor) aufgerufen werden kann.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 615 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (5-1)<br />
• Demonstrationsbeispiel zum Lebenszyklus e<strong>in</strong>es Applets<br />
◇ Applet-Code (Datei LifeCycleDemo.java)<br />
// LifeCycleDemo.java<br />
import java.applet.Applet;<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class LifeCycleDemo extends JApplet<br />
{ JLabel <strong>in</strong>fo;<br />
}<br />
public LifeCycleDemo() // i.a. nicht ueblich, nur fuer Demo-Zwecke<br />
{ super();<br />
System.out.pr<strong>in</strong>tln("construct<strong>in</strong>g ... ");<br />
}<br />
public void <strong>in</strong>it()<br />
{ <strong>in</strong>fo = new JLabel("Demo des Applet Lifecycles", Sw<strong>in</strong>gConstants.CENTER);<br />
<strong>in</strong>fo.setBackground(Color.YELLOW);<br />
<strong>in</strong>fo.setOpaque(true);<br />
getContentPane().add(<strong>in</strong>fo);<br />
System.out.pr<strong>in</strong>tln("<strong>in</strong>itializ<strong>in</strong>g... ");<br />
}<br />
public void start()<br />
{ System.out.pr<strong>in</strong>tln("start<strong>in</strong>g... ");<br />
}<br />
public void stop()<br />
{ System.out.pr<strong>in</strong>tln("stopp<strong>in</strong>g... ");<br />
}<br />
public void destroy()<br />
{ System.out.pr<strong>in</strong>tln("destroy<strong>in</strong>g...");<br />
}<br />
public void pa<strong>in</strong>t(Graphics g)<br />
{ super.pa<strong>in</strong>t(g);<br />
System.out.pr<strong>in</strong>tln("pa<strong>in</strong>t<strong>in</strong>g ...");<br />
//Zeichnen e<strong>in</strong>es Rechtecks um Fensterflaeche des Applets.<br />
g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);<br />
}<br />
◇ E<strong>in</strong>bettende HTML-Datei (LifeCycleDemo.html)<br />
<br />
<br />
A Simple Aplet <br />
<br />
<br />
<br />
<br />
<br />
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 615 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (5-2)<br />
• Demonstrationsbeispiel zum Lebenszyklus e<strong>in</strong>es Applets, Forts.<br />
◇ Darstellung des Applets durch : appletviewer LifeCycleDemo.html<br />
◇ Beispiel zur Konsolenausgabe<br />
Ausführung folgender Aktionen<br />
- Start des Applets im Appletviewer<br />
- Vergrösserung des Applet-Viewer-Fensters <strong>in</strong> der Breite ( e<strong>in</strong>maliger Aufruf von pa<strong>in</strong>t())<br />
- Vergrösserung des Applet-Viewer-Fensters <strong>in</strong> der Höhe ( e<strong>in</strong>maliger Aufruf von pa<strong>in</strong>t())<br />
- Ikonifizierung des Applet-Viewer-Fensters<br />
- Herstellung der Normalgroesse des Applet-Viewer-Fensters<br />
- Verkle<strong>in</strong>erung des Applet-Viewer-Fensters <strong>in</strong> der Breite ( zweimaliger Aufruf von pa<strong>in</strong>t())<br />
- Schliessen des Applet-Viewer-Fensters<br />
E:\<strong>Java</strong>\fhm\ee\vorl\applets>appletviewer LifeCycleDemo.html<br />
construct<strong>in</strong>g ...<br />
<strong>in</strong>itializ<strong>in</strong>g...<br />
start<strong>in</strong>g...<br />
pa<strong>in</strong>t<strong>in</strong>g ...<br />
pa<strong>in</strong>t<strong>in</strong>g ...<br />
pa<strong>in</strong>t<strong>in</strong>g ...<br />
stopp<strong>in</strong>g...<br />
start<strong>in</strong>g...<br />
pa<strong>in</strong>t<strong>in</strong>g ...<br />
pa<strong>in</strong>t<strong>in</strong>g ...<br />
pa<strong>in</strong>t<strong>in</strong>g ...<br />
stopp<strong>in</strong>g...<br />
destroy<strong>in</strong>g...<br />
E:\<strong>Java</strong>\fhm\ee\vorl\applets>
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 616 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (6-1)<br />
• Demonstrationsbeispiel zur Vere<strong>in</strong>igung von Applet und Applikations-Programm<br />
◇ Applet-Code (Datei AppletAndAppliDemo.java)<br />
// AppletAndAppliDemo.java<br />
import java.applet.*;<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class AppletAndAppliDemo extends JApplet<br />
{<br />
Str<strong>in</strong>g progType="Application";<br />
JLabel lab;<br />
}<br />
public void <strong>in</strong>it()<br />
{<br />
progType="Applet";<br />
setContentPane(buildGUI());<br />
}<br />
private Conta<strong>in</strong>er buildGUI()<br />
{<br />
JPanel pan=new JPanel();<br />
lab=new JLabel("gestartet als " + progType, Sw<strong>in</strong>gConstants.CENTER);<br />
lab.setBackground(Color.YELLOW);<br />
lab.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));<br />
lab.setOpaque(true);<br />
pan.add(lab);<br />
return pan;<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
AppletAndAppliDemo app = new AppletAndAppliDemo();<br />
JFrame frame = new JFrame("AppletAndAppliDemo");<br />
frame.setContentPane(app.buildGUI());<br />
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
frame.setSize(330, 150);<br />
frame.setVisible(true);<br />
}<br />
◇ E<strong>in</strong>bettende HTML-Datei (AppletAndAppliDemo.html)<br />
<br />
<br />
AppletAndAppliDemo<br />
<br />
<br />
<br />
<br />
<br />
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 616 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Aufbau und Funktionsweise von <strong>Java</strong>-Applets (6-2)<br />
• Demonstrationsbeispiel zur Vere<strong>in</strong>igung von Applet und Applikations-Programm, Forts.<br />
◇ Start als Applet mittels : appletviewer AppletAndAppliDemo.html<br />
◇ Start als Applikations-Programm mittels : java AppletAndAppliDemo
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 621 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• M<strong>in</strong>imalform des -Tags<br />
HTML--Tag (1)<br />
◇ Vorbemerkung : In der HTML-Syntax wird nicht zwischen Groß- und Kle<strong>in</strong>-Buchstaben unterscheiden.<br />
◇ Das zur Referenzierung e<strong>in</strong>es Applets (genauer : der Applet-Start-Klasse) <strong>in</strong> e<strong>in</strong>er HTML-Seite benötigte -<br />
Tag besitzt Attribute. Diese dienen zur Festlegung bestimmter Eigenschaften des Applets.<br />
◇ In se<strong>in</strong>er M<strong>in</strong>imalform muß das - Tag den Namen der Applet-Start-Klasse sowie die Größe (Breite und<br />
Höhe) des Applet-Fensters festlegen.<br />
Damit muß es wenigstens die folgenden drei Attribute def<strong>in</strong>ieren :<br />
▻ code : Date<strong>in</strong>ame der Bytecode-Datei der Applet-Start-Klasse. Die Extension .class kann weggelassen<br />
werden. Die Angabe e<strong>in</strong>es auch Directory-Angaben enthaltenen Dateipfades ist nicht zulässig.<br />
Der Date<strong>in</strong>ame wird relativ zur Codebase-URL der Applet-Start-Klasse ausgewertet.<br />
Ohne explizite Festlegung (Attribut codebase) ist diese Codebase-URL gleich der Directory-URL<br />
der HTML-Datei, d.h. Applet-Bytecode-Datei und HTML-Datei müssen sich im gleichen Verzeichnis<br />
bef<strong>in</strong>den.<br />
▻ width : Breite des Applet-Fensters <strong>in</strong> Pixel<br />
▻ height : Höhe des Applet-Fensters <strong>in</strong> Pixel<br />
◇ Beispiel : <br />
<br />
• Allgeme<strong>in</strong>e Form des -Tags<br />
◇ Die Werte der Attribute des -Tags werden als Str<strong>in</strong>gs <strong>in</strong>terpretiert.<br />
Sie können mit oder ohne Str<strong>in</strong>g-Quotes (doppelte Hochkommata) angegeben werden.<br />
◇ Die M<strong>in</strong>imalform des -Tags kann optional ergänzt werden um<br />
▻ weitere Attribute<br />
▻ Parameter, die an das Applet übergeben werden<br />
▻ alternativen HTML-Code, der von Browsern, die das -Tag nicht verstehen, <strong>in</strong>terpretiert wird<br />
◇ Allgeme<strong>in</strong>e Form des -Tags (Die eckigen Klammern [...] kennzeichnen optionale Angaben) :<br />
<br />
[]<br />
[]<br />
. . .<br />
[alternateHTML]<br />
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 622 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Optionale Attribute des -Tags<br />
HTML--Tag (2)<br />
◇ Die folgenden -Tag-Attribute s<strong>in</strong>d optional :<br />
▻ codebase : URL des Verzeichnisses, <strong>in</strong> dem sich die Bytecode-Datei der Applet-Start-Klasse bzw die <strong>Java</strong>-<br />
Archiv-Datei (s. unten) bef<strong>in</strong>det.<br />
Die Angabe kann absolut oder relativ zur Directory-URL der HTML-Datei erfolgen<br />
Diese Angabe ist notwendig, wenn die Codebase-URL von der Directory-URL der HTML-Datei<br />
abweicht, also Applet-Bytecode-Datei und HTML-Datei sich <strong>in</strong> verschiedenen Verzeichnissen<br />
bef<strong>in</strong>den.<br />
▻ archive : Date<strong>in</strong>ame e<strong>in</strong>er <strong>Java</strong>-Archiv-Datei (Extension .jar), <strong>in</strong> der die Applet-Start-Klasse sowie<br />
weitere von dieser verwendete Klassen zusammengefasst s<strong>in</strong>d.<br />
Der Date<strong>in</strong>ame wird relativ zur Codebase-URL ausgewertet.<br />
▻ alt : Alternativer Text, der dargestellt wird, wenn der Browser zwar das -Tag versteht,<br />
aber ke<strong>in</strong>e <strong>Java</strong>-Applets ausführen kann<br />
▻ name : Name der Applet-Instanz (genauer : Instanz der Applet-Start-Klasse).<br />
Dieser Name ermöglicht es, dass sich mehrere Applets auf der gleichen HTML-Seite gegenseitig<br />
lokalisieren und mite<strong>in</strong>ander kommunizieren können.<br />
▻ align : Ausrichtung des Applets gegenüber dem umgebenden Text (Wirkung wie beim -Tag)<br />
Zulässige Werte : midddle, top, bottom, left, right, texttop, absmiddle,<br />
basel<strong>in</strong>e, absbottom<br />
▻ hspace : Horizontaler Abstand (l<strong>in</strong>ks und rechts) des Applet-Fensters zu den umgebenden Elementen auf der<br />
HTML-Seite <strong>in</strong> Pixel<br />
▻ vspace : Vertikaler Abstand (oben und unten) des Applet-Fensters zu den umgebenden Elementen auf der<br />
HTML-Seite <strong>in</strong> Pixel<br />
• Parameter <strong>in</strong> -Tags<br />
◇ Zwischen den Tag-Begrenzungen und können auch Parameter angegeben werden, die<br />
von der HTML-Seite an das Applet (genauer : die Instanz der Applet-Start-Klasse) übergeben werden.<br />
◇ Name und Wert e<strong>in</strong>es Parameters s<strong>in</strong>d als Attribut-Werte e<strong>in</strong>es -Tags festzulegen.<br />
Sowohl der Name als auch der Wert des Parameters s<strong>in</strong>d jeweils als Str<strong>in</strong>g anzugeben :<br />
<br />
◇ Es können beliebig viele Parameter angegeben werden.<br />
◇ In der Klasse Applet existieren Memberfunktionen, mit denen Applets zu diesen Parametern zugreifen können.<br />
• Alternativer HTML-Code<br />
◇ alternateHTML<br />
Steht für alternativen HTML-Code, der für Browser, die das -Tag nicht verstehen, vorgesehen ist.<br />
Er ist zwischen den Tag-Begrenzungen und anzugeben.<br />
Typischerweise kann hier alternativ auszugebender Text oder e<strong>in</strong> L<strong>in</strong>k zu e<strong>in</strong>er alternativ anzuzeigenden Seite ange-<br />
geben werden.<br />
◇ Von Browsern, die das -Tag verstehen, wird dieser Code ignoriert.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 631 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
<strong>Java</strong>-Applet-API (1)<br />
◇ Das <strong>Java</strong>-Applet-API wird im wesentlichen durch die Klasse Applet und das Interface AppletContext<br />
implementiert (beide s<strong>in</strong>d im Package java.applet enthalten).<br />
Auf der Basis der engen Beziehung, die zwischen Applets und den sie ausführenden Web-Browsern besteht, stellen<br />
sie die folgenden Applet-Fähigkeiten zur Verfügung :<br />
∙ Annahme verschiedener Lebenszyklus-Zustände ("milestones")<br />
∙ Zugriff zu im -Tag enthaltenen Parametern<br />
∙ E<strong>in</strong>b<strong>in</strong>den von Graphiken, die <strong>in</strong> Dateien abgelegt s<strong>in</strong>d<br />
∙ Abspielen von Audio- (Sound-)Dateien<br />
∙ Ausgabe von Informationen <strong>in</strong> der Statuszeile des Browsers<br />
∙ Darstellung e<strong>in</strong>es neuen HTML-Dokuments im Browser<br />
∙ Kommunikation mit anderen Applets auf derselben HTML-Seite<br />
• Das Interface AppletContext<br />
◇ Das Interface AppletContext stellt dem Applet e<strong>in</strong>en Zugang zu se<strong>in</strong>er Umgebung (der das Applet enthaltenen<br />
HTML-Seite und den anderen Applets auf dieser Seite) zur Verfügung. Es wird durch die JRE des Browsers/Applet-<br />
Viewers implementiert.<br />
◇ Mittels der Methode getAppletContext() kann e<strong>in</strong> Applet se<strong>in</strong> AppletContext-"Objekt" ermitteln.<br />
Über dieses kann das Applet mit se<strong>in</strong>er Umgebung kommunizieren.<br />
◇ Methoden des Interfaces (Auszug)<br />
public Image getImage(URL url) Erzeugung e<strong>in</strong>es Image-Objekts, das die durch die<br />
absolute URL url referierte Bild-Datei repräsentiert<br />
public AudioClip getAudioClip(URL url) Erzeugung e<strong>in</strong>es AudioClip-Objekts, das die durch die<br />
absolute URL url referierte Audio-Datei repräsentiert<br />
public void showStatus(Str<strong>in</strong>g msg) Ausgabe des Str<strong>in</strong>gs msg <strong>in</strong> die Statuszeile des Browsers<br />
public void showDocument(URL url) Ersatz der aktuell dargestellten HTML-Seite durch den Inhalt<br />
der durch die absolute URL url referierten HTML-Datei<br />
(darf von e<strong>in</strong>em Applet-Viewer ignoriert werden)<br />
public void showDocument(URL url, Darstellung des Inhalts der durch die absolute URL url re-<br />
Str<strong>in</strong>g tgt) referierten HTML-Datei <strong>in</strong> dem durch tgt bezeichneten<br />
Browser-Frame<br />
(darf von e<strong>in</strong>em Browser / Applet-Viewer ignoriert werden)<br />
public Applet getApplet(Str<strong>in</strong>g name) Ermittlung der Instanz des Applets mit dem Namen name<br />
Dabei ist name der Wert des name-Attributs im<br />
-Tag<br />
public Enumeration getApplets() Ermittlung aller Applet-Instanzen <strong>in</strong> der aktuellen HTML-<br />
Seite, e<strong>in</strong>schliesslich des Applets, das diese Methode für<br />
se<strong>in</strong>en AppletContext aufruft<br />
◇ Für e<strong>in</strong>ige dieser Methoden stehen gleichnamige Methoden <strong>in</strong> der Klasse Applet zur Verfügung, die jeweils mittels<br />
getAppletContext() das zugehörige AppletContext-"Objekt" ermitteln und dann für dieses die entspre-<br />
chende AppletContext-Methode aufrufen.<br />
In e<strong>in</strong>em derartigen Fall kann der Applet-Programmierer also auf den expliziten Aufruf von getAppletContext()<br />
verzichten und direkt die jeweilige Applet-Methode aufrufen
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 632 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong>-Applet-API (2)<br />
• Memberfunktionen der Klasse Applet (auszugsweiser Überblick)<br />
◇ Lebenszyklus-Methoden : Aufruf durch JRE des Browsers, Implementierung <strong>in</strong> der Klasse Applet tut nichts,<br />
Bei Bedarf müssen sie <strong>in</strong> abgeleiteten Klassen geeignet überschrieben werden<br />
public void <strong>in</strong>it() Aufruf beim erstmaligen Laden des Applets, dient zur Initialisierung des Applets<br />
public void start() Aufruf beim (Wieder-)Beg<strong>in</strong>n der Applet-Abarbeitung<br />
public void stop() Aufruf beim (vorübergehenden) Anhalten der Applet-Abarbeitung<br />
public void destroy() Aufruf, wenn das Applet zerstört wird, dient zur Freigabe allozierter Resourcen<br />
◇ e<strong>in</strong>ige weitere Methoden :<br />
public Str<strong>in</strong>g getAppletInfo() Rückgabe von Informationen über das Applet<br />
Die Implementierung <strong>in</strong> Applet liefert null.<br />
Die Methode sollte <strong>in</strong> abgeleiteten Klassen geeignet über-<br />
schrieben werden (Autor, Version, Copyright)<br />
public AppletContext getAppletContext() Ermittlung des AppletContext-"Objekts"<br />
public URL getCodeBase() Ermittlung der URL des Directories, das die Datei mit<br />
dem Applet-Code enthält<br />
public URL getDocumentBase() Ermittlung der URL der HTML-Datei, <strong>in</strong> die das Applet<br />
e<strong>in</strong>gebettet ist.<br />
public Str<strong>in</strong>g[][] getParameterInfo() Rückgabe von Informationen über die Parameter, die das<br />
Applet "verstehen" kann<br />
Die Implementierung <strong>in</strong> Applet liefert null.<br />
Die Methode sollte <strong>in</strong> abgeleiteten Klassen geeignet über-<br />
schrieben werden (s. <strong>Java</strong>-API-Dokumentation)<br />
public Str<strong>in</strong>g getParameter(Str<strong>in</strong>g name) Ermittlung des Werts des Parameters bzw -Tag-<br />
Attributs mit dem Namen name<br />
public Image getImage(URL url) Rückgabe e<strong>in</strong>es Image-Objekts, das die durch die<br />
absolute URL url referierte Bild-Datei repräsentiert<br />
public Image getImage(URL base, Rückgabe e<strong>in</strong>es Image-Objekts, das die Bild-Datei<br />
Str<strong>in</strong>g rel) repräsentiert, die durch die absolute Basis-URL base und<br />
den hierzu relativen Pfad rel referiert wird<br />
public AudioClip getAudioClip(URL url) Rückgabe e<strong>in</strong>es AudioClip-Objekts, das die durch die<br />
absolute URL url referierte Audio-Datei repräsentiert<br />
public AudioClip getAudioClip(URL base, Rückgabe e<strong>in</strong>es AudioClip-Objekts, das die Audio-Datei<br />
Str<strong>in</strong>g rel) repräsentiert, die durch die absolute Basis-URL base und<br />
den hierzu relativen Pfad rel referiert wird<br />
public void play(URL url) Abspielen der durch url referierten Audio-Datei<br />
public void play(URL base, Str<strong>in</strong>g rel) Abspielen der durch die Basis-URL url und den hierzu<br />
relativen Pfad rel referierten Audio-Datei<br />
public void showStatus(Str<strong>in</strong>g msg) Ausgabe des Str<strong>in</strong>gs msg <strong>in</strong> die Statuszeile des Browsers<br />
public static f<strong>in</strong>al AudioClip newAudioClip(URL url) (ermöglicht Sound <strong>in</strong> Applikations-Progr.)<br />
Rückgabe e<strong>in</strong>es AudioClip-Objekts, das die durch die absolute URL url referierte Audio-Datei repräsentiert
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 633 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Zugriff zu Applet- Parametern<br />
<strong>Java</strong>-Applet-API (3)<br />
◇ Von der HTML-Seite, <strong>in</strong> die e<strong>in</strong> Applet e<strong>in</strong>gebettet ist, lassen sich Parameter an das Applet übergeben, die – analog zu<br />
Kommandozeilen-Parametern von Applikations-Programmen – die Konfigurierung und Steuerung der Arbeitsweise des<br />
Applets ermöglichen ( Applet-Parameter).<br />
◇ Applet-Parameter s<strong>in</strong>d im -Tag mit ihrem Namen und Wert anzugeben :<br />
<br />
Sowohl der Name (name) als auch der Wert (value) werden – unabhängig davon, ob sie <strong>in</strong> doppelte Hochkommata<br />
gesetzt werden oder nicht – als Str<strong>in</strong>gs <strong>in</strong>terpretiert<br />
Dabei werden beim Namen Groß- und Kle<strong>in</strong>-Buchstaben als gleich betrachtet (case-<strong>in</strong>sensitive), während der Wert<br />
dagegen case-sensitive ist.<br />
Werden durch die Str<strong>in</strong>gs Werte anderer Datentypen dargestellt (z.B. numerische Werte), müssen sie vor ihrer Verwen-<br />
dung erst entsprechend konvertiert werden.<br />
◇ Innerhalb des Applet-Codes kann (typischerweise <strong>in</strong> der <strong>in</strong>it()-Methode) der Wert e<strong>in</strong>es durch se<strong>in</strong>en Namen<br />
name spezifizierten Parameters ermittelt werden mittels der Methode<br />
public Str<strong>in</strong>g getParameter(Str<strong>in</strong>g name)<br />
Für e<strong>in</strong>en im -Tag nicht gesetzten Parameter liefert die Methode den Wert null.<br />
Mit dieser Methode lassen sich auch die Werte der -Tag-Attribute ermitteln (name == Attribut-Name)<br />
◇ Beispiele typischer Kandidaten für Applet-Parameter s<strong>in</strong>d<br />
- Name und Ort von zu verwendenden Resource-Dateien (z.B. Bild- oder Ton-Dateien)<br />
- Werte, die die Ersche<strong>in</strong>ung des Applets bee<strong>in</strong>flussen (darzustellender Text, Schrift-Stil und -Größe, Anzahl der Bild-<br />
wechsel pro sec bei annimierten Applets usw)<br />
- Größe darzustellender Fenster usw<br />
◇ Defaultwerte für Applet-Parameter<br />
Für alle von e<strong>in</strong>em Applet verwendeten Parameter sollten im Applet-Code s<strong>in</strong>nvolle Defaultwerte vorgesehen werden.<br />
Damit kann e<strong>in</strong>e e<strong>in</strong>wandfreie Funktion des Applets auch dann sichergestellt werden, wenn bestimmte Parameter nicht<br />
durch das -Tag bereitgestellt werden.<br />
◇ Beispiel :<br />
...<br />
<br />
...<br />
<br />
...<br />
<br />
...<br />
public class AppletAPIDemo1 extends JApplet<br />
{<br />
// ...<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_SOUNDPATH = "sounds/bark.au";<br />
// ...<br />
}<br />
public void <strong>in</strong>it()<br />
{<br />
Str<strong>in</strong>g relSoundPath=getParameter("SoundPath");<br />
if (relSoundPath==null)<br />
relSoundPath=DEF_SOUNDPATH;<br />
// ...<br />
}<br />
// ...
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 634 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Zugriff zu Resource-Dateien<br />
<strong>Java</strong>-Applet-API (4)<br />
◇ Mit e<strong>in</strong>igen Applet-API-Funktionen kann zu Resource-Dateien (i.a. Bild- und Audio-Dateien) zugegriffen werden.<br />
◇ Die entsprechenden Methoden benötigen i.a. e<strong>in</strong> Objekt der Klasse URL als Parameter.<br />
Objekte der Klasse URL (Package java.net) repräsentieren <strong>in</strong> <strong>Java</strong> die als Uniform Resource Locator (URL)<br />
bezeichnete spezielle Darstellung von Resourcen-Adressen im Internet.<br />
◇ E<strong>in</strong>e URL setzt sich im allgeme<strong>in</strong>en aus mehreren Komponenten zusammen, im wesentlichen aus :<br />
- Protokoll<br />
- Rechneradresse<br />
- Port-Nummer<br />
- Dateipfad (auf dem Rechner)<br />
E<strong>in</strong>ige der Komponenten können gegebenenfalls auch fehlen. Sie werden dann durch Default-Werte ersetzt<br />
(z.B. Default-Port-Nr des jeweiligen Protokolls).<br />
E<strong>in</strong>e URL kann auch als relative URL angegeben werden. Sie dient dann zur Spezifikation e<strong>in</strong>er Resource relativ zu<br />
e<strong>in</strong>er anderen URL. Meist handelt es sich hierbei um e<strong>in</strong>en relativen Dateipfad. Derartige relative URLs werden z.B.<br />
häufig <strong>in</strong>nerhalb von HTML-Seiten verwendet. Sie beziehen sich dann auf die Directory-URL der HTML-Seite.<br />
◇ URLs werden üblicherweise als Str<strong>in</strong>gs angegeben, z.B.<br />
http://archive.ncsa.uiuc.edu:80/SDG/Software/Mosaic/Demo/url-primer.html<br />
◇ Erzeugung e<strong>in</strong>es URL-Objektes aus e<strong>in</strong>em URL-Str<strong>in</strong>g :<br />
Hierzu dient der folgende Konstruktor der Klasse URL :<br />
public URL(Str<strong>in</strong>g spec) throws MalformedURLException<br />
Wenn der als Parameter übergebene Str<strong>in</strong>g spec formal ke<strong>in</strong>e URL bezeichnen kann (z.B. unbekanntes Protokoll),<br />
wird e<strong>in</strong>e MalformedURLException geworfen.<br />
Es existieren noch weitere Konstruktoren mit mehr als e<strong>in</strong>em Parameter.<br />
E<strong>in</strong>ige dieser Konstruktoren erlauben es, e<strong>in</strong>zelne Komponenten e<strong>in</strong>er URL getrennt durch Str<strong>in</strong>gs anzugeben.<br />
◇ Applets dürfen i.a. nur zu Dateien zugreifen, die sich auf demselben Rechner bef<strong>in</strong>den, von dem sie selbst (d.h. der<br />
Byte-Code ihrer Start-Klasse) geladen worden s<strong>in</strong>d.<br />
S<strong>in</strong>nvollerweise werden derartige Dateien durch e<strong>in</strong>e relative Pfadangabe referiert, die sich entweder auf die Code-<br />
Base-URL (Directory-URL der Applet-Start-Klasse) oder auf die Directory-URL der HTML-Seite, <strong>in</strong> der das Applet<br />
e<strong>in</strong>gebettet ist, bezieht.<br />
◇ Die Klasse Applet stellt Memberfunktionen sowohl zum relativen Dateizugriff als auch zur Ermittlung der i.a.<br />
hierfür benötigen Basis-URLs zur Verfügung.<br />
• E<strong>in</strong>b<strong>in</strong>den von Graphiken<br />
◇ Mittels den Applet-Memberfunktionen<br />
public Image getImage(URL url)<br />
public Image getImage(URL base, Str<strong>in</strong>g rel)<br />
wird e<strong>in</strong> Objekt der Klasse Image aus dem Inhalt der Bild-Datei erzeugt, die durch die absolute URL url bzw<br />
die Basis-URL base und den relativen Pfad rel referiert wird.<br />
◇ Mittels des Konstruktors public ImageIcon(Image img)<br />
lässt sich aus dem Image-Objekt img e<strong>in</strong> Objekt der Klasse ImageIcon erzeugen.<br />
Die Klasse ImageIcon implementiert das Interface Icon.<br />
Die durch Objekte dieser Klasse repräsentierten Bilder können <strong>in</strong> diversen Sw<strong>in</strong>g-Komponten (z.B. JButton,<br />
JLabel, JCheckBox) dargestellt werden (Übergabe durch entsprechende Konstruktoren bzw Memberfunktionen.<br />
Beispiel : Image img = getImage(getCodeBase(), relPictPath);<br />
JButton pictbut=new JButton(new ImageIcon(img));<br />
◇ Alternativ kann e<strong>in</strong> Image-Objekt auch <strong>in</strong>nerhalb der Methode public void pa<strong>in</strong>t(Graphics g) mittels<br />
der Graphics-Memberfunktion public boolean drawImage(Image img, ...) dargestellt werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 635 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Abspielen von Audio-Dateien<br />
<strong>Java</strong>-Applet-API (5)<br />
◇ <strong>Java</strong>-Applets können Audio-Dateien abspielen.<br />
Ab dem JDK 1.2 steht diese Möglichkeit auch für Applikations-Programme zur Verfügung.<br />
◇ Zum e<strong>in</strong>maligen Abspielen e<strong>in</strong>er Audio-Datei dienen die Applet-Memberfunktionen<br />
public void play(URL url)<br />
public void play(URL base, Str<strong>in</strong>g rel)<br />
Die abzuspielende Audio-Datei wird entweder durch e<strong>in</strong>e absolute URL url oder e<strong>in</strong>e Basis-URL base und e<strong>in</strong>en<br />
relativen Pfad rel referiert.<br />
Sie wird bei jedem Aufruf von play() erneut geladen.<br />
◇ Zum beliebig mehrmaligen und auch ständig wiederholten Abspielen ohne erneutes Laden der Audio-Datei ist es<br />
s<strong>in</strong>nvoll, zunächst e<strong>in</strong> die Audio-Datei repräsentierendes AudioClip-Objekt zu erzeugen.<br />
Dies ermöglichen die Applet-Memberfunktionen<br />
public AudioClip getAudioClip(URL url)<br />
public AudioClip getAudioClip (URL base, Str<strong>in</strong>g rel)<br />
Auch hier wird die abzuspielende Audio-Datei entweder durch e<strong>in</strong>e absolute URL url oder e<strong>in</strong>e Basis-URL base<br />
und e<strong>in</strong>en relativen Pfad rel referiert.<br />
◇ Das Interface AudioClip stellt drei Methoden zur Verfügung :<br />
public void play() e<strong>in</strong>maliges Abspielen der durch das AudioClip-Objekt repräsentierten Audio-Datei<br />
public void loop() ständiges wiederholtes Abspielen der repräsentierten Audio-Datei<br />
public void stop() Beenden des Abspielens der repräsentierten Audio-Datei<br />
Mit ihnen lässt sich das Abspielen der repräsentierten Audio-Datei ohne erneutes Laden beliebig steuern.<br />
Dies kann zum Beispiel <strong>in</strong> der Methode actionPerformed() e<strong>in</strong>es ActionListener-Objekts als Reaktion<br />
auf das Betätigen e<strong>in</strong>es Schaltknopfes (JButton) erfolgen.<br />
◇ Beispiel :<br />
public class AppletAPIDemo1 extends JApplet<br />
{<br />
// ...<br />
AudioClip sound;<br />
}<br />
public void <strong>in</strong>it()<br />
{<br />
// ...<br />
sound=getAudioClip(getCodeBase(), relSoundPath);<br />
// ...<br />
}<br />
class ButtonListener implements ActionListener<br />
{<br />
public void actionPerformed(ActionEvent e)<br />
{ Object src=e.getSource();<br />
if (src==startbut)<br />
sound.loop();<br />
else if (src==stopbut)<br />
sound.stop();<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 636 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Demonstrationsbeispiel 1 zum <strong>Java</strong>-Applet-API<br />
<strong>Java</strong>-Applet-API (6-1)<br />
◇ Applet-Code (Datei AppletAPIDemo1.java), 1.Teil<br />
import java.applet.*;<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class AppletAPIDemo1 extends JApplet<br />
{<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_LABTEXT = "Demo";<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_PICTPATH = "images/dukeWaveRed.gif";<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_SOUNDPATH = "sounds/bark.au";<br />
static f<strong>in</strong>al <strong>in</strong>t DEF_RAND = 10;<br />
Conta<strong>in</strong>er c;<br />
JLabel lab;<br />
JButton pictbut;<br />
JButton startbut;<br />
JButton stopbut;<br />
JPanel playpan;<br />
AudioClip sound;<br />
public void <strong>in</strong>it()<br />
{ Str<strong>in</strong>g relSoundPath=getParameter("SoundPath");<br />
if (relSoundPath==null)<br />
relSoundPath=DEF_SOUNDPATH;<br />
sound=getAudioClip(getCodeBase(), relSoundPath);<br />
Str<strong>in</strong>g labText=getParameter("LabelText");<br />
if (labText==null)<br />
labText=DEF_LABTEXT;<br />
<strong>in</strong>t rand;<br />
try<br />
{ rand = Integer.parseInt(getParameter("RandBreite")); }<br />
catch (NumberFormatException e)<br />
{ rand=DEF_RAND; }<br />
lab=new JLabel(labText, Sw<strong>in</strong>gConstants.CENTER);<br />
lab.setAlignmentX(Component.CENTER_ALIGNMENT);<br />
lab.setBackground(Color.YELLOW);<br />
lab.setBorder(BorderFactory.createEmptyBorder(rand, rand, rand, rand));<br />
lab.setOpaque(true);<br />
Str<strong>in</strong>g relPictPath=getParameter("PictPath");<br />
if (relPictPath==null)<br />
relPictPath=DEF_PICTPATH;<br />
Image img = getImage(getCodeBase(), relPictPath);<br />
pictbut=new JButton(new ImageIcon(img));<br />
pictbut.setAlignmentX(Component.CENTER_ALIGNMENT);<br />
pictbut.setBorder(BorderFactory.createCompoundBorder(<br />
BorderFactory.createEmptyBorder(5, 0, 10, 0),<br />
pictbut.getBorder()));<br />
startbut = new JButton("start play");<br />
startbut.setBackground(Color.GREEN);<br />
stopbut = new JButton("stop play");<br />
stopbut.setBackground(Color.RED);<br />
playpan = new JPanel();<br />
playpan.add(startbut);<br />
playpan.add(stopbut);<br />
ActionListener butlis = new ButtonListener();<br />
startbut.addActionListener(butlis);<br />
stopbut.addActionListener(butlis);
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 636 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong>-Applet-API (6-2)<br />
• Demonstrationsbeispiel 1 zum <strong>Java</strong>-Applet-API, Forts.<br />
◇ Applet-Code (Datei AppletAPIDemo1.java), 2.Teil<br />
}<br />
c=getContentPane();<br />
c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS));<br />
c.add(lab);<br />
c.add(pictbut);<br />
c.add(playpan);<br />
} // Ende <strong>in</strong>it()<br />
class ButtonListener implements ActionListener<br />
{ public void actionPerformed(ActionEvent e)<br />
{ Object src=e.getSource();<br />
if (src==startbut)<br />
sound.loop();<br />
else if (src==stopbut)<br />
sound.stop();<br />
}<br />
}<br />
◇ E<strong>in</strong>bettende HTML-Datei (AppletAPIDemo1.html)<br />
<br />
<br />
AppletAPIDemo1<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
◇ Darstellung des Applets durch : appletviewer AppletAPIDemo1.html
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 637 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong>-Applet-API (7-1)<br />
• Demonstrationsbeispiel 2 zum <strong>Java</strong>-Applet-API (Demo zu showStatus())<br />
◇ Applet-Code (Datei AppletAPIDemo2.java)<br />
// AppletAPIDemo2.java<br />
// Demo zu showStatus()<br />
import java.applet.*;<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class AppletAPIDemo2 extends JApplet<br />
{<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_PICTPATH = "images/javalogo52x88.gif";<br />
Conta<strong>in</strong>er c;<br />
JLabel textlab;<br />
JLabel pictlab;<br />
public void <strong>in</strong>it()<br />
{<br />
textlab=new JLabel("Demo zu showStatus()", Sw<strong>in</strong>gConstants.CENTER);<br />
textlab.setAlignmentX(Component.CENTER_ALIGNMENT);<br />
textlab.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));<br />
}<br />
}<br />
}<br />
Str<strong>in</strong>g relPictPath=getParameter("PictPath");<br />
if (relPictPath==null)<br />
relPictPath=DEF_PICTPATH;<br />
Image img = getImage(getCodeBase(), relPictPath);<br />
pictlab=new JLabel(new ImageIcon(img));<br />
pictlab.setAlignmentX(Component.CENTER_ALIGNMENT);<br />
pictlab.setBorder(BorderFactory.createL<strong>in</strong>eBorder(Color.BLACK));<br />
c=getContentPane();<br />
c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS));<br />
c.add(textlab);<br />
c.add(pictlab);<br />
MouseListener mouselis = new AppletMouseListener();<br />
addMouseListener(mouselis);<br />
class AppletMouseListener extends MouseAdapter<br />
{<br />
public void mouseEntered(MouseEvent e)<br />
{<br />
showStatus("Gruess Gott Mouse !");<br />
}<br />
public void mouseExited(MouseEvent e)<br />
{<br />
showStatus("Auf Wiedersehen Mouse !");<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 637 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
<strong>Java</strong>-Applet-API (7-2)<br />
• Demonstrationsbeispiel 2 zum <strong>Java</strong>-Applet-API (Demo zu showStatus()), Forts.<br />
◇ E<strong>in</strong>bettende HTML-Datei (AppletAPIDemo2.html)<br />
<br />
<br />
AppletAPIDemo2<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
◇ Darstellung des Applets durch : appletviewer AppletAPIDemo2.html<br />
Mouse-Zeiger<br />
über dem Applet<br />
Mouse-Zeiger wieder<br />
ausserhalb desApplets
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 641 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Sicherheitsbeschränkungen bei <strong>Java</strong>-Applets (1)<br />
◇ E<strong>in</strong> über das Netz geladenes lokal ablaufendes Programm stellt für den lokalen Rechner pr<strong>in</strong>zipiell e<strong>in</strong> Sicherheits-<br />
risiko dar.<br />
◇ Um dieses Sicherheitsrisiko aufzuheben, muß sichergestellt werden, dass e<strong>in</strong> derartiges Programm ke<strong>in</strong>e unbefugten<br />
Aktionen (wie z.B. Zugriff zum lokalen Dateisystem, Start lokaler Programme usw) durchführen kann.<br />
◇ Als Mechanismus zum Schutz vor der unbefugten Ausführung sicherheitsrelevanter Operationen ist <strong>in</strong> <strong>Java</strong> e<strong>in</strong> so-<br />
genannter Security-Manager vorgesehen.<br />
E<strong>in</strong> Security-Manager ist e<strong>in</strong> Objekt der Klasse SecurityManager oder e<strong>in</strong>er davon abgeleiteten Klasse, das <strong>in</strong><br />
jedem <strong>Java</strong>-Programm <strong>in</strong>stalliert se<strong>in</strong> kann.<br />
E<strong>in</strong> SecurityManager-Objekt stellt Methoden zur Verfügung, die die Zulässigkeit diverser sicherheitsrelevanter<br />
Operationen überprüfen.<br />
Falls im Programm e<strong>in</strong> SecurityManager-Objekt <strong>in</strong>stalliert ist, wird von den <strong>Java</strong>-Bibliotheks-Klassen vor der<br />
Ausführung e<strong>in</strong>er entsprechenden sicherheitsrelevanten Operation die zugehörige SecurityManager-Überprüfungs-<br />
Methode aufgerufen.<br />
Falls die Ausführung der überprüften Operation unzulässig ist, wird e<strong>in</strong>e SecurityException geworfen.<br />
◇ Defaultmässig besitzt e<strong>in</strong> Applikations-Programm ke<strong>in</strong>en Security-Manager.<br />
Soll die Ausführung bestimmter sicherheitsrelevanter Operationen für e<strong>in</strong> Applikations-Programm beschränkt werden,<br />
muß es selbst e<strong>in</strong> geeignetes SecurityManager-Objekt erzeugen und <strong>in</strong>stallieren.<br />
◇ Die existierenden java-fähigen Browser und Applet-Viewer dagegen <strong>in</strong>stallieren beim Start e<strong>in</strong>en Security-Manager.<br />
Damit unterliegt die Ausführung von Applets den durch diesen zur Verfügung gestellten Sicherheits-Überprüfungen.<br />
Für die Ausführung von Applets gelten also bestimmte Sicherheitsbeschränkungen, die verh<strong>in</strong>dern, dass unbefugte<br />
Aktionen ausgeführt werden können.<br />
• Pr<strong>in</strong>zipielle Sicherbeschränkungen bei Applets<br />
◇ Der Umfang der für Applets geltenden Sicherheitsbeschränkungen hängt von dem jeweiligen Browser / Applet-Viewer<br />
und dem <strong>in</strong>stallierten Security-Manager sowie von der Vertrauenswürdigkeit des Applets ab.<br />
◇ Standardmässig werden alle von e<strong>in</strong>em anderen Rechner geladen Applets als nicht-vertrauenswürdig betrachtet.<br />
Sie unterliegen damit i.a. allen nachfolgend aufgelisteten Sicherheitsbeschränkungen.<br />
◇ Vom lokalen Dateisystem geladene Applets werden dagegen als vertrauenswürdig betrachtet.<br />
Für sie gelten die meisten der Sicherheitsbeschränkungen nicht.<br />
Analoges gilt für signierte Applets, auch wenn sie von e<strong>in</strong>em entfernten Rechner geladen werden.<br />
Sie werden ebenfalls als vertrauenswürdig betrachtet.<br />
◇ Typischerweise gelten für nicht-vertrauenswürdige Applets die folgenden Sicherheitsbeschränkungen :<br />
∙ ke<strong>in</strong> Zugriff (weder lesend noch schreibend) zum lokalen Dateisystem (Client-Datei-System)<br />
∙ ke<strong>in</strong> Aufbau von Netzwerkverb<strong>in</strong>dungen, außer zu dem Rechner von dem das Applet jeweils stammt (Host-Rechner)<br />
∙ ke<strong>in</strong> Start von Programmen auf dem ausführenden (lokalen) Rechner (Client-Rechner)<br />
∙ ke<strong>in</strong> zusätzliches Laden von Bibliotheken (über die vom Browser geladene Standard-Bibliothek h<strong>in</strong>aus)<br />
∙ ke<strong>in</strong>e Def<strong>in</strong>ition von native-Methoden<br />
∙ ke<strong>in</strong> Top-Level-Fenster ohne Warnh<strong>in</strong>weis erzeugen<br />
∙ ke<strong>in</strong>e Beendigung des Browsers (mittels System.exit(i))<br />
∙ e<strong>in</strong>geschränkter Zugriff zur System-Umgebung (System Properties)<br />
◇ Für vom Applet-Viewer des JDK ausgeführte Applets gelten viele der o.a. Beschränkungen nicht
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 642 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Sicherheitsbeschränkungen bei <strong>Java</strong>-Applets (2)<br />
• Beschränkungen beim Zugriff zur System-Umgebung (System-Properties)<br />
◇ Applets können zu e<strong>in</strong>igen, aber nicht allen System Properties zugreifen.<br />
◇ Der Zugriff zu folgenden System Properties ist gemäß der <strong>Java</strong>-Dokumentation für Applets nicht möglich :<br />
∙ java.home <strong>Java</strong>-Installations-Directory<br />
∙ java.class.path Wert der CLASSPATH-Environment-Variablen<br />
∙ user.name Benutzer-Name des aktuellen Benutzers<br />
∙ user.home Heimat-Verzeichnis des aktuellen Benutzers<br />
∙ user.dir aktuelles Arbeitsverzeichnis des aktuellen Benutzers<br />
◇ Zu den folgenden System Properties sollte dagegen von Applets aus jedem Browser bzw Applet-Viewer zugegriffen<br />
werden können :<br />
∙ java.version Nummer der <strong>Java</strong>-Version<br />
∙ java.vendor Kennzeichnung des <strong>Java</strong>-Lieferanten<br />
∙ java.vendor.url URL des <strong>Java</strong>-Lieferanten<br />
∙ java.class.version <strong>Java</strong>-Klassen-Versions-Nummer<br />
∙ os.name Name des Betriebssystems<br />
∙ os.arch Prozessor-Architektur auf der das Betriebssystem läuft<br />
∙ os.version Versions-Nummer des Betriebssystems<br />
∙ file.separator Trennzeichen <strong>in</strong> Pfadangaben<br />
∙ path.separator Trennzeichen zwischen Pfaden<br />
∙ l<strong>in</strong>e.separator Zeilenende-Zeichen
HOCHSCHULE MUENCHEN FKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 700 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
7. Multithread<strong>in</strong>g<br />
Kapitel 7<br />
7.1. Erzeugung von Threads<br />
7.2. Beenden von Threads<br />
7.3. Synchronisation von Threads<br />
7.4. Thread-Kommunikation über Pipes
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 711 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zip von Threads<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Unter e<strong>in</strong>em Thread ("Ablauffaden") versteht man e<strong>in</strong>en Kontrollfluß <strong>in</strong>nerhalb e<strong>in</strong>es Prozesses, <strong>in</strong> dem Anwei-<br />
sungen e<strong>in</strong>es Programms sequentiell abgearbeitet werden.<br />
Dabei können <strong>in</strong>nerhalb e<strong>in</strong>es Prozesses mehrere Threads existieren, die nebenläufig (parallel bzw quasi-parallel)<br />
ablaufen Multithread<strong>in</strong>g.<br />
Threads ermöglichen also e<strong>in</strong>e Nebenläufigkeit <strong>in</strong>nerhalb e<strong>in</strong>es Programms (Prozesses)<br />
◇ Jeder Thread besitzt e<strong>in</strong>en eigenen Programmzähler und e<strong>in</strong>en eigenen Stack, teilt sich aber mit den anderen Threads<br />
desselben Programms fast alle anderen Resourcen, <strong>in</strong>sbesondere e<strong>in</strong>en geme<strong>in</strong>samen Adressraum.<br />
Bezüglich der Nebenläufigkeit verhalten sich Threads zwar pr<strong>in</strong>zipiell wie eigenständige Prozesse, im Unterschied zu<br />
diesen verfügen sie aber weitgehend über e<strong>in</strong>e geme<strong>in</strong>same Ablaufumgebung. "leichtgewichtige" Prozesse.<br />
◇ Typischerweise ist die <strong>in</strong> e<strong>in</strong>em Thread abgearbeitete Anweisungsfolge <strong>in</strong> e<strong>in</strong>er Funktion (Prozedur) zusammenge-<br />
fasst. Diese kann natürlich weitere Funktionen aufrufen, die dann ebenfalls <strong>in</strong>nerhalb des Threads ausgeführt werden.<br />
◇ E<strong>in</strong> Thread bef<strong>in</strong>det sich zu jedem Zeitpunkt <strong>in</strong> genau e<strong>in</strong>em von mehreren möglichen Zuständen<br />
◇ E<strong>in</strong> Thread wird als aktiv (active, alive) bezeichnet, wenn se<strong>in</strong>e Anweisungsfolge gestartet aber noch nicht beendet<br />
worden ist.<br />
• Threads <strong>in</strong> <strong>Java</strong><br />
◇ Jeder ("schwergewichtige") Prozeß, d.h. jedes <strong>in</strong> Ausführung bef<strong>in</strong>dliche Programm, enthält wenigstens e<strong>in</strong>en Thread.<br />
In <strong>Java</strong>-Programmen wird dieser durch die Abarbeitung der ma<strong>in</strong>()-Funktion der Startklasse gebildet.<br />
Bei Programmen mit graphischer Oberfläche werden darüber h<strong>in</strong>aus automatisch weitere Threads erzeugt. U.a. gibt<br />
es den event-dispatch<strong>in</strong>g Thread, der für das Zustellen von Ereignissen und deren Bearbeitung zuständig ist.<br />
◇ Grundsätzlich ist die Erzeugung weiterer Threads <strong>in</strong> <strong>Java</strong> sehr e<strong>in</strong>fach.<br />
Das Konzept e<strong>in</strong>er Nebenläufigkeit mit Threads ist direkt <strong>in</strong> die Sprache <strong>in</strong>tegriert worden (Sprachkomponenten zur<br />
Synchronisation) und wird durch geeignete Bibliothekskomponenten effizient unterstützt.<br />
◇ Threads <strong>in</strong> <strong>Java</strong> besitzen e<strong>in</strong>e Priorität ,e<strong>in</strong>en Namen und – ab dem JDK 5.0 – e<strong>in</strong>e ID (positiver long-Wert).<br />
◇ Threads <strong>in</strong> <strong>Java</strong> s<strong>in</strong>d <strong>in</strong> Thread-Gruppen zusammengefasst. Jeder Thread gehört zu e<strong>in</strong>er Thread-Gruppe<br />
◇ Threads werden <strong>in</strong> <strong>Java</strong> durch Objekte gekapselt.<br />
Pr<strong>in</strong>zipiell kann ihre Gesamt-Funktionalität dabei auf zwei Objekte aufgeteilt se<strong>in</strong> :<br />
▻ E<strong>in</strong> Objekt def<strong>in</strong>iert die vom Thread auszuführende Anweisungsfolge<br />
Es legt die durchzuführende Arbeit ("work") fest "Thread-Arbeits-Objekt", Thread-Target-Objekt.<br />
▻ E<strong>in</strong> Objekt dient zur Verwaltung und Steuerung (Starten, Beenden, Unterbrechen, Weiterlaufen) der Thread-Abar-<br />
beitung. Es führt die Arbeit durch ("worker") "Thread-Arbeiter-Objekt", Thread-Verwaltungs-Objekt.<br />
Die Funktionalität von beiden kann auch <strong>in</strong> e<strong>in</strong>em e<strong>in</strong>zigen Objekt zusammengefasst se<strong>in</strong>.<br />
◇ Kern der Thread-Unterstützung durch die Standardbibliothek s<strong>in</strong>d (enthalten im Package java.lang) :<br />
▻ das Interface Runnable<br />
▻ die Klasse Thread<br />
• Das Interface Runnable<br />
◇ Alle Thread-Target-Objekte müssen Instanzen e<strong>in</strong>er Klasse se<strong>in</strong>, die das Interface Runnable implementiert.<br />
◇ Das Interface Runnable deklariert e<strong>in</strong>e e<strong>in</strong>zige Methode :<br />
public void run()<br />
◇ Die Methode run() muß <strong>in</strong> e<strong>in</strong>er implementierenden Klasse so überschrieben werden, dass sie die <strong>in</strong>nerhalb des<br />
Threads auszuführende Anweisungsfolge def<strong>in</strong>iert.<br />
◇ Der Start e<strong>in</strong>es Threads bewirkt die Abarbeitung der run()-Methode des zum Thread gehörenden Target-Objekts<br />
Der Aufruf dieser Methode erfolgt automatisch – <strong>in</strong>direkt – durch die JVM
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 712 – 01 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Die Klasse Thread (Package java.lang)<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (2-1)<br />
◇ Diese Klasse def<strong>in</strong>iert die Funktionalität zur Verwaltung/Steuerung von Threads.<br />
Jedes Thread-Verwaltungs-Objekt muß e<strong>in</strong>e Instanz dieser Klasse oder e<strong>in</strong>er von ihr abgeleiteten Klasse se<strong>in</strong>.<br />
◇ E<strong>in</strong> Thread-Objekt kann bei se<strong>in</strong>er Erzeugung mit e<strong>in</strong>em Thread-Target-Objekt assoziiert werden.<br />
◇ Die Klasse Thread implementiert selbst auch das Interface Runnable.<br />
Falls mit e<strong>in</strong>em Thread-Objekt e<strong>in</strong> Thread-Target-Objekt assoziiert ist, ruft die <strong>in</strong> der Klasse Thread def<strong>in</strong>ierte<br />
run()-Methode die run()-Methode des Target-Objekts auf.<br />
Andernfalls besitzt die run()-Methode e<strong>in</strong>e leere Funktionalität.<br />
In e<strong>in</strong>er von Thread abgeleiteten Klasse kann die run()-Methode aber so überschrieben werden, dass sie die<br />
volle Arbeits-Funktionalität e<strong>in</strong>es Threads enthält. Damit lassen sich Thread-Verwaltungs- und Thread-Arbeits-Funk-<br />
tionalität <strong>in</strong> e<strong>in</strong>em e<strong>in</strong>zigen Objekt zusammenfassen.<br />
◇ Die Klasse Thread def<strong>in</strong>iert als e<strong>in</strong>gebettete Top-Level-Klasse den Aufzählungstyp Thread.State :<br />
public static enum State extends Enum { ... }<br />
Die Objekte dieses Aufzählungstyps (== Aufzählungskonstante) kennzeichnen die verschiedenen Thread-Zustände.<br />
◇ Die Klasse def<strong>in</strong>iert drei statische öffentliche Datenkomponenten als Konstanten für die Prioritätsfestlegung :<br />
public static f<strong>in</strong>al <strong>in</strong>t MIN_PRIORITY m<strong>in</strong>imale Priorität, die e<strong>in</strong> Thread haben kann<br />
public static f<strong>in</strong>al <strong>in</strong>t MAX_PRIORITY maximale Priorität, die e<strong>in</strong> Thread haben kann<br />
public static f<strong>in</strong>al <strong>in</strong>t NORM_PRIORITY Default-Priorität, die e<strong>in</strong>em Thread zugeordnet wird<br />
◇ Konstruktoren der Klasse Thread (Auswahl)<br />
public Thread() Erzeugung e<strong>in</strong>es Thread-Objekts, das mit ke<strong>in</strong>em Thread-Target-Objekt<br />
assoziiert ist und e<strong>in</strong>en vom System vergebenen Default-Namen besitzt<br />
public Thread(Runnable tgt) Erzeugung e<strong>in</strong>es Thread-Objekts, das mit dem Thread-Target-Objekt tgt<br />
assoziiert ist und e<strong>in</strong>en vom System vergebenen Default-Namen besitzt<br />
public Thread(Runnable tgt, Erzeugung e<strong>in</strong>es Thread-Objekts, das mit dem Thread-Target-Objekt tgt<br />
Str<strong>in</strong>g name) assoziiert ist und den Namen name besitzt<br />
public Thread(Str<strong>in</strong>g name) Erzeugung e<strong>in</strong>es Thread-Objekts, das mit ke<strong>in</strong>em Thread-Target-Objekt<br />
assoziiert ist und den Namen name besitzt<br />
◇ Memberfunktionen zur Thread-Steuerung (Auswahl)<br />
public void start() Start der Ausführung des Threads. Die Methode veranlasst die JVM<br />
die run()-Methode des Thread-Objekts aufzurufen<br />
public void run() Aufruf der run()-Methode e<strong>in</strong>es assozierten Thread-Target-Objekts<br />
bzw leere Funktionalität, falls ke<strong>in</strong> Thread-Target-Objekt assoziiert ist<br />
Muss <strong>in</strong> abgeleiteten Klassen geeignet überschreiben werden<br />
public void <strong>in</strong>terrupt() Setzen des Abbruch-Flags des Threads bzw – falls der Thread <strong>in</strong> e<strong>in</strong>em<br />
Wartezustand ist – Senden e<strong>in</strong>er InterruptedException an<br />
den Thread<br />
public f<strong>in</strong>al void jo<strong>in</strong>() Warten auf die Beendigung des Threads<br />
public static void sleep(long ms) Übergang des aktuellen Threads <strong>in</strong> den Wartezustand für ms Millisek<br />
Kann gegebenenfalls e<strong>in</strong>e InterruptedException werfen<br />
public static void yield() (temporäre) Freigabe der CPU durch den laufenden Thread
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 712 – 02 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die Klasse Thread, Forts.<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (2-2 )<br />
◇ Memberfunktionen zur Information über den Thread-Zustand<br />
public Thread.State getState() Rückgabe des Thread-Zustands (ab dem JDK 5.0)<br />
public boolean isInterrupted() Überprüfung des Abbruch-Flags des Threads,<br />
liefert true, wenn das Abbruch-Flag gesetzt ist<br />
Das Abbruch-Flag selbst wird nicht bee<strong>in</strong>flusst<br />
public static boolean <strong>in</strong>terrupted() Überprüfung des Abbruch-Flags des aktuellen Threads<br />
liefert true, wenn das Abbruch-Flag gesetzt ist<br />
Das Abbruch-Flag wird rückgesetzt<br />
public boolean isAlive() Überprüfung, ob der Thread noch aktiv ist<br />
(gestartet und noch nicht beendet)<br />
liefert true, wenn der Thread noch aktiv ist<br />
◇ Memberfunktionen zurInformation über und Bee<strong>in</strong>flussung von Thread-Eigenschaften (Auswahl)<br />
public long getID() Rückgabe der Thread-ID (ab dem JDK 5.0)<br />
public f<strong>in</strong>al Str<strong>in</strong>g getName() Rückgabe des Thread-Namens<br />
public f<strong>in</strong>al void setName(Str<strong>in</strong>g name) Ändern des Thread-Namens auf name<br />
public f<strong>in</strong>al <strong>in</strong>t getPriority() Rückgabe der Thread-Priorität<br />
public f<strong>in</strong>al void setPriority(<strong>in</strong>t prio) Ändern der Thread-Priorität auf prio<br />
public f<strong>in</strong>al ThreadGroup getThreadGroup() Rückgabe e<strong>in</strong>er Referenz auf das ThreadGroup-Objekt<br />
der Thread-Gruppe, zu der der Thread gehört<br />
public static <strong>in</strong>t activeCount() Rückgabe der Anzahl der aktiven Threads, die sich <strong>in</strong><br />
der Thread-Gruppe des aktuell laufenden Threads bef<strong>in</strong>den<br />
public static Thread currentThread() Rückgabe e<strong>in</strong>er Referenz auf das Thread-Objekt des<br />
aktuell ausgeführten Threads<br />
public Str<strong>in</strong>g toStr<strong>in</strong>g() Rückgabe e<strong>in</strong>er Str<strong>in</strong>g-Repräsentation des Threads.<br />
Diese enthält den Namen und die Priorität des Threads<br />
sowie den Namen se<strong>in</strong>er Thread-Gruppe<br />
◇ Zur Synchronisation und damit zur Steuerung von Threads dienen auch e<strong>in</strong>ige Methoden der Klasse Object :<br />
▻ public f<strong>in</strong>al void wait()<br />
public f<strong>in</strong>al void wait(long timeout)<br />
public f<strong>in</strong>al void wait(long timeout, <strong>in</strong>t nanos)<br />
▻ public f<strong>in</strong>al void notify()<br />
▻ public f<strong>in</strong>al void notifyAll()<br />
Diese Methoden werden aber nicht als Memberfunktionen des zu steuernden Threads aufgerufen, sondern als<br />
Memberfunktion des Objekts, zu dem der Zugriff synchronisiert werden soll.<br />
Sie bee<strong>in</strong>flussen jeweils den Thread, der die Zugriffssperre (Lock) zu diesem Objekt besitzt, bzw e<strong>in</strong> oder alle Objekte,<br />
die auf die Freigabe und damit den Besitz des Locks für das Objekt warten.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 712 – 03 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (2-3 )<br />
• Der Aufzählungstyp Thread.State (Package java.lang)<br />
◇ static-Komponente der Klasse Thread e<strong>in</strong>gebetteter Top-Level-Typ<br />
◇ Der Typ ist abgeleitet von der parameterisierten Klasse Enum<br />
◇ Objekte dieses Typs (== Aufzählungskonstante) dienen zur Kennzeichnung der verschiedenen Thread-Zustände<br />
◇ Die def<strong>in</strong>ierten Aufzählungskonstanten (und damit Thread-Zustände) s<strong>in</strong>d :<br />
◇ Die folgenden von der Klasse Enum geerbten Methoden werden durch Thread.State<br />
überschrieben :<br />
▻<br />
▻<br />
NEW Zustand nach Erzeugung e<strong>in</strong>es Thread-Objekts vor Aufruf der start()-Methode<br />
RUNNABLE Der Thread wird gerade abgearbeitet oder ist ablaufbereit (wartet auf CPU)<br />
BLOCKED Der Thread wartet auf die Freigabe e<strong>in</strong>es Monitor-Locks (zu Beg<strong>in</strong>n der Ausführung<br />
e<strong>in</strong>er synchronized-Anweisung/Methode bzw nach Aufwecken durch<br />
notify() auf das durch den Aufruf von wait() gewartet wurde)<br />
WAITING Der Thread wartet auf e<strong>in</strong>en anderen Thread um weiterlaufen zu können (z.B. Warten<br />
auf notify() e<strong>in</strong>es anderen Threads nach dem Aufruf von wait() oder<br />
Warten auf die Beendigung e<strong>in</strong>es Threads für den jo<strong>in</strong>() aufgerufen wurde)<br />
TIMED_WAITING Der Thread wartet auf den Ablauf e<strong>in</strong>er festgelegten Zeit (z.B. nach Aufruf von<br />
sleep() oder wait() mit Timeout oder jo<strong>in</strong>() mit Timeout)<br />
TERMINATED Der Thread ist beendet (Methode run() ist beendet)<br />
public static f<strong>in</strong>al Thread.State[] values()<br />
Die Funktion gibt e<strong>in</strong> Array der def<strong>in</strong>ierten Aufzählungskonstanten zurück.<br />
Die Reihenfolge der Konstanten im Array entspricht ihrer Def<strong>in</strong>itionsreihenfolge<br />
public static Thread.State valueOf(Str<strong>in</strong>g name)<br />
Die Funktion gibt die Aufzählungskonstante (d.h. das entsprechende Thread.State-Objekt) mit dem<br />
Namen name zurück.<br />
Die Funktion wirft e<strong>in</strong>e Exception vom Typ IllegalArgumentException, wenn name ke<strong>in</strong>e<br />
def<strong>in</strong>ierte Aufzählungskonstante bezeichnet.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 713 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (3-1 )<br />
• Demonstrationsprogramm zu den standardmässig erzeugten Threads e<strong>in</strong>facher GUI-Programme<br />
◇ Quellcode (Datei BasicThreadDemo.java)<br />
// BasicThreadDemo.java<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class BasicThreadDemo extends JFrame<br />
{<br />
Conta<strong>in</strong>er c;<br />
JButton but;<br />
}<br />
public BasicThreadDemo()<br />
{ super("BasicThreadDemo");<br />
c=getContentPane();<br />
c.setLayout(new FlowLayout());<br />
but = new JButton("Pr<strong>in</strong>t Current Thread Info");<br />
c.add(but);<br />
Thread nthr = new Thread("Leer-Thread");<br />
System.out.pr<strong>in</strong>t(nthr + " ID : " + nthr.getId());<br />
System.out.pr<strong>in</strong>tln(" (State : " + nthr.getState() + ")");<br />
}<br />
ActionListener actlis = new ActionListener()<br />
{ public void actionPerformed(ActionEvent e)<br />
{ System.out.pr<strong>in</strong>tln("\n" + Thread.currentThread() + " (im Event-Listener)");<br />
threadInfo();<br />
}<br />
};<br />
but.addActionListener(actlis);<br />
setSize(300, 180);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
System.out.pr<strong>in</strong>tln(Thread.currentThread() + " (im Konstruktor)");<br />
public void threadInfo()<br />
{ System.out.pr<strong>in</strong>tln();<br />
Thread[] thrarr = new Thread[Thread.activeCount()];<br />
<strong>in</strong>t threadAnz = Thread.currentThread().getThreadGroup().enumerate(thrarr);<br />
System.out.pr<strong>in</strong>tln("ThreadGroup enthaelt " + threadAnz + " aktive Threads : \n");<br />
for (Thread thr : thrarr)<br />
{ System.out.pr<strong>in</strong>t(thr + " ID : " + thr.getId());<br />
System.out.pr<strong>in</strong>tln(" (State : " + thr.getState() + ")");<br />
}<br />
System.out.pr<strong>in</strong>tln();<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ System.out.pr<strong>in</strong>tln("Thread-M<strong>in</strong>-Priority : " + Thread.MIN_PRIORITY);<br />
System.out.pr<strong>in</strong>tln("Thread-Max-Priority : " + Thread.MAX_PRIORITY);<br />
System.out.pr<strong>in</strong>tln("Thread-Norm-Priority : " + Thread.NORM_PRIORITY);<br />
System.out.pr<strong>in</strong>tln("\n" + Thread.currentThread() + " (<strong>in</strong> ma<strong>in</strong>())");<br />
new BasicThreadDemo().setVisible(true);<br />
while(true);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 713 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (3-2 )<br />
• Demonstrationsprogramm zu den standardmässig erzeugten Threads e<strong>in</strong>facher GUI-Programme<br />
◇ Programmstart und -ausgabe
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 714 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (4)<br />
• Möglichkeiten zur Erzeugung von Threads <strong>in</strong> <strong>Java</strong><br />
◇ Es existieren zwei grundsätzliche Möglichkeiten<br />
◇ Erste Möglichkeit :<br />
Zusammenfassung der Thread-Target- und der Thread-Verwaltungs-Funktionalität <strong>in</strong> e<strong>in</strong>em e<strong>in</strong>zigen Objekt.<br />
Die Klasse dieses Thread-Objekts (MyThread) muß von der Klasse Thread abgeleitet werden und die Methode<br />
run() so überschreiben, dass sie die vom Thread auszuführenden Anweisungsfolge def<strong>in</strong>iert.<br />
class MyThread extends Thread<br />
{<br />
public void run()<br />
{ // ...<br />
}<br />
// ...<br />
}<br />
Der Thread wird durch Aufruf der von Thread geerbten Methode start() für e<strong>in</strong> erzeugtes MyThread-<br />
Objekt gestartet. Der Aufruf von start() bewirkt den Aufruf der überschriebenen Methode run().<br />
new MyThread().start();<br />
◇ Zweite Möglichkeit :<br />
Aufteilung der Thread-Gesamt-Funktionalität auf e<strong>in</strong> Thread-Target- und e<strong>in</strong> Thread-Verwaltungs-Objekt.<br />
Die Klasse des Thread-Target-Objekts (MyRun) muß das Interface Runnable implementieren und die Methode<br />
run()mit der vom Thread auszuführenden Anweisungsfolge def<strong>in</strong>ieren.<br />
Das Thread-Verwaltungs-Objekt ist e<strong>in</strong>e Instanz der Klasse Thread. Diesem ist bei se<strong>in</strong>er Erzeugung im Konstruk-<br />
tor e<strong>in</strong>e Instanz der Thread-Target-Klasse MyRun zu übergeben.<br />
class MyRun implements Runnable<br />
{<br />
public void run()<br />
{ // ...<br />
}<br />
// ...<br />
}<br />
Gestartet wird der Thread durch Aufruf der Methode start() für das erzeugte Thread-Objekt.<br />
Der Aufruf dieser Methode bewirkt den Aufruf der Methode run() des gleichen Objekts. Diese wiederum ruft<br />
die run()-Methode des dem Thread-Objekt übergebenen MyRun-Objekts auf.<br />
new Thread(new MyRun()).start();<br />
<strong>in</strong>terface<br />
Runnable Runnable Runnable Runnable<br />
+run():void<br />
MyRun<br />
MyRun<br />
+run():void<br />
<strong>in</strong>terface<br />
Runnable Runnable Runnable Runnable<br />
+run():void<br />
Thread<br />
Thread<br />
+run():void<br />
+start():void<br />
MyThread MyThread<br />
MyThread<br />
+run():void<br />
Thread<br />
Thread<br />
+run():void<br />
+start():void
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 715 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (5)<br />
• Demonstrationsprogramm zu Threads (Thread-Klasse von Thread abgeleitet)<br />
◇ Quellcode (Datei SimpleThreadDemo1.java)<br />
// SimpleThreadDemo1.java<br />
public class SimpleThreadDemo1 extends Thread<br />
{ private Str<strong>in</strong>g wort;<br />
private <strong>in</strong>t delay;<br />
}<br />
public SimpleThreadDemo1(Str<strong>in</strong>g wrt, <strong>in</strong>t del)<br />
{ wort = wrt;<br />
delay = del;<br />
}<br />
public void run()<br />
{ try<br />
{ while(true)<br />
{ System.out.pr<strong>in</strong>t(wort + ' ');<br />
Thread.sleep(delay);<br />
}<br />
}<br />
catch(InterruptedException e)<br />
{ return;<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ new SimpleThreadDemo1("PING", 100).start();<br />
new SimpleThreadDemo1("pong", 33).start();<br />
}<br />
◇ Programmstart und -ausgabe
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 716 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Erzeugung von Threads <strong>in</strong> <strong>Java</strong> (6)<br />
• Demonstrationsprogramm zu Threads (Thread-Target-Klasse implementiert Runnable)<br />
◇ Quellcode (Datei SimpleThreadDemo1.java)<br />
// SimpleThreadDemo2.java<br />
public class SimpleThreadDemo2 implements Runnable<br />
{ private Str<strong>in</strong>g wort;<br />
private <strong>in</strong>t delay;<br />
}<br />
public SimpleThreadDemo2(Str<strong>in</strong>g wrt, <strong>in</strong>t del)<br />
{ wort = wrt;<br />
delay = del;<br />
}<br />
public void run()<br />
{ try<br />
{ while(true)<br />
{ System.out.pr<strong>in</strong>t(wort + ' ');<br />
Thread.sleep(delay);<br />
}<br />
}<br />
catch(InterruptedException e)<br />
{ return;<br />
}<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
new Thread(new SimpleThreadDemo2("PING", 100)).start();<br />
new Thread(new SimpleThreadDemo2("pong", 33)).start();<br />
}<br />
◇ Programmstart und -ausgabe
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 721 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Normales Ende e<strong>in</strong>es Threads<br />
Beenden von Threads <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Normalerweise läuft e<strong>in</strong> Thread solange wie se<strong>in</strong>e run()-Methode ausgeführt wird.<br />
Er wird erst beendet, wenn auch die letzte Anweisung dieser Methode abgearbeitet worden ist.<br />
◇ E<strong>in</strong> Thread lässt sich nur e<strong>in</strong>mal mittels start() starten.<br />
D.h. e<strong>in</strong> e<strong>in</strong>mal beendeter Thread kann nicht noch e<strong>in</strong>mal ablaufen.<br />
Soll die im Thread realisierte Funktionalität nochmals ausgeführt werden, muss e<strong>in</strong> neues Thread-Objekt erzeugt<br />
und für dieses dann start() aufgerufen werden.<br />
• Vorzeitiges Beenden e<strong>in</strong>es Threads<br />
◇ Der Aufruf der Methode System.exit(...) <strong>in</strong> irgende<strong>in</strong>em Thread bewirkt, dass die JVM und damit alle<br />
Threads beendet werden.<br />
◇ Tritt <strong>in</strong> e<strong>in</strong>emThread e<strong>in</strong>e Exception auf, die nicht gefangen wird, führt das ebenfalls zum vorzeitigen Ende des<br />
Threads.<br />
◇ Häufig läuft e<strong>in</strong> Thread <strong>in</strong> e<strong>in</strong>er Schleife, die gezielt zu e<strong>in</strong>em bestimmten Zeitpunkt von aussen – durch e<strong>in</strong>en anderen<br />
Thread – beendet werden soll, wodurch dann i.a. auch der Thread se<strong>in</strong> Ende erreicht<br />
Ohne diese E<strong>in</strong>wirkung von aussen würde der Thread meist <strong>in</strong> e<strong>in</strong>er Endlosschleife laufen.<br />
◇ E<strong>in</strong> derartiges gezieltes vorzeitiges Beenden e<strong>in</strong>en Threads kann dadurch erreicht werden, dass der Thread an geeig-<br />
neter Stelle <strong>in</strong>nerhalb der Schleife e<strong>in</strong> Abbruchkriterium überprüft, dass von aussen gesetzt werden kann.<br />
Pr<strong>in</strong>zipiell kann hierfür e<strong>in</strong>e explizit dafür vorgesehene Datenkomponente (z.B. vom Typ boolean) e<strong>in</strong>gesetzt<br />
werden.<br />
◇ E<strong>in</strong>facher und i.a. effizienter ist es aber, hierfür auf e<strong>in</strong>en <strong>in</strong> der Klasse Thread implementierten Mechanismus zu-<br />
rückzugreifen.<br />
Dieser beruht auf den Memberfunktionen <strong>in</strong>terrupt () und isInterrupted().<br />
◇ Die Methode <strong>in</strong>terrupt() führt bei dem Thread-Objekt, für das sie aufgerufen wird, zum Setzen e<strong>in</strong>es<br />
Abbruch-Flags, falls sich der zugehörige Thread nicht <strong>in</strong> e<strong>in</strong>em Wartezustand bef<strong>in</strong>det.<br />
Falls sich der Thread <strong>in</strong> e<strong>in</strong>em Wartezustand bef<strong>in</strong>det (z.B. ausgelöst durch den Aufruf von Thread.sleep(...)),<br />
wird an ihn e<strong>in</strong>e InterruptedException geschickt, die den Wartezustand beendet. Das Abbruch-Flag wird nicht<br />
gesetzt (es wird sogar rückgesetzt, falls es gesetzt gewesen war).<br />
Um auch <strong>in</strong> diesem Fall e<strong>in</strong> Setzen des Abbruch-Flags zu erreichen, muss der zugehörige Exception-Handler se<strong>in</strong>erseits<br />
die Methode <strong>in</strong>terrupt() aufrufen. Da sich der Thread nun nicht mehr <strong>in</strong> e<strong>in</strong>em Wartezustand bef<strong>in</strong>det, wird da-<br />
durch das Abbruch-Flag gesetzt.<br />
◇ Mit der Methode isInterrupted() kann der Thread den Zustand se<strong>in</strong>es Abbruch-Flags überprüfen.<br />
Falls die Methode true zurückliefert, war das Flag gesetzt. Dies sollte dann zum Beenden der Schleife führen.<br />
◇ Beispiel :<br />
public void run()<br />
{<br />
while (!isInterrupted())<br />
{<br />
try<br />
{<br />
// tue etwas<br />
Thread.sleep(500);<br />
}<br />
catch(InterruptedException e)<br />
{<br />
<strong>in</strong>terrupt();<br />
}<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 722 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Beenden von Threads <strong>in</strong> <strong>Java</strong> (2-1)<br />
• Demonstrationsprogramm zum gezielten vorzeitigen Beenden e<strong>in</strong>es Threads, Teil 1<br />
◇ Quellcode der Klasse Bl<strong>in</strong>kDemo (Datei Bl<strong>in</strong>kDemo.java)<br />
// Bl<strong>in</strong>kDemo.java<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class Bl<strong>in</strong>kDemo extends JFrame<br />
{ Conta<strong>in</strong>er c;<br />
Bl<strong>in</strong>kPanel blkpan;<br />
Bl<strong>in</strong>kThread blkthr = null;<br />
}<br />
public Bl<strong>in</strong>kDemo()<br />
{ super("Bl<strong>in</strong>kDemo");<br />
c=getContentPane();<br />
blkpan = new Bl<strong>in</strong>kPanel(Color.GREEN, Color.RED);<br />
c.add(blkpan);<br />
setSize(250, 200);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
blkpan.addMouseListener(new MouseAdapter()<br />
{ public void mouseClicked(MouseEvent e)<br />
{ if (blkthr==null || !blkthr.isAlive())<br />
{ blkthr = new Bl<strong>in</strong>kThread(Bl<strong>in</strong>kDemo.this);<br />
blkthr.start();<br />
}<br />
else<br />
blkthr.<strong>in</strong>terrupt();<br />
}<br />
}<br />
);<br />
}<br />
public void bl<strong>in</strong>k()<br />
{ blkpan.chgCol();<br />
repa<strong>in</strong>t();<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Bl<strong>in</strong>kDemo blkdemo = new Bl<strong>in</strong>kDemo();<br />
blkdemo.setVisible(true);<br />
}<br />
◇ Vom Programm erzeugtes Fenster (beide Bl<strong>in</strong>kzustände)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 722 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Beenden von Threads <strong>in</strong> <strong>Java</strong> (2-2)<br />
• Demonstrationsprogramm zum gezielten vorzeitigen Beenden e<strong>in</strong>es Threads, Teil 2<br />
◇ Quellcode der Klasse Bl<strong>in</strong>kPanel (Datei Bl<strong>in</strong>kPanel.java)<br />
// Bl<strong>in</strong>kPanel.java<br />
import java.awt.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class Bl<strong>in</strong>kPanel extends JPanel<br />
{ Color bgc;<br />
Color vgc;<br />
boolean equcol;<br />
}<br />
public Bl<strong>in</strong>kPanel(Color bg, Color vg)<br />
{ bgc=bg;<br />
vgc=vg;<br />
setBackground(bgc);<br />
setOpaque(true);<br />
equcol=false;<br />
}<br />
public void chgCol()<br />
{ equcol=!equcol;<br />
}<br />
public void pa<strong>in</strong>t(Graphics g)<br />
{ super.pa<strong>in</strong>t(g);<br />
if (equcol)<br />
setForeground(bgc);<br />
else<br />
setForeground(vgc);<br />
g.fillOval(20, 20, getWidth()-40, getHeight()-40);<br />
}<br />
◇ Quellcode der Klasse Bl<strong>in</strong>kThread (Datei Bl<strong>in</strong>kThread.java)<br />
// Bl<strong>in</strong>kThread.java<br />
public class Bl<strong>in</strong>kThread extends Thread<br />
{<br />
private Bl<strong>in</strong>kDemo blkdem;<br />
}<br />
public Bl<strong>in</strong>kThread(Bl<strong>in</strong>kDemo bd)<br />
{ blkdem=bd;<br />
}<br />
public void run()<br />
{ while (!isInterrupted())<br />
{ blkdem.bl<strong>in</strong>k();<br />
try<br />
{ Thread.sleep(500);<br />
}<br />
catch (InterruptedException e) {<strong>in</strong>terrupt();}<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 731 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Probleme bei Nebenläufigkeit<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Multithread<strong>in</strong>g dient zur Realisierung e<strong>in</strong>er Nebenläufigkeit <strong>in</strong>nerhalb e<strong>in</strong>es Prozesses.<br />
Nebenläufigkeit ermöglicht aber e<strong>in</strong>en konkurierenden Zugriff zu denselben Resourcen (z.B. Daten).<br />
Dies kann zu erheblichen Problemen führen.<br />
Die beiden wichtigsten dieser Probleme s<strong>in</strong>d :<br />
- Zugriffs-Wettlauf (race condition)<br />
- Verklemmung (deadlock)<br />
◇ Zugriffs-Wettlauf (race condition)<br />
Wenn zwei oder mehr Threads konkurierend zu denselben Daten zugreifen und wenigstens e<strong>in</strong>er dieser Threads die<br />
Daten verändert,<br />
- kann es zu <strong>in</strong>konsistenten und <strong>in</strong> der Folge zu fehlerhaften Datenzuständen kommen<br />
(z.B. gleichzeitige bzw zeitlich verzahnte Durchführung je e<strong>in</strong>es read-modify-write-Zyklus auf die gleichen Daten<br />
durch zwei verschiedene Threads, allgeme<strong>in</strong> : Leser-Schreiber-Problem)<br />
- können von den Threads erzeugte Ergebnisse zeitabhängig se<strong>in</strong><br />
(Ergebnisse hängen von der Zugriffsreihenfolge ab, typisch : Produzenten-Verbraucher-Problem)<br />
Zur Vermeidung dieser Probleme muss der konkurierende Zugriff synchronisiert werden.<br />
Durch e<strong>in</strong>e derartige Synchronisation wird sichergestellt, dass e<strong>in</strong> "kritischer" Datenzugriff immer nur von e<strong>in</strong>em<br />
Thread ausgeführt werden kann. Nur e<strong>in</strong> Thread besitzt die Zugriffsberechtigung zu den Daten (allg. : Betriebsmittel).<br />
Andere Threads, die zu den gleichen Daten (Betriebsmittel) zugreifen wollen, müssen warten, bis der erste Thread<br />
se<strong>in</strong>en Zugriff beendet hat (gegenseitiger Ausschluß, mutual exclusion).<br />
Die Sprache <strong>Java</strong> stellt hierfür Sprachmittel zu Verfügung<br />
◇ Verklemmung (deadlock)<br />
Wenn zwei (oder mehr) Threads wechselseitig auf Daten (allgeme<strong>in</strong>er : Betriebsmittel) zugreifen wollen, die der jeweils<br />
andere Thread – <strong>in</strong>folge von Synchronisationsmassnahmen – exklusiv belegt hat, blockieren sie sich gegenseitig.<br />
Diese Situation kann z.B. auftreten, wenn Thread A die Zugriffsberechtigung zu e<strong>in</strong>em Objekt X und Thread B die<br />
Zugriffsberechtigung zu e<strong>in</strong>em Objekt Y besitzen und beide zu ihrer – zur Freigabe dieser Objekte führenden – Weiterarbeit<br />
den Zugriff auf das jeweils andere Objekt benötigen.<br />
Zur Lösung derartiger Probleme existieren <strong>in</strong> der Sprache <strong>Java</strong> ke<strong>in</strong>e Möglichkeiten.<br />
Sie müssen durch wachsame und geschickte Programmierung vermieden werden.<br />
• Synchronisation <strong>in</strong> <strong>Java</strong> : Monitore und Locks<br />
◇ E<strong>in</strong> Code-Bereich , <strong>in</strong> dem e<strong>in</strong> konkurierender Datenzugriff erfolgen kann, wird als kritischer Abschnitt oder kritische<br />
Region bezeichnet.<br />
Solange e<strong>in</strong> Thread e<strong>in</strong>en derartigen kritischen Abschnitt durchläuft, sollte ke<strong>in</strong> anderer Thread <strong>in</strong> denselben oder e<strong>in</strong>en<br />
anderen kritischen Abschnitt, der sich auf dieselben Daten bezieht, e<strong>in</strong>treten.<br />
Durch Überwachung (Freigabe, Sperren) der zu bestimmten Daten (z.B. e<strong>in</strong>em Objekt) gehörenden kritischen Abschnit-<br />
te lässt sich der Zugriff zu diesen Daten synchronisieren.<br />
◇ Zur Überwachung der kritischen Abschnitte werden <strong>in</strong> <strong>Java</strong> sogenannte Monitore e<strong>in</strong>gesetzt.<br />
E<strong>in</strong> Monitor stellt sicher, dass immer nur der Thread, der die Zugriffsberechtigung zu den jeweiligen Daten besitzt, den<br />
durch ihn geschützten Code ausführen kann.<br />
◇ In <strong>Java</strong> ist mit jedem Objekt e<strong>in</strong> Monitor assoziiert, der nach entsprechender Aktivierung den Zugriff zu dem Objekt<br />
überwacht. Die Aktivierung des Monitors bezieht sich immer auf e<strong>in</strong>en bestimmten überwachten Codeabschnitt.<br />
Monitore werden mittels Locks (Zugriffssperren) verwaltet.<br />
E<strong>in</strong> Thread kann e<strong>in</strong>en Monitor belegen, <strong>in</strong> dem er e<strong>in</strong>en Lock auf den Monitor setzt ("lock the monitor").<br />
Solange der Thread den Lock auf den Monitor besitzt, kann er une<strong>in</strong>geschränkt zu dem von dem Monitor überwachten<br />
Objekt zugreifen.<br />
Versucht e<strong>in</strong> anderer Thread e<strong>in</strong>en Lock auf denselben Monitor (d.h. e<strong>in</strong>en Zugriff auf dasselbe Objekt) zu erlangen,<br />
muß er warten, bis der erste Thread den Lock wieder freigegeben hat ("unlock the monitor"). Erst dann kann er se<strong>in</strong>er-<br />
seits den Lock setzen und danach zu dem Objekt zugreifen.<br />
Versucht e<strong>in</strong> Thread e<strong>in</strong>en durch e<strong>in</strong>en aktivierten Monitor überwachten Codeabschnitt auszuführen, überprüft der<br />
Monitor, ob der Thread den benötigten Lock setzen darf. Wenn ja, darf er <strong>in</strong> den Codeabschnitt e<strong>in</strong>treten, wenn ne<strong>in</strong>,<br />
muß er warten bis der Lock freigegeben wird.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 732 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (2)<br />
• Demonstrationsprogramm zum Zugriffs-Wettlauf bei Multithread<strong>in</strong>g<br />
◇ Quellcode der Klasse LValBox (Datei LValBox.java)<br />
public class LValBox<br />
{<br />
private long val;<br />
}<br />
public LValBox(long lv)<br />
{ val=lv; }<br />
public long getVal()<br />
{ return val; }<br />
public void setVal(long lv)<br />
{ val=lv; }<br />
◇ Quellcode der Klasse LVBChangeThread (Datei LVBChangeThread.java)<br />
// LVBChangeThread.java<br />
public class LVBChangeThread extends Thread<br />
{ private LValBox vbox;<br />
}<br />
public LVBChangeThread(LValBox vb)<br />
{ vbox=vb; }<br />
public void run()<br />
{ long val = 0;<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 733 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Die synchronized-Anweisung<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Diese Anweisung dient zum Aktivieren des Monitors, mit dem der Zugriff zu e<strong>in</strong>em Objekt (Ziel-Objekt) synchroni-<br />
siert werden kann.<br />
Sie legt das betreffende Ziel-Objekt fest und def<strong>in</strong>iert die der Überwachung unterliegende Anweisungsfolge<br />
◇ Syntax :<br />
Der <strong>in</strong> runden Klammern stehende Ausdruck muß als Wert e<strong>in</strong>e Referenz auf e<strong>in</strong> Objekt ergeben.<br />
Er bestimmt das Objekt, zu dem der Zugriff synchronisiert werden soll (Ziel-Objekt).<br />
Die <strong>in</strong> geschweiften Klammern stehende Anweisungsfolge (der "Rumpf" derAnweisung) bildet den überwachten<br />
kritischen Codeabschnitt, <strong>in</strong> dem i.a. (aber nicht immer) zu dem Zielobjekt zugegriffen werden sollte.<br />
◇ Beispiel :<br />
◇ Wirkung :<br />
synchronized ( Ausdruck )<br />
▻ Die synchronized-Anweisung überprüft, ob der aufrufende Thread den Lock auf den Monitor des durch den<br />
Ausdruck referierten Objekts, das Ziel-Objekt, (im Beispiel : vbox) setzen kann (oder bereits besitzt).<br />
▻ Wenn ja, wird der Lock durch den Thread gesetzt und die im Rumpf stehende Anweisungsfolge ausgeführt.<br />
Nach Beendigung der Anweisungsfolge (entweder normal oder durch das Werfen e<strong>in</strong>er nicht gefangenen Exception)<br />
wird der Lock wieder freigegeben.<br />
▻ Wenn ne<strong>in</strong>, besitzt e<strong>in</strong> anderer Thread bereits den Lock. In dem Fall muß der aufrufende Thread warten, bis der<br />
Lock von dem besitzenden Thread wieder frei gegeben wird. Erst dann kann die Anweisung wie oben skizziert<br />
weiter ausgeführt werden.<br />
◇ Weitere Anmerkungen<br />
synchronized (vbox)<br />
{<br />
val=vbox.getVal();<br />
val++;<br />
vbox.setVal(val);<br />
}<br />
Anweisung<br />
{ }<br />
▻ Die synchronized-Anweisung bewirkt, dass das Setzen und Freigeben e<strong>in</strong>es Locks immer als Paar auftritt.<br />
Dadurch ist es nicht möglich, dass e<strong>in</strong> von e<strong>in</strong>em Thread gehaltener Lock von diesem nicht wieder freigegeben wird<br />
(ausser im Fall e<strong>in</strong>er Verklemmung)<br />
▻ Der Zugriff e<strong>in</strong>es Threads zu e<strong>in</strong>em Objekt, auf dessen Monitor e<strong>in</strong> anderer Thread den Lock besitzt, ohne Aktivie-<br />
rung der Monitor-Überwachung (d.h. ohne entsprechende synchronized-Anweisung) ist grundsätzlich möglich.<br />
In diesem Fall f<strong>in</strong>det ke<strong>in</strong>e Synchronisation statt.<br />
▻ Die synchronized-Anweisung erlaubt die Festlegung e<strong>in</strong>es beliebigen Objekts als Ziel-Objekt.<br />
Wird sie <strong>in</strong> dem Code, der das Ziel-Objekt verwendet, e<strong>in</strong>gesetzt, spricht man von client-seitiger Synchronisation.<br />
Damit die Synchronisation tatsächlich funktionieren kann, muß hierbei jeder das Objekt benutzende Client e<strong>in</strong>en<br />
synchronisierten Zugriff sicherstellen.<br />
Sie kann aber auch <strong>in</strong> den Memberfunktionen des Ziel-Objekts selbst e<strong>in</strong>gesetzt werden. In diesem Fall muss das<br />
Ziel-Objekt durch this referiert werden. Das Ziel-Objekt sorgt selbst für se<strong>in</strong>e Zugriffs-Synchronisation.<br />
E<strong>in</strong>e unsynchronisierte Verwendung durch Clients ist nicht möglich.<br />
Manchmal wird dies als server-seitige Synchronisation bezeichnet.<br />
▻ Da Synchronisation i.a. zu e<strong>in</strong>em Performenz-Verlust führen kann (Threads müssen auf Zugriff warten), sollte e<strong>in</strong><br />
Monitor-Lock immer nur so kurz wie möglich besessen werden, d.h. der überwachte Codeabschnitt sollte auf die<br />
unbed<strong>in</strong>gt notwendigen Anweisungen beschränkt werden.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 734 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (4)<br />
• Demonstrationsprogramm zur synchronized-Anweisung (client-seitige Synchronisation)<br />
◇ Quellcode der Klasse LValBox (Datei LValBox.java)<br />
public class LValBox<br />
{<br />
private long val;<br />
}<br />
public LValBox(long lv)<br />
{ val=lv; }<br />
public long getVal()<br />
{ return val; }<br />
public void setVal(long lv)<br />
{ val=lv; }<br />
◇ Quellcode der Klasse LVBChangeThreadSync (Datei LVBChangeThreadSync.java)<br />
// LVBChangeThreadSync.java<br />
public class LVBChangeThreadSync extends Thread<br />
{ private LValBox vbox;<br />
}<br />
public LVBChangeThreadSync(LValBox vb)<br />
{ vbox=vb; }<br />
public void run()<br />
{ long val = 0;<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 735 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• synchronized-Methoden<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (5)<br />
◇ Sowohl statische als auch nichtstatische Memberfunktionen können mit dem Methoden-Modifizierer<br />
synchronized def<strong>in</strong>iert werden.<br />
◇ Hierdurch wird e<strong>in</strong> Monitor für die gesamte Memberfunktion aktiviert.<br />
Die gesamte Memberfunktion unterliegt damit e<strong>in</strong>er Synchronisations-Überwachung.<br />
◇ Bei nichtstatischen Memberfunktionen ist das Ziel-Objekt, für das der Monitor aktiviert wird, das jeweils aktuelle<br />
Objekt, für das die Memberfunktion aufgerufen wird.<br />
Damit stellt die Modifizierung e<strong>in</strong>er nichtstatischen Memberfunktion mit synchronized e<strong>in</strong>e abkürzende Schreib-<br />
weise für e<strong>in</strong>e "normale" Memberfunktion dar, bei der der gesamte Funktionsrumpf <strong>in</strong> e<strong>in</strong>e synchronized-Anwei-<br />
sung mit der Ziel-Objekt-Referenz this e<strong>in</strong>geschlossen ist.<br />
Die beiden folgenden Formulierungen s<strong>in</strong>d <strong>in</strong> ihrer Wirkung identisch :<br />
public synchronized void myFunc()<br />
{<br />
// tue etwas<br />
}<br />
public void myFunc()<br />
{<br />
synchronized (this)<br />
{<br />
// tue etwas<br />
}<br />
}<br />
◇ Bei statischen Memberfunktionen ist das Ziel-Objekt das Class-Objekt, das mit der Klasse der Memberfunktion<br />
assoziiert ist.<br />
Auch hier gilt, dass die Modifizierung der Memberfunktion mit synchronized e<strong>in</strong>e abkürzende Schreibweise dar-<br />
stellt für e<strong>in</strong>e nicht-modifizierte Memberfunktion, bei der der gesamte Funktionsrumpf <strong>in</strong> e<strong>in</strong>e synchronized-An-<br />
weisung gekapselt ist.<br />
Wenn der Name der Klasse, zu der die statische Memberfunktion gehört, MyClass ist, lautet die Referenz auf das<br />
Ziel-Objekt hier MyClass.class (e<strong>in</strong> derartiger Ausdruck wird class literal genannt)<br />
Statische synchronized-Methoden können lediglich den Zugriff zu statischen Datenkomponenten der Klasse<br />
synchronisieren.<br />
◇ Der durch den Aufruf e<strong>in</strong>er statischen synchronized-Methode erlangte Besitz e<strong>in</strong>es Monitor-Locks für das<br />
Class-Objekt e<strong>in</strong>er Klasse hat ke<strong>in</strong>en E<strong>in</strong>fluß auf den Zugriff zu irgendwelchen Objekten dieser Klasse.<br />
E<strong>in</strong> Thread kann also durchaus nichtstatische synchronized-Methoden für e<strong>in</strong> Objekt e<strong>in</strong>er Klasse aufrufen,<br />
während e<strong>in</strong> anderer Thread e<strong>in</strong>en durch e<strong>in</strong>e statische Methode erworbenen Lock für das Class-Objekt dieser Klasse<br />
besitzt.<br />
◇ Die Def<strong>in</strong>ition von synchronized-Methoden implementiert immer e<strong>in</strong>e serverseitige Synchronisation.<br />
Clients können also das E<strong>in</strong>richten von Monitoren nicht "vergessen".<br />
Andererseits unterliegen hierbei immer vollständige Methoden der Synchronisations-Überwachung.<br />
Gegebenenfalls kann es effizienter se<strong>in</strong>, nur für die wirklich notwendigen Teile e<strong>in</strong>er Methode e<strong>in</strong>e entsprechende Über-<br />
wachung vorzusehen. Hierfür müssen dann entsprechende synchronized-Anweisungen e<strong>in</strong>gesetzt werden.<br />
Ausserdem ist serverseitige Synchronisation nicht immer möglich. So lassen sich read-modify-write-Zugriffe durch e<strong>in</strong>en<br />
Client i.a. nicht als Memberfunktion des Server-Objekts formulieren (Server-Objekt kennt Art des modify nicht)<br />
• Wirksamkeit der Synchronisation mittels synchronized-Anweisungen und -Methoden<br />
◇ Die durch synchronized-Anweisungen und –Methoden implementierte Synchronisation löst direkt nur das<br />
Problem der <strong>in</strong>konsistenten und fehlerhaften Daten bei nebenläufigem Lesen und Schreiben (Leser-Schreiber-Problem)<br />
(Sperrsynchronisation, gegenseitiger Ausschluß, mutual exclusion)<br />
◇ Das zu zeitabhängigen Ergebnissen führende Problem der gegenseitigen Datenabhängigkeit von Threads (Produzenten-<br />
Verbraucher-Problem, Reihenfolge des Zugriffs ist wichtig) lässt sich damit aber nicht ausreichend lösen. Hierfür muß<br />
die Sperrsynchronisation um zusätzliche Mechanismen ergänzt werden ( Zustands- bzw Ereignis-Synchronisation).<br />
Derartige Mechanismen werden z.B. durch Synchronisations-Methoden der Klasse Object zur Verfügung gestellt
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 736 – 00 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (6)<br />
• Die Methoden wait() und notify() der Klasse Object<br />
◇ Neben e<strong>in</strong>em Monitor ist jedem Objekt <strong>in</strong> <strong>Java</strong> auch e<strong>in</strong>e Warteliste (wait set) zugeordnet.<br />
In diese Warteliste werden Threads e<strong>in</strong>getragen, die vom Scheduler unterbrochen worden s<strong>in</strong>d und zu ihrer Fortsetzung<br />
auf den E<strong>in</strong>tritt e<strong>in</strong>es Ereignisses warten.<br />
Nach der Erzeugung e<strong>in</strong>es Objekts ist diese Warteliste leer.<br />
◇ Die <strong>in</strong> der Klasse Object def<strong>in</strong>ierten – nicht überschreibbaren – Methoden wait() und notify() <strong>in</strong>teragieren<br />
mit dem Scheduler und arbeiten mit der Warteliste des Objekts, für das sie jeweils aufgerufen werden.<br />
Sie stellen e<strong>in</strong>en weiteren Mechanismus zur Synchronisation von Threads zur Verfügung, der das Monitor-Konzept<br />
ergänzt.<br />
◇ Sowohl wait() als auch notify() dürfen nur für e<strong>in</strong> Objekt aufgerufen werden, dessen Monitor-Lock von<br />
dem jeweiligen aktuellen Thread besessen wird, d.h. sie dürfen nur <strong>in</strong>nerhalb von synchronized-Code<br />
verwendet werden.<br />
◇ E<strong>in</strong> Aufruf von wait() bewirkt, dass der aktuelle Thread angehalten, der von ihm besessene Lock auf den Monitor<br />
des Ziel-Objekts freigegeben und der Thread <strong>in</strong> die Thread-Warteliste des Ziel-Objekts e<strong>in</strong>getragen wird.<br />
Für den Scheduler wird dieser Thread als – auf e<strong>in</strong> Ereignis – wartend markiert.<br />
E<strong>in</strong> anderer – eventuell schon darauf wartender – Thread kann damit den Lock auf den Monitor des Objekts bekommen.<br />
◇ E<strong>in</strong> Aufruf von notify() kennzeichnet den E<strong>in</strong>tritt des Ereignisses, auf das die <strong>in</strong> der Warteliste e<strong>in</strong>getragenen<br />
Threads warten. Er bewirkt, dass e<strong>in</strong>er dieser Threads (oder auch alle) aufgeweckt, d.h. als ablaufbereit markiert wird.<br />
Damit kann dieser dann vom Scheduler wieder für die CPU-Zuteilung berücksichtigt werden. Wird er als nächster<br />
laufender Thread ausgewählt, bekommt er den Lock auf den Monitor des Objekts wieder zurück. Allerd<strong>in</strong>gs ist das erst<br />
dann möglich, wenn der Thread, der notify() aufgerufen hat, den Lock auf den Monitor des Objekts se<strong>in</strong>erseits<br />
wieder freigegeben hat.<br />
Der Weiterlauf des wartenden Threads führt zur Beendigung der von ihm aufgerufenen wait()-Methode.<br />
◇ Es gibt Varianten der wait()-Methode, mit der der aufrufende Thread e<strong>in</strong> Timeout-Interval festlegen kann, nachdem<br />
er spätestens aufgeweckt werden möchte, auch dann, wenn bis dah<strong>in</strong> ke<strong>in</strong> notify()-Aufruf für das Objekt erfolgt<br />
ist.<br />
◇ wait()-Methoden<br />
public f<strong>in</strong>al void wait() Veranlasst, dass der aktuelle Thread <strong>in</strong> den Wartezustand<br />
übergeht bis e<strong>in</strong> anderer Thread notify() oder<br />
notifyAll() für dasselbe Ziel-Objekt aufruft.<br />
Der aktuelle Thread muss den Lock für dieses Objekt besitzen.<br />
Der Lock wird für die Dauer des Wartezustands abgegeben<br />
public f<strong>in</strong>al void wait(long timeout) wie wait(), jedoch wird der Wartezustand spätestens nach<br />
Ablauf von timeout Millisek verlassen<br />
public f<strong>in</strong>al void wait(long timeout, wie wait(), jedoch wird der Wartezustand spätestens nach<br />
<strong>in</strong>t nanos) Ablauf von (timeout Millisek + nanos Nanosek)<br />
verlassen<br />
Jede der wait()-Methoden kann e<strong>in</strong>e InterruptedException werfen, die gefangen werden muß.<br />
Diese Exception wird geworfen, wenn e<strong>in</strong> anderer Thread für den wartenden Thread <strong>in</strong>terrupt() aufruft<br />
◇ notify()-Methoden<br />
public f<strong>in</strong>al void notify() Weckt e<strong>in</strong>en der Threads aus der Thread-Warteliste des Ziel-Objekts auf<br />
Welcher Thread aufgeweckt wird, kann nicht vorausgesagt werden<br />
public f<strong>in</strong>al void notifyAll() Weckt alle Threads aus der Thread-Warteliste des Ziel-Objekts auf
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 737 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (7)<br />
• Ereignissynchronisation mittels wait() und notify()<br />
◇ Unter Ereignis- oder Zustands-Synchronisation versteht man die Sicherstellung e<strong>in</strong>er def<strong>in</strong>ierten zeitlichen Reihen-<br />
folge bei der Abarbeitung von mehreren Threads.<br />
Die Reihenfolge wird durch den E<strong>in</strong>tritt bestimmter Ereignisse (bzw bestimmter Zustände) gesteuert.<br />
E<strong>in</strong> wartender Thread muss von e<strong>in</strong>em anderen Thread über den E<strong>in</strong>tritt e<strong>in</strong>es erwarteten Ereignisses <strong>in</strong>formiert werden<br />
Zwischen Threads muß e<strong>in</strong>e elementare Kommunikation stattf<strong>in</strong>den.<br />
◇ E<strong>in</strong>e def<strong>in</strong>ierte Abarbeitungs-Reihenfolge von Threads ist immer dann notwendig, wenn diese vone<strong>in</strong>ander datenab-<br />
hängig s<strong>in</strong>d. E<strong>in</strong> typisches Beispiel hierfür ist die Erzeugung von Daten durch e<strong>in</strong>en Thread und deren Verwendung<br />
durch e<strong>in</strong>en anderen Thread. Erzeuger-Verbraucher-Problem.<br />
◇ Die Object-Methoden wait() und notify() ermöglichen die für e<strong>in</strong>e Ereignissynchronisation notwendige<br />
elementare Thread-Kommunikation.<br />
E<strong>in</strong> Thread wartet bis e<strong>in</strong> bestimmtes Ereignis e<strong>in</strong>tritt, das e<strong>in</strong>e von ihm zu überprüfende Bed<strong>in</strong>gung bee<strong>in</strong>flusst haben<br />
könnte. Mittels notify() wird er von e<strong>in</strong>em anderen Thread über den E<strong>in</strong>tritt dieses Ereignisse <strong>in</strong>formiert.<br />
◇ Der Code zur Realisierung e<strong>in</strong>er Ereignissynchronisation kann sowohl <strong>in</strong> dem Objekt, auf das der Monitor-Lock<br />
bestehen muß (serverseitige Sync.) als auch <strong>in</strong> e<strong>in</strong>em anderen Objekt (z.B. im Thread-Objekt, clientseitige Sync.)<br />
enthalten se<strong>in</strong>.<br />
◇ Typische pr<strong>in</strong>zipielle Formulierung des Synchronisations-Codes :<br />
▻ im wartenden (empfangenden) Thread<br />
(hier <strong>in</strong> e<strong>in</strong>er Methode des Objekts auf das der Thread den Lock besitzt, serverseitige Synchronisation)<br />
synchronized void doSometh<strong>in</strong>g()<br />
{<br />
while (!bed<strong>in</strong>gung)<br />
wait();<br />
// Weiterarbeit<br />
}<br />
Anmerkung :<br />
Die Überprüfung der Bed<strong>in</strong>gung, die über Warten oder Weiterarbeit entscheidet, sollte unbed<strong>in</strong>gt<br />
<strong>in</strong> e<strong>in</strong>er Schleifenanweisung und nicht <strong>in</strong> e<strong>in</strong>er if-Anweisung erfolgen.<br />
Nur dann kann der Thread nach Beendigung der wait()-Anweisung auch überprüfen, ob die<br />
erwartete Bed<strong>in</strong>gung jetzt tatsächlich erfüllt ist. Sollte dies nicht der Fall se<strong>in</strong>, geht der Thread mit<br />
e<strong>in</strong>em erneuten wait()-Aufruf sofort wieder <strong>in</strong> den Wartezustand über.<br />
▻ im aufweckenden (sendenden) Thread<br />
(hier <strong>in</strong> e<strong>in</strong>er Methode des Objekts auf das der Thread den Lock besitzt, serverseitige Synchronisation)<br />
synchronized void changeCondition()<br />
{<br />
// tue etwas, das bed<strong>in</strong>gung veraendert<br />
notifyAll() // oder : notify()<br />
}<br />
• Unterbrechung von Threads mittels wait() und notify()<br />
◇ Die Methoden wait() und notify() können auch zur Unterbrechungssteuerung e<strong>in</strong>es typischerweise <strong>in</strong> e<strong>in</strong>er<br />
Schleife laufenden Threads e<strong>in</strong>gesetzt werden.<br />
◇ Dabei legt der Wert e<strong>in</strong>er logischen Variablen fest, ob der gesteuerte Thread unterbrochen werden oder weiterlaufen soll.<br />
Der gesteuerte Thread überprüft bei jedem Schleifendurchlauf diese Variable. Hat sie den Wert für "unterbrechen" legt<br />
sich der Thread durch den Aufruf von wait() "schlafen".<br />
Der steuernde Thread ändert den Wert dieser Variablen und <strong>in</strong>formiert den zu steuernden Thread mittels notify()<br />
wenn sie den Wert für "weiterlaufen" angenommen hat. Dadurch wird dieser wieder aufgeweckt und kann weiterlaufen.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 738 – 01 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (8-1)<br />
• Demonstrationsprogramm zum Erzeuger-Verbraucher-Problem<br />
◇ E<strong>in</strong> Erzeuger-Thread erzeugt laufend e<strong>in</strong>en zwischen 0 und 1000 liegenden <strong>in</strong>t-Wert und legt diesen <strong>in</strong> e<strong>in</strong>em<br />
Buffer ab. E<strong>in</strong> Verbraucher-Thread soll den im Buffer bef<strong>in</strong>dlichen <strong>in</strong>t-Wert jeweils wieder auslesen.<br />
◇ Quellcode des Interfaces IntBuffer (Datei IntBuffer.java)<br />
public <strong>in</strong>terface IntBuffer<br />
{ public void put(<strong>in</strong>t val);<br />
public <strong>in</strong>t get();<br />
public <strong>in</strong>t getBuffSize();<br />
}<br />
◇ Quellcode der Klasse IntErzeuger (Datei IntErzeuger.java)<br />
public class IntErzeuger extends Thread<br />
{ private IntBuffer buff;<br />
private <strong>in</strong>t cnt; // Anz. der zu erzeugenden Bufferfuellungen<br />
}<br />
public IntErzeuger(IntBuffer b, <strong>in</strong>t anz)<br />
{ buff = b;<br />
cnt = anz;<br />
}<br />
public void run()<br />
{ <strong>in</strong>t val;<br />
<strong>in</strong>t wdh=cnt*buff.getBuffSize();<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 738 – 02 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (8-2)<br />
• Demonstrationsprogramm zum Erzeuger-Verbraucher-Problem, Forts.<br />
◇ Ohne Ereignissynchronisation :<br />
Quellcode der Klasse UnsyncIntBuffer (Datei UnsyncIntBuffer.java)<br />
// UnsyncIntBuffer.java<br />
public class UnsyncIntBuffer implements IntBuffer<br />
{ private <strong>in</strong>t buff;<br />
}<br />
public synchronized void put(<strong>in</strong>t val)<br />
{ buff= val;<br />
}<br />
public synchronized <strong>in</strong>t get()<br />
{ <strong>in</strong>t val = buff;<br />
return val;<br />
}<br />
public <strong>in</strong>t getBuffSize()<br />
{ return 1;<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ IntBuffer ibuff = new UnsyncIntBuffer();<br />
new IntErzeuger(ibuff, 8).start();<br />
new IntVerbraucher(ibuff, 8).start();<br />
}<br />
◇ Beispiel für Start und Ausgabe des Programms
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 738 – 03 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (8-3)<br />
• Demonstrationsprogramm zum Erzeuger-Verbraucher-Problem, Forts.<br />
◇ Mit Ereignissynchronisation :<br />
Quellcode der Klasse SyncIntBuffer (Datei SyncIntBuffer.java)<br />
public class SyncIntBuffer implements IntBuffer<br />
{ private <strong>in</strong>t buff;<br />
private boolean voll;<br />
}<br />
public SyncIntBuffer()<br />
{ voll = false; }<br />
public synchronized void put(<strong>in</strong>t val)<br />
{ while (voll)<br />
{ try<br />
{ wait(); }<br />
catch (InterruptedException e) { }<br />
}<br />
buff = val;<br />
voll = true;<br />
notifyAll(); // Mitteilung, dass Buffer voll ist<br />
}<br />
public synchronized <strong>in</strong>t get()<br />
{ while (!voll)<br />
{ try<br />
{ wait(); }<br />
catch (InterruptedException e) { }<br />
}<br />
<strong>in</strong>t val = buff;<br />
voll = false;<br />
notifyAll(); // Mitteilung, dass Buffer leer ist<br />
return val;<br />
}<br />
public <strong>in</strong>t getBuffSize()<br />
{ return 1; }<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ IntBuffer ibuff = new SyncIntBuffer();<br />
new IntErzeuger(ibuff, 8).start();<br />
new IntVerbraucher(ibuff, 8).start();<br />
}<br />
◇ Beispiel für Start und Ausgabe des Programms
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 739 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (9-1)<br />
• Demonstrationsprogramm zum Unterbrechen/Weiterlaufen von Threads, Teil 1<br />
◇ Quellcode der Klasse Bl<strong>in</strong>kDemo2 (Datei Bl<strong>in</strong>kDemo2.java)<br />
import java.awt.*;<br />
import java.awt.event.*;<br />
import javax.sw<strong>in</strong>g.*;<br />
public class Bl<strong>in</strong>kDemo2 extends JFrame<br />
{ Conta<strong>in</strong>er c;<br />
Bl<strong>in</strong>kPanel blkpan;<br />
Bl<strong>in</strong>kThread2 blkthr = null;<br />
}<br />
public Bl<strong>in</strong>kDemo2()<br />
{ super("Bl<strong>in</strong>kDemo2");<br />
c=getContentPane();<br />
blkpan = new Bl<strong>in</strong>kPanel(Color.YELLOW, Color.BLUE);<br />
c.add(blkpan);<br />
setSize(250, 170);<br />
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />
blkpan.addMouseListener(new MouseAdapter()<br />
{ public void mouseClicked(MouseEvent e)<br />
{ System.out.pr<strong>in</strong>tln(Thread.currentThread());<br />
if (blkthr==null)<br />
{ blkthr = new Bl<strong>in</strong>kThread2(Bl<strong>in</strong>kDemo2.this);<br />
blkthr.start();<br />
}<br />
else<br />
synchronized(blkthr)<br />
{ blkthr.toggleBreak();<br />
blkthr.notify();<br />
}<br />
}<br />
}<br />
);<br />
}<br />
public void bl<strong>in</strong>k()<br />
{ blkpan.chgCol();<br />
repa<strong>in</strong>t();<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{ Bl<strong>in</strong>kDemo2 blkdemo = new Bl<strong>in</strong>kDemo2();<br />
blkdemo.setVisible(true);<br />
}<br />
◇ Vom Programm erzeugtes Fenster (beide Bl<strong>in</strong>kzustände)
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – 739 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Synchronisation von Threads <strong>in</strong> <strong>Java</strong> (9-2)<br />
• Demonstrationsprogramm zum Unterbrechen/Weiterlaufen von Threads, Teil2<br />
◇ Quellcode der Klasse Bl<strong>in</strong>kPanel (Datei Bl<strong>in</strong>kPanel.java)<br />
s. Demonstrationsprogramm zum gezielten vorzeitigen Beenden e<strong>in</strong>es Threads (V-JV-722-02)<br />
◇ Quellcode der Klasse Bl<strong>in</strong>kThread2 (Datei Bl<strong>in</strong>kThread2.java)<br />
// Bl<strong>in</strong>kThread2.java<br />
public class Bl<strong>in</strong>kThread2 extends Thread<br />
{<br />
private Bl<strong>in</strong>kDemo2 blkdem;<br />
private boolean unterbrechung;<br />
}<br />
public Bl<strong>in</strong>kThread2(Bl<strong>in</strong>kDemo2 bd)<br />
{<br />
blkdem=bd;<br />
unterbrechung=false;<br />
}<br />
public void toggleBreak()<br />
{<br />
unterbrechung = !unterbrechung;<br />
}<br />
public void run()<br />
{<br />
System.out.pr<strong>in</strong>tln(Thread.currentThread() + " Beg<strong>in</strong>");<br />
System.out.pr<strong>in</strong>tln("Anz. aktiver Threads : " + Thread.activeCount());<br />
while (true)<br />
{<br />
try<br />
{<br />
synchronized (this)<br />
{<br />
while(unterbrechung)<br />
wait();<br />
}<br />
blkdem.bl<strong>in</strong>k();<br />
Thread.sleep(500);<br />
}<br />
catch (InterruptedException e) { break;}<br />
}<br />
System.out.pr<strong>in</strong>tln(Thread.currentThread() + " Ende");<br />
}
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 741 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
• Pipes<br />
Thread-Kommunikation über Pipes <strong>in</strong> <strong>Java</strong> (1)<br />
◇ E<strong>in</strong>e Pipe ist e<strong>in</strong> unidirektionaler Kommunikationskanal, über den zwei Prozesse bzw Threads gekoppelt werden<br />
können :<br />
E<strong>in</strong>e Pipe besitzt e<strong>in</strong>e Schreibseite und e<strong>in</strong>e Leseseite.<br />
E<strong>in</strong> Prozess/Thread ist mit der Schreibseite verbunden und schreibt Daten <strong>in</strong> die Pipe, der andere Prozess/Thread ist mit<br />
der Leseseite verbunden und liest die geschriebenen Daten <strong>in</strong> genau der gleichen Reihenfolge wieder aus.<br />
◇ Pipes s<strong>in</strong>d spezielle Streams. Sie werden also dateiähnlich verwendet, mit der Besonderheit, dass zur Schreibseite e<strong>in</strong>er<br />
Pipe nur schreibend und zur Leseseite nur lesend zugegriffen werden kann.<br />
◇ Pipes werden mittels e<strong>in</strong>es im Arbeitsspeicher angelegten Puffers implementiert.<br />
Wenn der Puffer voll ist, blockiert der schreibende Prozess/Thread , wenn der Puffer leer ist blockiert der lesende<br />
Prozess/Thread.<br />
Pipes stellen e<strong>in</strong>en Synchronisationsmechanismus zur Verfügung, mit dem sich das Erzeuger-/Verbraucher-<br />
Problem sehr effizient lösen lässt.<br />
• Pipes <strong>in</strong> <strong>Java</strong><br />
◇ In <strong>Java</strong> lassen sich Pipes sowohl als Byte-Streams als auch als Zeichen-Streams realisieren.<br />
Hierfür existieren – im Package java.io – die Klassen<br />
▻ PipedOutputStream (abgeleitet von OutputStream) und<br />
PipedInputStream (abgeleitet von InputStream) (Byte-Streams), sowie<br />
▻ PipedWriter (abgeleitet von Writer) und<br />
PipedReader (abgeleitet von Reader) (Zeichen-Streams).<br />
◇ Objekte der Klasse PipedOutputStream bilden die Schreibseite, Objekte der Klasse PipedInputStream<br />
bilden die Leseseite e<strong>in</strong>er Pipe. Sie werden immer paarweise und immer <strong>in</strong> verschiedenen Threads e<strong>in</strong>gesetzt.<br />
Analoges gilt für Objekte der Klassen PipedWriter und PipedReader.<br />
◇ Klassendiagramme<br />
OutputStream<br />
PipedOutputStream<br />
Byte-Stream-Pipe Zeichen-Stream-Pipe<br />
1 1<br />
InputStream<br />
PipedInputStream<br />
Writer<br />
PipedWriter<br />
1 1<br />
◇ Die Kopplung zwischen je e<strong>in</strong>em PipedOutputStream- und e<strong>in</strong>em PipedInputStream-Objekt (bzw e<strong>in</strong>em<br />
PipedWriter- und e<strong>in</strong>em PipedReader-Objekt) kann gleich bei der Objekterzeugung (Konstruktor-Parameter)<br />
oder später mittels e<strong>in</strong>er geeigneten Memberfunktion erfolgen.<br />
Dabei ist es gleichgültig, ob e<strong>in</strong> PipedInputStream-Objekt an e<strong>in</strong> PipedOutputStream-Objekt (bzw e<strong>in</strong><br />
PipedReader-Objekt an e<strong>in</strong> PipedWriter-Objekt) gekoppelt wird oder umgekehrt.<br />
Wenn bereits e<strong>in</strong>e Kopplung besteht, führt der Versuch e<strong>in</strong>er erneuten Kopplung zum Werfen e<strong>in</strong>er IOException.<br />
◇ Der für e<strong>in</strong>e Pipe verwendete Puffer umfasst 1024 Bytes. Diese Größe kann nicht verändert werden.<br />
Reader<br />
PipedReader<br />
◇ Der Versuch der Verwendung (Schreiben bzw Lesen) e<strong>in</strong>es Pipe-Stream-Objekts, das nicht an e<strong>in</strong>e Gegenseite<br />
gekoppelt ist, führt zum Werfen e<strong>in</strong>er IOException.<br />
Dies ist z.B. auch dann der Fall, wenn der Thread der Gegenseite zwischenzeitlich beendet worden ist.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 742 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Thread-Kommunikation über Pipes <strong>in</strong> <strong>Java</strong> (2)<br />
• Die Klasse PipedOutputStream (Package java.io)<br />
◇ Objekte dieser Klasse bilden die Schreibseite e<strong>in</strong>er Byte-Stream-Pipe.<br />
◇ Konstruktoren<br />
public PipedOutputStream() Erzeugung e<strong>in</strong>es PipedOutputStream-<br />
Objekts, das an ke<strong>in</strong> PipedInputStream-<br />
Objekt (Pipe-Leseseite) gekoppelt ist<br />
public PipedOutputStream(PipedInputStream snk) Erzeugung e<strong>in</strong>es PipedOutputStream-<br />
throws IOException Objekts, das an das PipedInputStream-<br />
Objekt snk (Pipe-Leseseite) gekoppelt ist.<br />
◇ Memberfunktionen<br />
Die Klasse PipedOutputStream stellt das durch ihre Basisklasse OutputStream def<strong>in</strong>ierte Zugriffs-<br />
Interface zur Verfügung<br />
public void write(<strong>in</strong>t b) Schreiben des niederwertigen Bytes von b<br />
public void write(byte[] buff) Schreiben des Byte-Buffers buff<br />
public void write(byte[] buff, <strong>in</strong>t pos, Schreiben von len Bytes aus dem Buffer buff ab<br />
<strong>in</strong>t len) der Position pos<br />
public void flush() Übergabe aller gepufferten Schreib-Bytes an den Pipe-Buffer<br />
public void close() Schliessen des Streams (Pipe-Schreibseite)<br />
Zusätzlich ist def<strong>in</strong>iert :<br />
public void connect(PipedInputStream snk) Kopplung des aktuellen Objekts an das<br />
PipedInputStream-Objekt snk (Pipe-Leseseite)<br />
Alle Methoden werfen e<strong>in</strong>e IOException, wenn e<strong>in</strong> I/O-Fehler auftritt (z.B: Schreibversuch bei fehlender Pipe-<br />
Kopplung)<br />
• Die Klasse PipedWriter (Package java.io)<br />
◇ Objekte dieser Klasse bilden die Schreibseite e<strong>in</strong>er Zeichen-Stream-Pipe.<br />
◇ Es existieren<br />
▻ analoge Konstruktoren (Default-Konstruktor und Konstruktor zur Kopplung an e<strong>in</strong>PipedReader-Objekt) und<br />
▻ analoge Memberfunktionen (Interface der Basisklasse Writer, sowie Methode connect(...))<br />
wie bei der Klasse PipedOutputStream.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 743 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
Thread-Kommunikation über Pipes <strong>in</strong> <strong>Java</strong> (3)<br />
• Die Klasse PipedInputStream (Package java.io)<br />
◇ Objekte dieser Klasse bilden die Leseseite e<strong>in</strong>er Byte-Stream-Pipe.<br />
◇ Konstruktoren<br />
public PipedInputStream() Erzeugung e<strong>in</strong>es PipedInputStream-<br />
Objekts, das an ke<strong>in</strong> PipedOutputStream-<br />
Objekt (Pipe-Schreibseite) gekoppelt ist<br />
public PipedInputStream(PipedOutputStream src) Erzeugung e<strong>in</strong>es PipedInputStream-<br />
throws IOException Objekts, das an das PipedOutputStream-<br />
Objekt src (Pipe-Schreibseite) gekoppelt ist.<br />
◇ Memberfunktionen<br />
Die Klasse PipedInputStream stellt das durch ihre Basisklasse InputStream def<strong>in</strong>ierte Zugriffs-<br />
Interface zur Verfügung.<br />
Allerd<strong>in</strong>gs werden die Methoden mark(...) und reset() nicht unterstützt.<br />
public <strong>in</strong>t read() Lesen des nächsten Bytes aus der Pipe (==Funktionswert)<br />
Funktionswert==-1, wenn Schreibseite geschlossen<br />
public <strong>in</strong>t read(byte[] buff) Lesen e<strong>in</strong>er Byte-Folge, Ablage im Buffer buff<br />
Funktionswert : Anz. gelesener Bytes<br />
bzw –1, wenn Schreibseite geschlossen<br />
public <strong>in</strong>t read(byte[] buff, <strong>in</strong>t pos, Lesen von maximal len Bytes, Ablage imBuffer buff<br />
<strong>in</strong>t len) ab der Position pos<br />
Funktionswert : Anz. gelesener Bytes, bzw –1 (wie oben)<br />
public <strong>in</strong>t available() Ermittlung der Anzahl Bytes, die <strong>in</strong> der Pipe verfügbar s<strong>in</strong>d,<br />
d.h. ohne Blockierung gelesen werden können<br />
public long skip(long n) Überlesen der nächsten (maximal) n Bytes<br />
Funktionswert : Anzahl der tatsächlich überlesenen Bytes<br />
public void close() Schliessen des Streams (Pipe-Leseseite)<br />
Zusätzlich ist u.a. def<strong>in</strong>iert :<br />
public void connect(PipedOutputStream src) Kopplung des aktuellen Objekts an das<br />
PipedOutputStream-Objekt src (Pipe-Schreibs.)<br />
Alle Methoden werfen e<strong>in</strong>e IOException, wenn e<strong>in</strong> I/O-Fehler auftritt (z.B: Leseversuch bei fehlender Pipe-<br />
Kopplung)<br />
• Die Klasse PipedReader (Package java.io)<br />
◇ Objekte dieser Klasse bilden die Leseseite e<strong>in</strong>er Zeichen-Stream-Pipe.<br />
◇ Es existieren<br />
▻ analoge Konstruktoren (Default-Konstruktor und Konstruktor zur Kopplung an e<strong>in</strong>PipedWriter-Objekt) und<br />
▻ analoge Memberfunktionen (Interface der Basisklasse Reader, sowie Methode connect(...))<br />
wie bei der Klasse PipedInputStream.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 744 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Thread-Kommunikation über Pipes <strong>in</strong> <strong>Java</strong> (4-1)<br />
• Demonstrationsprogramm zur Lösung des Erzeuger-Verbraucher-Problems mittels Pipes<br />
◇ E<strong>in</strong> Erzeuger-Thread erzeugt laufend e<strong>in</strong>en zwischen 0 und 1000 liegenden <strong>in</strong>t-Wert und schreibt diesen<br />
<strong>in</strong> e<strong>in</strong>e Pipe.<br />
E<strong>in</strong> Verbraucher-Thread liest die erzeugten Werte aus der Pipe.<br />
◇ Zur vere<strong>in</strong>fachten Übertragung der <strong>in</strong>t-Werte <strong>in</strong> B<strong>in</strong>ärdarstellung werden der Pipe Filter vor- bzw nachgeschaltet :<br />
▻ der Pipe-Schreibseite (PipedOutputStream-Objekt) wird e<strong>in</strong> DataOutputStream-Objekt vorgeschaltet<br />
▻ der Pipe-Leseseite (PipedInputStream-Objekt) wird e<strong>in</strong> DataInputStream-Objekt nachgeschaltet<br />
◇ Quellcode der Klasse IntErzeugerPiped (Datei IntErzeugerPiped.java)<br />
// IntErzeugerPiped.java<br />
import java.io.*;<br />
public class IntErzeugerPiped extends Thread<br />
{<br />
private PipedOutputStream outpipe;<br />
private <strong>in</strong>t cnt;<br />
}<br />
public IntErzeugerPiped(PipedOutputStream op, <strong>in</strong>t anz)<br />
{<br />
outpipe = op;<br />
cnt = anz;<br />
}<br />
public void run()<br />
{<br />
try<br />
{<br />
DataOutputStream pout = null;<br />
try<br />
{<br />
<strong>in</strong>t val;<br />
pout = new DataOutputStream(outpipe);<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 744 – 02 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Thread-Kommunikation über Pipes <strong>in</strong> <strong>Java</strong> (4-2)<br />
• Demonstrationsprogramm zur Lösung des Erzeuger-Verbraucher-Problems mittels Pipes, Forts.<br />
◇ Quellcode der Klasse IntVerbraucherPiped (Datei IntVerbraucherPiped.java)<br />
// IntVerbraucherPiped.java<br />
import java.io.*;<br />
public class IntVerbraucherPiped extends Thread<br />
{<br />
private PipedInputStream <strong>in</strong>pipe;<br />
private <strong>in</strong>t cnt;<br />
}<br />
public IntVerbraucherPiped(PipedInputStream ip, <strong>in</strong>t anz)<br />
{<br />
<strong>in</strong>pipe = ip;<br />
cnt = anz;<br />
}<br />
public void run()<br />
{<br />
try<br />
{<br />
<strong>in</strong>t val;<br />
DataInputStream p<strong>in</strong> = new DataInputStream(<strong>in</strong>pipe);<br />
for (<strong>in</strong>t i=0; i
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 744 – 03 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Thread-Kommunikation über Pipes <strong>in</strong> <strong>Java</strong> (4-3)<br />
• Demonstrationsprogramm zur Lösung des Erzeuger-Verbraucher-Problems mittels Pipes, Forts.<br />
◇ Quellcode der Klasse PipeDemo (Datei PipeDemo.java)<br />
// PipeDemo.java<br />
import java.io.*;<br />
public class PipeDemo<br />
{<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{<br />
PipedOutputStream opipe = new PipedOutputStream();<br />
PipedInputStream ipipe = new PipedInputStream(opipe);<br />
new IntErzeugerPiped(opipe, 12).start();<br />
new IntVerbraucherPiped(ipipe, 13).start();<br />
}<br />
}<br />
◇ Beispiel für Start und Ausgabe des Programms
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 800 – 00 – TH – 03<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Kapitel 8<br />
8. <strong>Java</strong> <strong>in</strong> verteilten Systemen<br />
8.1. Socket-basierte Kommunikation<br />
8.2. Remote Method Invocation (RMI)
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 801 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Verteilte Systeme<br />
Grundlegendes zu verteilten Systemen<br />
◇ Verteilte Systeme bestehen aus zwei oder mehr unabhängigen aber mite<strong>in</strong>ander verbundenen Rechnern (z.B. über<br />
e<strong>in</strong> Netzwerk), die zur geme<strong>in</strong>samen Lösung von Aufgaben e<strong>in</strong>gesetzt werden können.<br />
◇ Die geme<strong>in</strong>sam zu lösende Aufgabe wird auf mehrere Prozesse aufgeteilt, die auf unterschiedlichen Rechnern laufen.<br />
Verteilte Anwendung<br />
◇ Die an e<strong>in</strong>er verteilten Anwendung beteiligten Prozesse müssen mite<strong>in</strong>ander Informationen austauschen. Die dafür<br />
notwendige Interprozess-Kommunikation über Rechnergrenzen h<strong>in</strong>weg erfordert die Def<strong>in</strong>ition und E<strong>in</strong>haltung<br />
bestimmter Schnittstellen und Protokolle.<br />
Derartige Protokolle können auf unterschiedlichen Ebenen (Schichten) e<strong>in</strong>gesetzt werden.<br />
• Client-Server-Modell<br />
◇ Am häufigsten arbeiten verteilte Anwendungen nach dem Client-Server-Modell :<br />
E<strong>in</strong> Server-Prozess stellt Dienstleistungen über e<strong>in</strong>e def<strong>in</strong>ierte Schnittstelle zur Verfügung. Diese Dienstleistungen<br />
können von Client-Prozessen genutzt werden.<br />
◇ Die Kommunikation zwischen Client und Server folgt dem – asymmetrischen – Request-Response-Pr<strong>in</strong>zip :<br />
E<strong>in</strong> Client richtet zu e<strong>in</strong>em beliebigen Zeitpunkt – also asynchron – e<strong>in</strong>e Anfrage (request) an den auf Anfragen wartenden<br />
Server. Der Server antwortet (response) i.a. <strong>in</strong>nerhalb e<strong>in</strong>er bestimmten Zeit – also synchron – auf diese Anfrage.<br />
◇ Häufig kann e<strong>in</strong> Server gleichzeitig zu mehreren Clients Kommunikationsbeziehungen unterhalten (Multithread-<br />
Server)<br />
◇ Verteilte Anwendungen, bei denen die beteiligten Prozesse sowohl als Server als auch als Client agieren, arbeiten nach<br />
dem Peer-to-Peer-Modell<br />
◇ Pr<strong>in</strong>zipiell werden zwei Verb<strong>in</strong>dungsarten e<strong>in</strong>er Rechnergrenzen überschreitenden Interprozess-Kommunikation<br />
unterschieden :<br />
▻ verb<strong>in</strong>dungsorientierte Kommunikation :<br />
Zwischen Client und Server wird für die Dauer der Kommunikation e<strong>in</strong>e ständige – virtuelle – Verb<strong>in</strong>dung herge-<br />
stellt. Diese Verb<strong>in</strong>dung muss aufgebaut werden, bevor die eigentliche Kommunikation stattf<strong>in</strong>den kann.<br />
Die e<strong>in</strong>zelnen Sendeoperationen benötigen ke<strong>in</strong>e expliziten Angaben über die Empfängeradresse.<br />
▻ verb<strong>in</strong>dungslose Kommunikation :<br />
Zwischen Client und Server existiert ke<strong>in</strong>e ständige Kommunikationsverb<strong>in</strong>dung. Diese wird vielmehr mit jeder<br />
e<strong>in</strong>zelnen Sendeoperation neu hergestellt.<br />
Jeder Sendeoperation muss die Adresse des Empfängers explizit mitgegeben werden.<br />
• Programmierschnittstellen<br />
◇ Die programmtechnische Implementierung von Client-Server-Kommunikationen kann auf unterschiedlichen Schichten<br />
erfolgen (OSI-Schichten-Modell der Rechnerkommunikation !)<br />
◇ Am weitesten verbreitet s<strong>in</strong>d heute :<br />
▻ Sockets, Programmierschnittstelle der Transportschicht (bzw Vermittlungsschicht)<br />
Sockets def<strong>in</strong>ieren den jeweiligen Kommunikations-Endpunkt e<strong>in</strong>er logischen Verb<strong>in</strong>dung zwischen Server und<br />
Client. Sie basieren auf dem für die jeweilige Verb<strong>in</strong>dung e<strong>in</strong>gesetzten Kommunikationsprotokoll-Typ und den<br />
von diesem verwendeten Adress-Angaben. Es gibt unterschiedliche Socket-Typen<br />
Sockets ermöglichen e<strong>in</strong>e bidirektionale Kommunikation (Senden und Empfangen) mittels I/O-Operationen<br />
analog zu Datei- bzw Stream-Zugriffen.<br />
E<strong>in</strong>e Kommunikation über e<strong>in</strong>en Socket kann erst stattf<strong>in</strong>den, wenn er an e<strong>in</strong>e lokale Adresse gebunden ist<br />
▻ Prozedur-Fernaufrufe (Remote Procedure Calls), Programmierschnittstelle der Anwendungsschicht<br />
Sie ermöglichen den Aufruf von Unterprogrammen (Funktionen), die sich <strong>in</strong> e<strong>in</strong>em anderen Prozessraum be-<br />
f<strong>in</strong>den unter Anwendung der gleichen Semantik wie für den Aufruf lokaler Unterprogramme.<br />
Die Implementierung dieses Konzepts <strong>in</strong> <strong>Java</strong> wird Remote Method Invocation (RMI) genannt. RMI erlaubt den<br />
Aufruf von Methoden für Objekte, die sich <strong>in</strong> e<strong>in</strong>er anderen JVM (i.a. auf e<strong>in</strong>em anderen Rechner) bef<strong>in</strong>den.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 811 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (1)<br />
• Pr<strong>in</strong>zip der verb<strong>in</strong>dungsorientierten Socket-Kommunikation<br />
◇ Der Server-Prozess erzeugt e<strong>in</strong>en Socket, den er an e<strong>in</strong>e lokale Adresse (Server-Adresse) b<strong>in</strong>det.<br />
Art und Aufbau der Adresse hängen von der für die Kommunikation e<strong>in</strong>gesetzten Protokoll-Familie ab.<br />
An diesem Socket wartet der Server auf Verb<strong>in</strong>dungswünsche durch Clients ("Horch"-Socket).<br />
◇ E<strong>in</strong> Client-Prozess <strong>in</strong>itiiert e<strong>in</strong>e Verb<strong>in</strong>dung zum Server, <strong>in</strong> dem er e<strong>in</strong>en Socket erzeugt und über diesen e<strong>in</strong>en<br />
Verb<strong>in</strong>dungswunsch an die Server-Adresse sendet.<br />
◇ Falls der Server-Prozess den Verb<strong>in</strong>dungswunsch akzeptiert, erzeugt er e<strong>in</strong>en neuen Socket, über den dann die eigent-<br />
liche Kommunikation mit dem Client stattf<strong>in</strong>den kann ("Kommunikations"-Socket).<br />
◇ Die anschliessende eigentliche Client-Server-Kommunikation erfolgt über die Sockets mittels dateianaloger Schreib-<br />
und Lese-Operationen<br />
◇ Die Kommunikation wird beendet, wenn der Client-Socket oder/und der "Kommunikations"-Socket des Servers<br />
geschlossen werden.<br />
◇ E<strong>in</strong> sequentieller Server kann erst nach Abschluss e<strong>in</strong>er Client-Kommunikation auf weitere Verb<strong>in</strong>dungswünsche<br />
warten.<br />
Bei e<strong>in</strong>em Multi-Thread-Server f<strong>in</strong>det jede Client-Kommunikation <strong>in</strong> e<strong>in</strong>em seperaten Thread statt.<br />
E<strong>in</strong> derartiger Server kann auf weitere Verb<strong>in</strong>dungswünsche unmittelbar nach Erzeugung des Kommunikations-Threads<br />
warten<br />
◇ Pr<strong>in</strong>zipieller Ablauf :<br />
Client<br />
Erzeugung e<strong>in</strong>es Sockets<br />
Verb<strong>in</strong>dungswunsch<br />
an die Server-Adresse<br />
Schreib-Operation<br />
Lese-Operation<br />
Schliessen<br />
des Sockets<br />
Verb<strong>in</strong>dungsaufnahme<br />
Kommunikation<br />
Server<br />
Erzeugung<br />
e<strong>in</strong>es "Horch"-Sockets<br />
B<strong>in</strong>dung an die Server-Adresse<br />
Warten auf<br />
Verb<strong>in</strong>dungswünsche<br />
durch Clients<br />
Akzeptieren e<strong>in</strong>es<br />
Verb<strong>in</strong>dungswunsches<br />
Erzeugung e<strong>in</strong>es<br />
"Kommunikations"-Sockets<br />
Lese-Operation<br />
Schreib-Operation<br />
Schliessen des<br />
"Kommunikations"-Sockets<br />
Multi-Thread-<br />
Multi-Thread-<br />
Server<br />
Server<br />
sequentieller Server
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 812 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• INET-Sockets<br />
Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (2)<br />
◇ INET-Sockets s<strong>in</strong>d Sockets für die TCP/IP-Protokoll-Familie.<br />
Diese Protokoll-Familie hat derzeit für die Rechnerkommunikation die grösste Bedeutung.<br />
U.a. wird sie im Internet, aber auch <strong>in</strong> den meisten lokalen Netzen e<strong>in</strong>gesetzt.<br />
◇ Adressen der TCP/IP-Protokoll-Familie (INET-Adressen) bestehen aus zwei Komponenten :<br />
▻ IP-Adresse : Sie bestimmt den Rechner, auf dem e<strong>in</strong> Prozess läuft<br />
4 Bytes (IP4-Adresse) bzw 16 Bytes (IP6-Adresse) gross.<br />
▻ Port-Nummer : Sie identifiziert den Prozess (Applikation) auf e<strong>in</strong>em Rechner.<br />
2 Bytes gross : ganze Zahl zwischen 0 und 65535<br />
(0 bis 1023 reserviert für systemnahe Dienste, well-known ports)<br />
◇ Zur besseren Verständlichkeit für den benutzenden Menschen werden IP-Adressen häufig auf Rechner-Namen<br />
(host names) abgebildet.<br />
Die Umsetzung von Rechner-Namen <strong>in</strong> IP-Adressen erfolgt u.a. durch Doma<strong>in</strong> Name Server (DNS).<br />
◇ Die beiden wichtigsten Protokolle dieser Protokoll-Familie s<strong>in</strong>d :<br />
▻ TCP (Transmission Control Protocol)<br />
▻ UDP (User Datagram Protocol)<br />
◇ TCP ist e<strong>in</strong> Protokoll für die verb<strong>in</strong>dungsorientierte Kommunikation.<br />
Es arbeitet streambasiert und mit Fehlerkontrolle. Dadurch bietet es Schutz gegen Datenverlust und Übertragungsfehler.<br />
Ausserdem stellt es die Beibehaltung der Daten-Reihenfolge sicher (sequenc<strong>in</strong>g). zuverlässiges Protokoll<br />
Sockets für dieses Protokoll werden als Stream-Sockets bezeichnet.<br />
◇ UDP ist e<strong>in</strong> Protokoll für die verb<strong>in</strong>dungslose Kommunikation.<br />
Es arbeitet paketbasiert (Übertragung unabhängiger Datenpakete == Datagramme) sowie ohne Fehlerkontrolle und<br />
Sequenc<strong>in</strong>g. Dadurch s<strong>in</strong>d weder Verlustlosigkeit und Fehlerfreiheit noch die Beibehaltung der Datenreihenfolge<br />
sichergestellt. unzuverlässiges Protokoll. Dafür ist die Übertragungsleistung dieses Protokolls höher.<br />
Sockets für dieses Protokoll werden Datagram-Sockets genannt.<br />
• Unterstützung von INET-Sockets <strong>in</strong> <strong>Java</strong><br />
◇ Die Implementierung von verteilten Anwendungen mittels INET-Sockets werden <strong>in</strong> <strong>Java</strong> sehr effizient durch geeignete<br />
Klassen der Standard-Bibliothek unterstützt. Die entsprechenden Klassen bef<strong>in</strong>den sich im Package java.net.<br />
◇ Zur Implementierung von Stream-Sockets existieren die Klassen<br />
▻ ServerSocket : Klasse für "Horch"-Sockets <strong>in</strong> Server-Prozessen<br />
▻ Socket : Klasse für "Kommunikations"-Sockets <strong>in</strong> Client- und Server-Prozessen<br />
◇ Die Implementierung e<strong>in</strong>er verb<strong>in</strong>dungslosen Kommunikation über Datagram-Sockets ermöglichen die Klassen :<br />
▻ DatagramSocket : Klasse für Datagramm-Sockets<br />
▻ DatagramPacket : Klasse zur Beschreibung der zu übertragenen Datenpakete<br />
◇ Socket-Adressen werden repräsentiert durch<br />
▻ SocketAddress : abstrakte Basisklasse für Socket-Adressen, ke<strong>in</strong>e konkrete Protokollb<strong>in</strong>dung<br />
▻ InetSocketAddress : konkrete Klasse für Adressen der TCP/IP-Protokoll-Familie (INET-Adresse)<br />
◇ Zur Repräsentation von IP-Adressen existieren die Klassen :<br />
▻ InetAddress : Darstellung sowohl von IP4-Adressen (4-Bytes) als auch IP6-Adressen (16 Bytes)<br />
▻ Inet4Address : Darstellung von IP4-Adressen (abgeleitet von InetAddress)<br />
▻ Inet6Address : Darstellung von IP6-Adressen (abgeleitet von InetAddress)<br />
◇ Zur Repräsentation von Internet-Resourcen referierenden URLs (Uniform Resource Locator) dient die Klasse<br />
▻ URL<br />
◇ Über die o.a. Klassen h<strong>in</strong>aus umfasst das Package java.net noch e<strong>in</strong>e Reihe weiterer Klassen.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 813 – 00 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Die Klasse InetAddress<br />
◇ Enthalten im Package java.net.<br />
Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (3)<br />
◇ Objekte dieser Klasse repräsentieren IP-Adressen<br />
Über Variable dieses Typs werden tatsächlich Inet4Address-Objekte (für IP4-Adressen (4-Bytes)) bzw<br />
Inet6Address-Objekte (für IP6-Adressen (16 Bytes)) referiert.<br />
Die Klasse InetAddress stellt e<strong>in</strong> geme<strong>in</strong>sames Verwendungs<strong>in</strong>terface für beide Arten von IP-Adressen zur<br />
Verfügung<br />
◇ Die Klasse besitzt ke<strong>in</strong>e öffentlichen Konstruktoren.<br />
Zur Objekterzeugung existieren statische Memberfunktionen. Diesen kann entweder die IP-Adresse (als Byte-Array<br />
oder als Str<strong>in</strong>g <strong>in</strong> dotted decimal notation) oder (gegebenenfalls und) der Rechnername übergeben werden.<br />
Bei alle<strong>in</strong>iger Übergabe des Rechnernamens wird zur Ermittlung der IP-Adresse die im System <strong>in</strong>stallierte Methode zur<br />
Namensauflösung (address resolution) verwendet.<br />
Ist e<strong>in</strong>e übergebene IP-Adresse dem Format nach ungültig oder schlägt die Namensauflösung fehl wird von den<br />
Erzeugungsmethoden e<strong>in</strong>e UnknownHostException (abgeleitet von IOException) geworfen.<br />
◇ Neben der IP-Adresse enthalten InetAddress-Objekte gegebenenfalls auch den zugehörigen Rechnernamen.<br />
Dies ist dann der Fall, wenn der Name bei der Objekterzeugung verwendet wurde oder e<strong>in</strong>e <strong>in</strong>verse Namensauflösung<br />
(reverse host name resolution) vorgenommen wurde.<br />
◇ Die Klasse InetAddress verwaltet e<strong>in</strong>en Cache, <strong>in</strong> dem erfolgreiche und nicht erfolgreiche Namensauflösungen<br />
abgelegt werden.<br />
◇ Es existieren u.a. Instanz-Memberfunktionen, die die gespeicherte IP-Adresse bzw den Rechnernamen zurück-<br />
liefern.<br />
◇ Statische Memberfunktion der Klasse InetAddress zur Objekterzeugung (Auswahl)<br />
public static Erzeugung e<strong>in</strong>es InetAddress-Objekts (genauer :<br />
InetAddress getByAddress(byte[] addr) e<strong>in</strong>es Inet4Address- bzw Inet6Address-<br />
throws UnknownHostException Objekts) mit der durch addr gegebenen IP-Adresse.<br />
Der Parameter addr muss die Address-Bytes <strong>in</strong><br />
Network Byte Order (big endian) enthalten<br />
public static Erzeugung e<strong>in</strong>es InetAddress-Objekts (genauer :<br />
InetAddress getByName(Str<strong>in</strong>g host) e<strong>in</strong>es Inet4Address- bzw Inet6Address-<br />
throws UnknownHostException Objekts) mit der durch Namensauflösung des Rechner-<br />
namens host ermittelten IP-Adresse.<br />
Der Parameter host kann auch direkt die IP-Adresse<br />
<strong>in</strong> Str<strong>in</strong>gdarstellung (dotted decimal notation) enthalten<br />
In diesem Fall entfällt e<strong>in</strong>e Namensauflösung<br />
◇ Instanz-Memberfunktion der Klasse InetAddress (Auswahl)<br />
public byte[] getAddress() Rückgabe der IP-Adresse als Byte-Array (<strong>in</strong> Network Byte Order)<br />
public Str<strong>in</strong>g getHostAddress() Rückgabe der IP-Adresse als Str<strong>in</strong>g <strong>in</strong> dotted decimal notation<br />
public Str<strong>in</strong>g getHostName() Rückgabe des Rechnernamens falls dieser im Objekt gespeichert ist<br />
oder durch <strong>in</strong>verse Namensauflösung ermittelt werden kann.<br />
Ist e<strong>in</strong> Security-Manager <strong>in</strong>stalliert, so wird bei erforderlicher <strong>in</strong>verser<br />
Namensauflösung dieser befragt, ob die Operation zulässig ist<br />
Ist die <strong>in</strong>verse Namensauflösung unzulässig oder kann der Rechner-<br />
name nicht ermittelt werden, wird die IP-Adresse als Str<strong>in</strong>g <strong>in</strong> dotted<br />
decimal notation zurückgegeben.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 814 – 00 – TH – 04<br />
------------------------------------------------------------------------------------<br />
• Die abstrakte Klasse SocketAddress<br />
◇ Enthalten im Package java.net.<br />
Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (4)<br />
◇ Diese Klasse repräsentiert generische – an ke<strong>in</strong> konkretes Protokoll gebundene – Socket-Adressen.<br />
◇ Variable dieses Typs müssen immer Objekte e<strong>in</strong>er konkreten von SocketAddress abgeleiteten Klasse referieren.<br />
Objekte e<strong>in</strong>er derartigen Klasse repräsentieren an jeweils e<strong>in</strong> konkretes Protokoll gebundene Socket-Adressen.<br />
Z. Zt. existiert <strong>in</strong> der <strong>Java</strong>-Standard-Bibliothek lediglich die abgeleitete Klasse InetSocketAddress (für<br />
Adressen der TCP/IP-Protokoll-Familie)<br />
◇ Die Klasse wird u.a. als Typangabe (Parameter- und Rückgabetyp) <strong>in</strong> Methoden der Klassen Socket und<br />
ServerSocket verwendet.<br />
• Die Klasse InetSocketAddress<br />
◇ Enthalten im Package java.net.<br />
◇ Objekte dieser Klasse repräsentieren Adressen der TCP/IP-Protokoll-Familie (INET-Adressen)<br />
Sie enthalten e<strong>in</strong>e IP-Adresse und e<strong>in</strong>e Port-Nummer.<br />
◇ Bei der Objekterzeugung s<strong>in</strong>d dem Konstruktor die IP-Adresse (als InetAddress-Objekt) und die Port-Nummer<br />
zu übergeben.<br />
E<strong>in</strong>em alternativen Konstruktor kann statt der IP-Adresse auch der Rechnername übergeben werden. In diesem Fall<br />
wird e<strong>in</strong>e Namensauflösung versucht. Bei Fehlschlag derselben wird der Name im Objekt gespeichert. Das Objekt<br />
repräsentiert dann e<strong>in</strong>e nichtaufgelöste Adresse (unresolved address). Diese kann beispielsweise bei Verb<strong>in</strong>dungs-<br />
aufnahme über e<strong>in</strong>en Proxy verwendet werden.<br />
◇ Die Klasse InetSocketAddress besitzt Memberfunktionen, mit denen die Komponenten e<strong>in</strong>er von e<strong>in</strong>em<br />
Objekt repräsentierten Adresse ermittelt werden können.<br />
◇ Konstruktoren der Klasse InetSocketAddress<br />
public InetSocketAddress(InetAddress addr, Erzeugung e<strong>in</strong>er INET-Adresse aus der IP-Adresse<br />
<strong>in</strong>t port) addr und der Port-Nr port<br />
public InetSocketAddress(<strong>in</strong>t port) Erzeugung e<strong>in</strong>er INET-Adresse aus der IP-Adresse<br />
0.0.0.0 (wildcard) und der Port-Nr port<br />
public Erzeugung e<strong>in</strong>er INET-Adresse aus der durch<br />
InetSocketAddress(Str<strong>in</strong>g host, <strong>in</strong>t port) Namensauflösung von host ermittelten IP-Adresse<br />
und der Port-Nr port<br />
◇ Memberfunktionen der Klasse InetSocketAddress (Auswahl)<br />
public f<strong>in</strong>al InetAddress getAddress() Rückgabe der IP-Adresse (als InetAddress-Objekt)<br />
public f<strong>in</strong>al <strong>in</strong>t getPort() Rückgabe der Port-Nummer<br />
public f<strong>in</strong>al Str<strong>in</strong>g getHostName() Rückgabe des Rechnernamens<br />
public f<strong>in</strong>al boolean isUnresolved() Überprüfung, ob der Rechnername aufgelöst werden<br />
konnte<br />
Rückgabe von true, wenn Auflösung nicht möglich war<br />
Rückgabe von false, wenn Auflösung möglich war
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 815 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse Socket<br />
◇ Enthalten im Package java.net.<br />
Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (5)<br />
◇ Objekte dieser Klasse implementieren TCP-"Kommunikations-Sockets".<br />
◇ Client-seitige Sockets bauen üblicherweise bei ihrer Erzeugung e<strong>in</strong>e Verb<strong>in</strong>dung zu e<strong>in</strong>em Server auf.<br />
Hierfür muss ihrem Konstruktor die IP-Adresse und die Port-Nummer der Server-Applikation übergeben werden.<br />
Dadurch werden sie auch automatisch an e<strong>in</strong>e geeignete lokale Adresse gebunden.<br />
Falls e<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, überprüft dieser die Zulässigkeit der gewünschten Verb<strong>in</strong>dung.<br />
Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />
Alternativ kann auch e<strong>in</strong> unverbundener Socket erzeugt werden (parameterloser Konstruktor).<br />
E<strong>in</strong> derartiger Socket ist dann auch an ke<strong>in</strong>e lokale Adresse gebunden.<br />
E<strong>in</strong> explizites B<strong>in</strong>den an e<strong>in</strong>e lokale Adresse ist mit der Memberfunktion b<strong>in</strong>d(...) möglich.<br />
Der spätere Aufbau e<strong>in</strong>er Server-Verb<strong>in</strong>dung sowie gegebenenfalls die implizite B<strong>in</strong>dung an e<strong>in</strong>e lokale Adresse<br />
kann mittels der Methode connect(...) erfolgen.<br />
◇ Server-seitige Sockets werden beim Akzeptieren e<strong>in</strong>es Client-Verb<strong>in</strong>dungswunsches durch den "Horch-Socket" erzeugt.<br />
◇ Zur Kommunikation stellen Socket-Objekte jeweils e<strong>in</strong> InputStream- und e<strong>in</strong> OutputStream-Objekt<br />
zur Verfügung dateiartige Lese- und Schreib-Operationen.<br />
◇ Nach Beendigung der Kommunikation sollten die Stream-Objekte (zuerst) und das Socket-Objekt geschlossen<br />
werden.<br />
◇ Viele Memberfunktionen (und Konstruktoren) der Klasse Socket können Exceptions verschiedenen Typs werfen<br />
(s. API-Dokumentation)<br />
◇ Konstruktoren der Klasse Socket (Auswahl)<br />
public Socket() Erzeugung e<strong>in</strong>es unverbundenen Sockets<br />
Der Socket ist auch an ke<strong>in</strong>e lokale Adresse gebunden<br />
public Socket(Str<strong>in</strong>g host, <strong>in</strong>t port) Erzeugung e<strong>in</strong>es Sockets, der mit der durch host (Rechner-<br />
throws UnknownHostException, name oder IP-Adr. als Str<strong>in</strong>g) und port def<strong>in</strong>ierten Server-<br />
IOException Adresse verbunden ist.<br />
Der Socket wird an e<strong>in</strong>e geeignete lokale Adresse gebunden<br />
public Socket(InetAddress adr, Erzeugung e<strong>in</strong>es Sockets, der mit der durch adr und<br />
<strong>in</strong>t port) und port def<strong>in</strong>ierten Server-Adresse verbunden ist<br />
throws IOException Der Socket wird an e<strong>in</strong>e geeignete lokale Adresse gebunden<br />
◇ Memberfunktionen der Klasse Socket (Auswahl)<br />
public void b<strong>in</strong>d(SocketAddress adr) B<strong>in</strong>den des Sockets an die lokale Socket-Adresse adr<br />
throws IOException (bei der Adresse muss es sich um e<strong>in</strong>e INET-Adr. handeln)<br />
public void connect(SocketAddress adr) Aufbau e<strong>in</strong>er Verb<strong>in</strong>dung zum Server mit der Adresse adr<br />
throws IOException (bei der Adresse muss es sich um e<strong>in</strong>e INET-Adr. handeln)<br />
public InputStream getInputStream() Rückgabe e<strong>in</strong>es InputStream-Objekts, mit dem aus<br />
throws IOException dem Socket gelesen (empfangen) werden kann<br />
public OutputStream getOutputStream() Rückgabe e<strong>in</strong>es OutputStream-Objekts, mit dem <strong>in</strong><br />
throws IOException den Socket geschrieben (gesendet) werden kann<br />
public void close() throws IOException Schliessen des Sockets<br />
Memberfunktionen zum Ermitteln der lokalen sowie der verbundenen (entfernten) Adresse, sowohl als INET-<br />
Adresse (SocketAddress-Objekt) als auch getrennt für IP-Adresse und Port-Nr), s. API-Dokumentation
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 816 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Die Klasse ServerSocket<br />
◇ Enthalten im Package java.net.<br />
Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (6)<br />
◇ Objekte dieser Klasse implementieren TCP-"Horch-Sockets" (Server-Sockets).<br />
◇ Üblicherweise wird e<strong>in</strong> Server-Socket gleich bei se<strong>in</strong>er Erzeugung an die lokale Adresse gebunden, an der er auf<br />
Verb<strong>in</strong>dungswünsche warten soll.<br />
Da die IP-Adresse i.a. bekannt ist, muss dem Konstruktor normalerweise nur die Port-Nr übergeben werden.<br />
Alternativ kann dem Konstruktor zusätzlich noch die maximale Grösse der Warteschlange für anstehende Verb<strong>in</strong>-<br />
dungswünsche übergeben werden (backlog). Ohne diese Angabe wird hierfür der Defaultwert 50 verwendet.<br />
Bei voller Warteschlange werden weitere Verb<strong>in</strong>dungswünsche zurückgewiesen.<br />
Es existiert auch e<strong>in</strong> Konstruktor, dem zusätzlich e<strong>in</strong>e IP-Adresse (als InetAddress-Objekt) übergeben werden<br />
kann. Dies ermöglicht für Server-Prozesse, die sich auf e<strong>in</strong>em über mehrere IP-Adressen verfügenden Rechner bef<strong>in</strong>den,<br />
die Festlegung e<strong>in</strong>er bestimmten Horch-Adresse .<br />
◇ Alternativ kann auch e<strong>in</strong> Socket erzeugt werden, der an ke<strong>in</strong>e lokale Adresse gebunden ist (parameterloser Konstruktor).<br />
In diesem Fall ist e<strong>in</strong> späteres B<strong>in</strong>den an e<strong>in</strong>e lokale Adresse mit der Memberfunktion b<strong>in</strong>d(...) möglich.<br />
◇ Falls e<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, überprüft dieser sowohl <strong>in</strong> den Konstruktoren als auch <strong>in</strong> der Methode<br />
b<strong>in</strong>d(..), ob an der lokalen Adresse e<strong>in</strong> anschliessendes Warten ("Horchen") auf Verb<strong>in</strong>dungswünsche zulässig ist.<br />
Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />
◇ Durch Aufruf der Methode accept() wird e<strong>in</strong> ServerSocket <strong>in</strong> den blockierenden Wartezustand versetzt, <strong>in</strong> dem<br />
er auf Verb<strong>in</strong>dungswünsche durch Clients wartet ("Horch-Zustand").<br />
Für e<strong>in</strong>en akzeptierten Verb<strong>in</strong>dungswunsch erzeugt accept() e<strong>in</strong>en "Kommunikations-Socket". Dieser Socket<br />
ist an e<strong>in</strong> neues Port gebunden. Dies ermöglicht e<strong>in</strong>em Multi-Thread-Server (Server, bei dem die Kommunikation mit<br />
e<strong>in</strong>em Client jeweils <strong>in</strong> e<strong>in</strong>em eigenen Thread stattf<strong>in</strong>det) sofort nach dem Akzeptieren e<strong>in</strong>es Verb<strong>in</strong>dungswunsches<br />
an dem "Horch"-Port auf weitere Verb<strong>in</strong>dungswünsche zu warten.<br />
Falls e<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, überprüft dieser ob die Erzeugung des vorgesehenen "Kommunikations-<br />
Sockets" zulässig ist. Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />
◇ Auch e<strong>in</strong> ServerSocket-Objekt sollte geschlossen werden, wenn es nicht mehr benötigt wird<br />
◇ Viele Memberfunktionen (und Konstruktoren) der Klasse ServerSocket können Exceptions verschiedenen Typs<br />
werfen (s. API-Dokumentation)<br />
◇ Konstruktoren der Klasse ServerSocket (Auswahl)<br />
public ServerSocket() Erzeugung e<strong>in</strong>es an ke<strong>in</strong>e lokale Adresse gebundenen Sockets<br />
throws IOException<br />
public ServerSocket(<strong>in</strong>t port) Erzeugung e<strong>in</strong>es Server-Sockets, der an die IP-Adresse 0.0.0.0<br />
throws IOException (wildcard) und die Port-Nr. port gebunden ist.<br />
Herstellung der Bereitschaft, auf Verb<strong>in</strong>dungswünsche zu warten<br />
Für port==0 kann auf allen Ports gewartet werden.<br />
Die maximale Grösse der Warteschlange wird auf 50 gesetzt<br />
◇ Memberfunktionen der Klasse ServerSocket (Auswahl)<br />
public void b<strong>in</strong>d(SocketAddress adr) B<strong>in</strong>den des Sockets an die lokale Socket-Adresse adr<br />
throws IOException (bei der Adresse muss es sich um e<strong>in</strong>e INET-Adr. handeln)<br />
public Socket accept() Warten auf Verb<strong>in</strong>dungswünsche von Clients. Bei Akzep-<br />
throws IOException tieren Erzeugung e<strong>in</strong>es "Kommunikations-Sockets"<br />
public void close() throws IOException Schliessen des Sockets<br />
Memberfunktionen zum Ermitteln der lokalen Adresse, sowohl als INET-Adresse (SocketAddress-Objekt) als<br />
auch getrennt für IP-Adresse und Port-Nr), s. API-Dokumentation
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 817 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Pr<strong>in</strong>zipielles Realisierungsgerüst des Servers<br />
Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong><br />
1. Erzeugung e<strong>in</strong>es ServerSocket-Objekts ServerSocket srvsk = new ServerSocket(port);<br />
B<strong>in</strong>den des Sockets an e<strong>in</strong> Port<br />
2. Warten auf Verb<strong>in</strong>dungswünsche durch Socket comsk = null;<br />
Clients mittels accept(), damit while ((comsk=srvsk.accept())!=null)<br />
Erzeugung e<strong>in</strong>es Socket-Objektes {<br />
(i.a. <strong>in</strong> e<strong>in</strong>er Schleife)<br />
3. Kommunikation mit dem Client über das<br />
Socket-Objekt<br />
▻ Ermittlung der vom Socket-Objekt InputStream is = comsk.getInputStream();<br />
bereitgestellten Stream-Objekte OutputStream os = comsk.getOutputStream();<br />
▻ Erzeugung der für die Kommunikation // zum Beispiel :<br />
tatsächlich e<strong>in</strong>zusetzenden Stream-Objekte DataInputStream dis =new DataInputStream(is);<br />
(Objekte von Stream-Filter-Klassen) DataOutputStream dos=new DataOutputStream(os);<br />
▻ Kommunikation mittels // zum Beispiel :<br />
Lese- und Schreiboperationen str = dis.readUTF();<br />
über die Stream-Objekte dos.writeUTF(str);<br />
▻ nach Beendigung der Kommunikation dis.close();<br />
Schliessen der Stream-Objekte; dos.close();<br />
4. Schliessen des Socket-Objektes comsk.close();<br />
}<br />
• Pr<strong>in</strong>zipielles Realisierungsgerüst des Clients<br />
1. Erzeugung e<strong>in</strong>es Socket-Objektes Socket sock = new Socket(name, port);<br />
Festlegung des Servers (Name oder IP-Adresse)<br />
und des Ports Verb<strong>in</strong>dungswunsch an Server<br />
2. Kommunikation mit dem Server über das<br />
Socket-Objekt<br />
▻ Ermittlung der vom Socket-Objekt OutputStream os = sock.getOutputStream();<br />
bereitgestellten Stream-Objekte InputStream is = sock.getInputStream();<br />
▻ Erzeugung der für die Kommunikation // zum Beispiel :<br />
tatsächlich e<strong>in</strong>zusetzenden Stream-Objekte DataOutputStream dos=new DataOutputStream(os);<br />
(Objekte von Stream-Filter-Klassen) DataInputStream dis =new DataInputStream(is);<br />
▻ Kommunikation mittels // zum Beispiel :<br />
Schreib- und Leseoperationen dos.writeUTF(str);<br />
über die Stream-Objekte str = dis.readUTF();<br />
▻ nach Beendigung der Kommunikation dis.close();<br />
Schliessen der Stream-Objekte; dos.close();<br />
3. Schliessen des Socket-Objektes sock.close();
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 818 – 01 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Demonstrationsbeispiel zur Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong> (1)<br />
• Zu lösende Aufgabe : Filterung von Text<br />
◇ Der zu filternde Text wird <strong>in</strong> e<strong>in</strong>em Client-Programm zeilenweise von der Standard-E<strong>in</strong>gabe e<strong>in</strong>gelesen<br />
und über e<strong>in</strong>e INET-Stream-Socket-Verb<strong>in</strong>dung zu e<strong>in</strong>em Server-Programm gesendet.<br />
Der Name des Server-Rechners und die Port-Nr des Server-Programms können durch Kommandozeilen-Parameter<br />
festgelegt werden. Falls das nicht erfolgt : Verwendung von Defaults.<br />
◇ Das Server-Programm filtert die erhaltenen Zeilen-Str<strong>in</strong>gs mittels e<strong>in</strong>es Filter-Objektes und sendet anschliessend<br />
die gefilterten Str<strong>in</strong>gs über die INET-Stream-Socket-Verb<strong>in</strong>dung zum Client zurück.<br />
Die Port-Nr des Server-Programms kann durch e<strong>in</strong>en Kommandozeilen-Parameter festgelegt werden.<br />
Falls das nicht erfolgt, wird e<strong>in</strong>e Default-Port-Nr verwendet.<br />
◇ Das Client-Programm gibt die erhaltenen gefilterten Zeilen-Str<strong>in</strong>gs <strong>in</strong> die Standard-Ausgabe aus.<br />
◇ Die Art der Filterung wird durch die Klasse des vom Server-Programm e<strong>in</strong>gesetzten Filter-Objekts festgelegt.<br />
Diese muss das Interface TextFilter implementieren.<br />
Hier : Klasse UpcaseFilter (Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben)<br />
• Quelldatei mit Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für Text-Filter (TextFilter.java)<br />
// TextFilter.java<br />
// Def<strong>in</strong>ition e<strong>in</strong>es Interfaces fuer Klassen zur TextFilterung<br />
public <strong>in</strong>terface TextFilter<br />
{<br />
public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str);<br />
}<br />
• Beispiel e<strong>in</strong>er Text-Filter-Klasse : Quelldatei UpcaseFilter.java<br />
// UpcaseFilter.java<br />
// Klasse zur Filterung von Str<strong>in</strong>gs : Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben<br />
// Implementierung des Interfaces TextFilter<br />
public class UpcaseFilter implements TextFilter<br />
{<br />
public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str)<br />
{<br />
return str.toUpperCase();<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 818 – 02 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Demonstrationsbeispiel zur Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong> (2)<br />
• Quelldatei mit Klasse für Serverprogramm (FilterServer.java)<br />
// FilterServer.java<br />
// Start-und Steuer-Klasse e<strong>in</strong>es Servers zum Filtern von Str<strong>in</strong>gs<br />
import java.net.*;<br />
import java.io.*;<br />
public class FilterServer<br />
{<br />
static f<strong>in</strong>al <strong>in</strong>t DEF_PORT = 60290;<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{<br />
<strong>in</strong>t port = DEF_PORT;<br />
if (args.length>0)<br />
port=Integer.parseInt(args[0]);<br />
Pr<strong>in</strong>tStream stdout = System.out;<br />
ServerSocket servsock = new ServerSocket(port);<br />
stdout.pr<strong>in</strong>tln("FilterServer");<br />
stdout.pr<strong>in</strong>tln("Lokale Adresse : " + servsock.getInetAddress());<br />
stdout.pr<strong>in</strong>tln("Lokales Port : " + servsock.getLocalPort() + '\n');<br />
Socket comsock = null;<br />
TextFilter fil = new UpcaseFilter();<br />
while ((comsock=servsock.accept())!=null)<br />
{ stdout.pr<strong>in</strong>t("Verb<strong>in</strong>dung zu : ");<br />
stdout.pr<strong>in</strong>t(comsock.getInetAddress());<br />
stdout.pr<strong>in</strong>tln(" (Port : " + comsock.getPort() +")");<br />
DataInputStream <strong>in</strong> = new DataInputStream(comsock.getInputStream());<br />
DataOutputStream out = new DataOutputStream(comsock.getOutputStream());<br />
Str<strong>in</strong>g l<strong>in</strong>e = null;<br />
boolean goon = true;<br />
while (goon)<br />
{ try<br />
{ l<strong>in</strong>e = <strong>in</strong>.readUTF();<br />
l<strong>in</strong>e = fil.filterStr<strong>in</strong>g(l<strong>in</strong>e);<br />
out.writeUTF(l<strong>in</strong>e);<br />
}<br />
catch (EOFException ex)<br />
{ stdout.pr<strong>in</strong>tln("Verb<strong>in</strong>dung geschlossen");<br />
goon = false;<br />
}<br />
catch (IOException ex)<br />
{ stdout.pr<strong>in</strong>tln(ex.getMessage());<br />
goon = false;<br />
}<br />
}<br />
<strong>in</strong>.close();<br />
out.close();<br />
comsock.close();<br />
}<br />
servsock.close();<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 818 – 03 – TH – 02<br />
------------------------------------------------------------------------------------<br />
Demonstrationsbeispiel zur Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong> (3)<br />
• Quelldatei mit Klasse für Clientprogramm (FilterClient.java)<br />
// FilterClient.java<br />
// Filterung von Str<strong>in</strong>gs, die ueber die Standarde<strong>in</strong>gabe e<strong>in</strong>gegeben werden<br />
// Demonstrationsbeispiel zur Socket-Kommunikation<br />
import java.io.*;<br />
import java.net.*;<br />
public class FilterClient<br />
{<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_HOST = "localhost";<br />
static f<strong>in</strong>al <strong>in</strong>t DEF_PORT = 60290;<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />
{<br />
Str<strong>in</strong>g host = DEF_HOST;<br />
<strong>in</strong>t port = DEF_PORT;<br />
switch(args.length)<br />
{ case 2 : port = Integer.parseInt(args[1]);<br />
case 1 : host = args[0];<br />
break;<br />
}<br />
Pr<strong>in</strong>tStream stdout = System.out;<br />
BufferedReader std<strong>in</strong> = new BufferedReader(new InputStreamReader(System.<strong>in</strong>));<br />
Socket sock = new Socket(host, port);<br />
DataInputStream <strong>in</strong> = new DataInputStream(sock.getInputStream());<br />
DataOutputStream out = new DataOutputStream(sock.getOutputStream());<br />
Str<strong>in</strong>g l<strong>in</strong>e;<br />
stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />
while ((l<strong>in</strong>e=std<strong>in</strong>.readL<strong>in</strong>e())!=null)<br />
{ out.writeUTF(l<strong>in</strong>e);<br />
l<strong>in</strong>e=<strong>in</strong>.readUTF();<br />
stdout.pr<strong>in</strong>tln("Ausgabe : " + l<strong>in</strong>e);<br />
stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />
}<br />
<strong>in</strong>.close();<br />
out.close();<br />
sock.close();<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 821 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Konzept von RMI<br />
Remote Method Invocation (RMI) von <strong>Java</strong> - Allgeme<strong>in</strong>es<br />
◇ E<strong>in</strong> objektorientiertes System besteht aus e<strong>in</strong>er Ansammlung von Objekten, die mite<strong>in</strong>ander <strong>in</strong> Kommunikations-<br />
beziehungen stehen.<br />
Jede Kommunikationsbeziehung zwischen Objekten kann als Client-Server-Beziehung aufgefasst werden :<br />
E<strong>in</strong> Server-Objekt stellt Dienstleistungen zur Verfügung, die von Client-Objekten durch den Aufruf von Methoden<br />
des Server-Objekts (= Senden von Botschaften an das Server-Objekt) genutzt werden können<br />
◇ Remote Method Invocation (RMI) realisiert e<strong>in</strong>e Übertragung des Konzepts des Prozedur-Fernaufrufs (Remote<br />
Procedure Call, RPC) auf e<strong>in</strong>e objektorientierte Umgebung.<br />
◇ RMI erlaubt den Aufruf von Methoden für Objekte, die sich <strong>in</strong> anderen virtuellen Masch<strong>in</strong>en bef<strong>in</strong>den, e<strong>in</strong>schliesslich<br />
solcher virtueller Masch<strong>in</strong>en, die auf anderen Rechnern laufen.<br />
Kommunikation zwischen Objekten über Rechnergrenzen h<strong>in</strong>weg verteilte Objekte<br />
◇ RMI ist die <strong>Java</strong>-spezifische Implementierung e<strong>in</strong>es Systems für verteilte Objekte<br />
"Natürliche" Integration des verteilten Objekt-Modells <strong>in</strong> die Sprache <strong>Java</strong> unter Ausnutzung ihrer Konzepte und<br />
Beibehaltung ihrer Objekt-Semantik<br />
E<strong>in</strong> entfernter Methodenaufruf sieht wie e<strong>in</strong> normaler lokaler Methodenaufruf aus<br />
(transparenter entfernter Methodenaufruf)<br />
◇ Bestandteil des <strong>Java</strong>-API (ab JDK 1.1, modifiziert und erweitert <strong>in</strong> JDK 1.2)<br />
• Weitere wesentliche Eigenschaften von RMI<br />
◇ Anwendungen stehen zwei Mechanismen zur Erlangung von Referenzen auf entfernte Objekte zur Verfügung :<br />
▻ Nachfragen bei e<strong>in</strong>em RMI-eigenen Namensdienst (rmiregistry)<br />
▻ Übergabe als Parameter und/oder Rückgabewerte von entfernten Funktionsaufrufen<br />
◇ Die eigentliche Kommunikation zwischen verteilten Objekten wird vom RMI-Laufzeitsystem unter E<strong>in</strong>satz von<br />
Sockets durchgeführt. E<strong>in</strong>zelheiten bleiben der eigentlichen Anwendung (und ihrem Programmierer) aber verborgen.<br />
◇ RMI ermöglicht die Übergabe von Objekten als Parameter und Rückgabewerte<br />
Das RMI-Laufzeitsystem stellt die notwendigen Mechanismen zur Übertragung von Objekt-Daten und -Code zur<br />
Verfügung ( Kopieren von Objekten)<br />
Diese beruhen auf<br />
▻ dem <strong>Java</strong>-Konzept der Objekt-Serialisierung (object serialization)<br />
▻ sowie der <strong>Java</strong>-Eigenschaft des dynamischen Ladens von Code (dynamic code download<strong>in</strong>g)<br />
Erzeugung von Objekten, deren Klassen-Implementierung (<strong>Java</strong>-Byte-Code) lokal nicht verfügbar ist<br />
◇ Das dynamische Laden von Code ermöglicht die dynamische Änderung des Verhaltens von Server und/oder Client<br />
◇ Unterstützung von Callbacks vom Server zum Client<br />
Übergabe von Referenzen auf – im Client vorhandene – entfernte Objekte als Parameter im entfernten Methodenaufruf.<br />
◇ Verteilte Garbage Collection<br />
E<strong>in</strong>beziehung von entfernten Objekten <strong>in</strong> den Garbage Collection Mechanismus von <strong>Java</strong><br />
RMI stellt sicher, daß dann und nur dann entfernte Objekte (remote objects) vernichtet werden, wenn weder e<strong>in</strong>e lokale<br />
noch e<strong>in</strong>e entfernte Referenz auf das jeweilige Objekt existiert.<br />
◇ E<strong>in</strong>bettung <strong>in</strong> die Sicherheitsmechanismen der <strong>Java</strong>-Plattform<br />
Verwendung von Security-Manager, Class Loader und Policy Files zur Überprüfung der Zulässigkeit des Ladens<br />
von entferntem Code und des Ausführens von Code (Resourcenzugriff)<br />
◇ Flexibilität und Erweiterbarkeit, z.B.<br />
▻ Implementierung unterschiedlicher Referenz-Semantiken für entfernte (Server-) Objekte<br />
(z.Zt im Standard-API implementiert : UnicastRemoteObject und Activatable )<br />
▻ E<strong>in</strong>satz unterschiedlicher Socket-Typen <strong>in</strong> der Transportschicht von RMI (Ersatz des standardmäßig verwendeten<br />
Socket-Typs (TCP-Protokoll) durch SSL-Sockets oder selbstdef<strong>in</strong>ierte Socket-Typen)
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 822 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• RMI –Architektur<br />
Remote Method Invocation (RMI) von <strong>Java</strong> – Funktionsweise (1)<br />
◇ Das RMI-System besteht aus drei Schichten :<br />
▻ Stub-/Skeleton-Schicht<br />
▻ RMI-Referenz-Schicht<br />
▻ RMI-Transport-Schicht<br />
Client-Objekt<br />
Stub<br />
RMI-Referenz-Schicht<br />
RMI-Tranport-Schicht<br />
Server-Objekt<br />
Skeleton<br />
RMI-Referenz-Schicht<br />
RMI-Tranport-Schicht<br />
RMI-<br />
Laufzeit-<br />
System<br />
◇ Die Stub-/Skeleton-Schicht bildet die Schnittstelle zwischen den Bestandteilen der verteilten Applikation<br />
(Client-Objekt und Server-Objekt) und dem restlichen RMI-System (RMI-Laufzeitsystem).<br />
Der Stub ist e<strong>in</strong> Stellvertreter-Objekt (Proxy) des Server-Objekts auf der Clientseite, der die gleiche Methoden-<br />
Aufruf-Schnittstelle wie das Server-Objekt anbietet.<br />
Er nimmt die RMI-Aufrufe des Clients entgegen, wandelt die Methoden-Aufruf-Parameter mittels Objekt-Serialisierung<br />
<strong>in</strong> serielle Byte-Streams um (marshall<strong>in</strong>g) und leitet diese zusammen mit den für den Aufruf der Serverfunktion<br />
benötigten Informationen (Identifikation des Ziel-Objekts und der aufzurufenden Methode) an die RMI-Referenzschicht<br />
weiter<br />
Umgekehrt erhält er von der RMI-Referenzschicht die Rückgabewerte e<strong>in</strong>es RMI-Aufrufs als Byte-Streams, deseriali-<br />
siert diese (ummarshall<strong>in</strong>g) und reicht sie an das aufrufende Client-Objekt weiter.<br />
Das Skeleton nimmt auf der Serverseite die RMI-Aufrufe von der RMI-Referenzschicht entgegen, deserialisiert die<br />
als Byte-Streams erhaltenen Parameter und ruft mit diesen die eigentlich auszuführende im Server-Objekt implementierte<br />
Methode auf. Nach Bendigung dieser Funktion nimmt es deren Rückgabewerte entgegen und leitet sie nach<br />
Serialisierung an die RMI-Referenzschicht weiter.<br />
In früheren <strong>Java</strong>-Versionen wurde hierfür e<strong>in</strong> eigenes Skeleton-Objekt e<strong>in</strong>gesetzt.<br />
In neueren Versionen wird die Funktionalität des Skeletons durch e<strong>in</strong>en allgeme<strong>in</strong>en Verteiler des RMI-Laufzeit-<br />
systems ersetzt. Es muss daher ke<strong>in</strong> eigenes Skeleton-Objekt mehr erzeugt werden.<br />
Der Stub muss dagegen an das jeweilige Server-Objekt angepaßt se<strong>in</strong>.<br />
Se<strong>in</strong>e Klasse wird aus der Server-Objekt-Klasse mittels e<strong>in</strong>es RMI-Compilers (rmic) generiert.<br />
(Der RMI-Compiler war früher auch zuständig für die Erzeugung der Skeleton-Klasse)<br />
Ab dem JDK 5.0 kann das Stub-Objekt dynamisch zur Laufzeit erzeugt werden. Aufruf von rmic nicht<br />
erforderlich wenn auch der Client-Code mit dem JDK 5.0 erzeugt wurde.<br />
◇ Die RMI-Referenz-Schicht ist für die Lokalisierung des jeweiligen Kommunikationspartners (Server bzw Client)<br />
zuständig. Sie be<strong>in</strong>haltet den RMI-Namensdienst (Registry) und verwaltet die Referenzen auf entfernte Objekte.<br />
Unter Berücksichtigung der jeweiligen Referenz-Semantik gibt sie die vom Stub erhaltenen RMI-Aufrufe e<strong>in</strong>schließ-<br />
lich deren Parameter (Byte-Streams) an die RMI-Transportschicht weiter.<br />
Auf der Serverseite nimmt sie die RMI-Aufrufe und deren Parameter von der RMI-Transportschicht entgegen, aktiviert<br />
gegebenenfalls das Server-Objekt und leitet die Aufrufe an das Skeleton weiter.<br />
Analog ist sie an der Übermittlung der Rückgabewerte beteiligt.<br />
◇ In der RMI-Transport-Schicht werden die Kommunikationsverb<strong>in</strong>dungen verwaltet und die eigentliche Kommu-<br />
nikation zwischen verschiedenen Adressräumen (JVMs) abgewickelt.<br />
Üblicherweise werden hierfür Sockets e<strong>in</strong>gesetzt.
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 822 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
Remote Method Invocation (RMI) von <strong>Java</strong> – Funktionsweise (2)<br />
• Übertragung von Parametern und Rückgabewerten<br />
◇ Die Parameter und Rückgabewerte von RMI-Aufrufen werden mittels Objekt-Serialisierung als Byte-Streams<br />
übertragen.<br />
Übertragbare Objekte müssen serialisierbar se<strong>in</strong>, d.h. das Interface java.io.Serializable implementieren.<br />
◇ e<strong>in</strong>fache Datentypen : Übertragung der Werte (Call by Value)<br />
◇ lokale Objekte (non-remote objects) : Übertragung e<strong>in</strong>er Kopie des Objekts (Call by Copy)<br />
Für Rückgabewerte wird beim Aufrufer e<strong>in</strong> neues Objekt erzeugt<br />
◇ entfernte Objekte (remote objects) : Übertragung e<strong>in</strong>er Referenz auf das Objekt (Call by Reference)<br />
Die Referenz ist das zum Objekt gehörende Stub-Objekt. (das se<strong>in</strong>erseits per Kopie übertragen wird)<br />
◇ In dem im Byte-Stream für e<strong>in</strong> übertragenes Objekt enthaltenen Klassen-Deskriptor ist auch die URL über die der<br />
Klassen-Code (<strong>Java</strong> Byte Code) zugänglich ist, vermerkt.<br />
Dies ermöglicht es dem empfangenden System, den Klassen-Code dynamisch zu laden, falls er nicht lokal verfügbar<br />
ist. (Dynamic Code Download<strong>in</strong>g).<br />
E<strong>in</strong>e derartige Situation kann auftreten, wenn das übertragene Objekt e<strong>in</strong>e Instanz e<strong>in</strong>es Untertyps des deklarierten<br />
Parametertyps ist. E<strong>in</strong> Untertyp <strong>in</strong> diesem S<strong>in</strong>n ist entweder e<strong>in</strong>e Klasse, die e<strong>in</strong> Interface, das als Parametertyp dekla-<br />
riert ist, implementiert oder e<strong>in</strong>e von der Parameterklasse abgeleitete Klasse.<br />
• RMI-Registry<br />
◇ Die RMI-Registry ist e<strong>in</strong> e<strong>in</strong>facher Namensdienst, der es Clients ermöglicht, entfernte Objekte über ihren Namen zu<br />
lokalisieren.<br />
◇ E<strong>in</strong>e RMI-Registry muß lokal auf dem System, das Objekte für RMI-Aufrufe (entfernte Objekte) bereitstellt (RMI-<br />
Server) existieren.<br />
◇ Üblicherweise wird die RMI-Registry <strong>in</strong> e<strong>in</strong>er eigenen JVM als H<strong>in</strong>tergrundprozeß gestartet.<br />
Defaultmäßig "horcht" sie auf Port 1099.<br />
Sie kann aber auch mit e<strong>in</strong>er anderen Port-Nummer gestartet werden.<br />
Kommando : [start] rmiregistry [port] (W<strong>in</strong>dows)<br />
rmiregistry [port] & (L<strong>in</strong>ux)<br />
◇ E<strong>in</strong> entferntes Objekt, das über die Registry zugänglich se<strong>in</strong> soll, muß vom Server-Prozeß der Registry bekannt<br />
gemacht (registriert, "gebunden") werden.<br />
◇ E<strong>in</strong> Client, der e<strong>in</strong>en RMI-Aufruf ausführen möchte, benötigt e<strong>in</strong>e Referenz auf das entsprechende (entfernte) Server-<br />
Objekt. Diese erhält er durch e<strong>in</strong>e Nachfrage ("lookup") bei der RMI-Registry des Server-Rechners.<br />
Falls für das – über e<strong>in</strong>en Namen referierte – Objekt e<strong>in</strong> E<strong>in</strong>trag vorhanden ist, liefert die Registry se<strong>in</strong> als Referenz<br />
dienendes Stub-Objekt zurück.<br />
◇ Typischerweise wird die RMI-Registry nur zur Lokalisierung des ersten vom Client referierten entfernten Objekts<br />
verwendet.<br />
Weitere gegebenenfalls benötigte entfernte Objekte können dann über dieses Objekt ermittelt werden (als Parameter<br />
bzw Rückgabewerte von RMI-Aufrufen)<br />
◇ Die Kommunikation mit der RMI-Registry erfolgt üblicherweise über das von der <strong>Java</strong>-Klasse java.rmi.Nam<strong>in</strong>g<br />
bereitgestellte Interface (statische Methoden)<br />
◇ Tatsächlich stellt die RMI-Registry bereits selbst e<strong>in</strong> besonderes entferntes Objekt dar, zu dem auch mittels RMI, das<br />
durch die Nam<strong>in</strong>g-Funktionen gekapselt wird, zugegriffen wird.<br />
Client-Objekt<br />
2 : Nachfrage<br />
3 : RMI-Aufruf<br />
RMI-Registry<br />
1:Registrierung<br />
Server-Objekt
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 822 – 03 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
Remote Method Invocation (RMI) von <strong>Java</strong> – Funktionsweise (3)<br />
• Dynamisches Laden von Code (Dynamic Code Download<strong>in</strong>g)<br />
◇ E<strong>in</strong>e hervorstechende Eigenschaft von <strong>Java</strong> ist die Fähigkeit, dynamisch Code von jeder URL <strong>in</strong> e<strong>in</strong>e laufende<br />
<strong>Java</strong> Virtual Mach<strong>in</strong>e (JVM) zu laden. I.a. wird die URL auf e<strong>in</strong> anderes physikalisches System verweisen.<br />
E<strong>in</strong>e JVM kann Code ausführen, der nie auf ihrem eigenen System <strong>in</strong>stalliert worden ist.<br />
◇ Diese Fähigkeit wird auch vom RMI-System genutzt :<br />
▻ Zum Laden des Codes für den Stub des Server-Objekts durch den Client (ab dem JDK 5.0 nicht mehr erforderlich).<br />
Die Stub-Klasse muß nicht lokal zur Verfügung stehen<br />
(ab dem JDK 5.0 wird sie lokal beim Client aus dem RMI-Interface erzeugt)<br />
▻ Zum Laden des Codes für als Parameter <strong>in</strong> oder Rückgabewerte von RMI-Aufrufen übergebene Objekte<br />
(sowohl lokale Objekte als auch entfernte Objekte)<br />
◇ Das dynamische Laden von Code erfordert das Setzen der Property java.rmi.server.codebase <strong>in</strong> der JVM<br />
des das Objekt bzw die Klasse zur Verfügung stellenden Prozesses :<br />
- bei Stubs von Server-Objekten : <strong>in</strong> der JVM des RMI-Server-Prozesses, der e<strong>in</strong> entferntes Objekt registriert<br />
(ab dem JDK 5.0 nicht mehr notwendig)<br />
- bei als Parameter übergebenen Objekten : <strong>in</strong> der JVM des RMI-Client-Prozesses<br />
- bei Objekten, die von RMI-Aufrufen zurückgegeben werden : <strong>in</strong> der JVM des Server-Prozesses<br />
Als Wert der codebase-Property ist die URL, von der der Klassen-Code geladen werden kann, anzugeben.<br />
Diese URL kann sich auf e<strong>in</strong> drittes System beziehen.<br />
◇ Wenn der Server-Prozeß e<strong>in</strong> entferntes Objekt unter e<strong>in</strong>em Namen bei der RMI-Registry registriert, wird der <strong>in</strong> der<br />
Server-JVM gesetzte codebase-Wert (URL !) zusammen mit der Objekt-Referenz (Stub-Objekt) gespeichert.<br />
Voraussetzung : Der Code der Stub-Klasse darf nicht über die CLASSPATH-Environment-Variable der JVM der<br />
RMI-Registry erreichbar se<strong>in</strong>. (gilt nicht ab dem JDK 5.0, da muss die .class-Datei des RMI-Interfaces über die<br />
CLASSPATH-Environment-Variable der JVM der RMI-Registry erreichbar se<strong>in</strong>)<br />
◇ Der Client-Prozeß erhält auf se<strong>in</strong>e Nachfrage bei der RMI-Registry das Stub-Objekt als Referenz auf das Server-<br />
Objekt. Falls er den Stub-Klassen-Code nicht über se<strong>in</strong>e CLASSPATH-Environment-Variable lokal f<strong>in</strong>det, versucht<br />
er bis e<strong>in</strong>schliesslich dem JDK 1.4 den Code von der mit dem Stub-Objekt verbundenen URL (codebase-Wert) zu<br />
laden. (ab dem JDK 5.0 wird der Code lokal aus dem RMI-Interface erzeugt)<br />
Voraussetzung : Der RMI-Client-Prozeß hat e<strong>in</strong>en Security-Manager <strong>in</strong>stalliert, der das Laden des Stubs erlaubt<br />
(z.B. RMISecurityManager). In <strong>Java</strong> 2 (ab JDK 1.2) erfordert dies zusätzlich e<strong>in</strong> entsprechend konfiguriertes<br />
Security Policy File (Default : Datei .java.policy im Heimat-Verzeichnis des Users)<br />
Anmerkung : Der Security-Manager wird bereits für den Zugriff zur Registry benötigt.<br />
◇ Analog erfolgt das Laden von Klassen-Codes für Objekte, die dem Server-Objekt vom Client-Objekt als Parameter<br />
<strong>in</strong> RMI-Aufrufen übergeben werden (e<strong>in</strong>schliesslich das Laden aller weiteren von diesen benötigten Objekte).<br />
Das gilt auch für das JDK 5.0 !<br />
Voraussetzungen : Der codebase-Wert im Client-Prozeß ist auf die richtige URL gesetzt und das Server-Objekt<br />
kann den Code nicht lokal über se<strong>in</strong>e CLASSPATH-Environment-Variable f<strong>in</strong>den. Außerdem muß im Server e<strong>in</strong><br />
Security-Manager <strong>in</strong>stalliert se<strong>in</strong>.<br />
4. u. 5<br />
nicht bei<br />
JDK 5.0<br />
Client-Objekt<br />
5. Rückgabe des Klassen-<br />
Codes des Stub-Objekts<br />
4. Erfragen des<br />
Klassen-Codes<br />
für Stub-Objekt<br />
2. Namens-<br />
Nachfrage<br />
myHost<br />
codebase-URL<br />
(http)<br />
RMI-Registry<br />
3. Rückgabe e<strong>in</strong>es<br />
Stub-Objekts<br />
6. RMI-Aufruf<br />
1. Registrierung<br />
des entfernten<br />
Server-Objekts<br />
Server-Prozeß,<br />
der entferntes Objekt<br />
erzeugt<br />
Server-Objekt<br />
java.rmi.server.codebase<br />
=http://myHost/mydir/
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 823 – 01 – TH – 02<br />
------------------------------------------------------------------------------------<br />
• RMI-Packages<br />
<strong>Java</strong>-RMI - Interfaces und Klassen (1)<br />
Das RMI-API von <strong>Java</strong> wird durch die folgenden Packages zur Verfügung gestellt :<br />
▻ java.rmi<br />
grundlegendes Package<br />
▻ java.rmi.activation<br />
Unterstützung für die RMI Object Activation<br />
▻ java.rmi.dgc<br />
Klassen und Interfaces für die RMI Distributed Garbage Collection<br />
▻ java.rmi.registry<br />
Klassen und Interfaces für die RMI-Registry<br />
▻ java.rmi.server<br />
Klassen und Interfaces zur Unterstützung der Server-Seite von RMI<br />
• Überblick über die wichtigsten Interfaces und Klassen des RMI-API<br />
Für Anwenderprogramme s<strong>in</strong>d vor allem die folgenden Interfaces und Klassen von Bedeutung :<br />
<strong>in</strong>terface<br />
Remote<br />
(java.rmi)<br />
class<br />
UnicastRemoteObject<br />
(java.rmi.server)<br />
class<br />
Nam<strong>in</strong>g<br />
(java.rmi)<br />
abstract class<br />
RemoteObject<br />
(java.rmi.server)<br />
abstract class<br />
RemoteServer<br />
(java.rmi.server)<br />
class<br />
Activatable<br />
(java.rmi.activation)<br />
class<br />
RMISecurityManager<br />
(java.rmi)<br />
class<br />
RemoteException<br />
(java.rmi)
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 823 – 02 – TH – 03<br />
------------------------------------------------------------------------------------<br />
<strong>Java</strong>-RMI - Interfaces und Klassen (2)<br />
• Die wichtigsten Interfaces und Klassen des <strong>Java</strong>-RMI-API - Kurzbeschreibung<br />
◇ <strong>in</strong>terface Remote (Package : java.rmi)<br />
"Basis"-Interface für alle Interfaces, deren Methoden mittels RMI aufrufbar se<strong>in</strong> sollen.<br />
Alle Klassen, deren Objekte mittels RMI ansprechbar se<strong>in</strong> sollen, müssen direkt oder <strong>in</strong>direkt – über abgeleitete<br />
Interfaces – dieses Interface implementieren.<br />
Mittels RMI können nur die Methoden, die <strong>in</strong> e<strong>in</strong>em von Remote abgeleiteten Interface ( remote <strong>in</strong>terface) spezi-<br />
fiziert s<strong>in</strong>d, aufgerufen werden.<br />
◇ class RemoteObject (Package : java.rmi.Server)<br />
Abstrakte Klasse, die e<strong>in</strong>ige Methoden der Klasse java.lang.Object für entfernt nutzbare Objekte (remote<br />
objects) überschreibt und damit die entsprechenden Fähigkeiten für derartige Objekte implementiert.<br />
(spezielle Implementierungen der Methoden hashCode(), equals() und toStr<strong>in</strong>g())<br />
◇ class RemoteServer (Package : java.rmi.Server)<br />
Abstrakte Superklasse der Klassen für entfernt nutzbare Server-Objekte.<br />
Sie stellt e<strong>in</strong> geme<strong>in</strong>sames Framework zur Unterstützung unterschiedlichster Semantiken für entfernte Referenzen<br />
zur Verfügung, die durch die von ihr abgeleiteten Klassen implementiert werden<br />
Die zur Erzeugung und Exportierung von Objekten an das RMI-Laufzeitsystem benötigten Methoden (Konstruktoren<br />
und gegebenenfalls weitere Methoden) werden durch die von dieser Klasse abgeleiteten Klassen bereitgestellt.<br />
U.a. stellt diese Klasse auch e<strong>in</strong>e statische Methode zum Ermitteln des aufrufenden Client-Rechners zur Verfügung.<br />
◇ class UnicastRemoteObject (Package : java.rmi.Server)<br />
Von der Klasse RemoteServer abgeleitete Klasse für e<strong>in</strong>fache – nicht replizierbare – entfernte Objekte, deren<br />
Referenzen nur gültig s<strong>in</strong>d, solange die Objekte aktiv s<strong>in</strong>d.<br />
Sie stellt die Unterstützung für Punkt-zu-Punkt-Verb<strong>in</strong>dungen zu aktiven Objekten (bezüglich Aufrufe, Parameter,<br />
Rückgabewerte) unter Verwendung von TCP-Sockets bereit<br />
Durch Übergabe e<strong>in</strong>es <strong>in</strong>t-Parameters an den Konstruktor kann die Port-Nummer festgelegt werden.<br />
Wird ke<strong>in</strong> Parameter übergeben, wird vom System e<strong>in</strong> anonymes Port gewählt.<br />
Eigene Klassen, die diese Referenz-Semantik bereitstellen sollen, müssen – unter Implementierung e<strong>in</strong>es geeigneten<br />
remote <strong>in</strong>terfaces - von dieser Klasse abgeleitet werden.<br />
◇ class Activatable (Package : java.rmi.Activation)<br />
Von der Klasse RemoteServer abgeleitete Klasse für entfernte Objekte, deren Referenzen auch gültig s<strong>in</strong>d,<br />
wenn die Objekte <strong>in</strong>aktiv und persistent ausgelagert s<strong>in</strong>d Diese Objekte können bei Bedarf wieder aktiviert werden.<br />
Eigene Klassen, die diese Referenz-Semantik bereitstellen sollen, müssen – unter Implementierung e<strong>in</strong>es geeigneten<br />
remote <strong>in</strong>terfaces - von dieser Klasse abgeleitet werden.<br />
◇ class RemoteException (Package : java.rmi)<br />
Superklasse der kommunikationsorientierten Exceptions, die bei RMI auftreten können.<br />
Alle Methoden e<strong>in</strong>es remote <strong>in</strong>terfaces müssen diese Exception weiterreichen können, d.h. <strong>in</strong> ihrem Funktionskopf<br />
muß e<strong>in</strong>e entsprechende Exception-Spezifikation (throws-Klausel) enthalten se<strong>in</strong>.<br />
◇ class Nam<strong>in</strong>g (Package : java.rmi)<br />
Nicht ableitbare Klasse (f<strong>in</strong>al), die statische Methoden zum Zugriff zur RMI-Registry bereitstellt<br />
◇ class RMISecurityManager (Package : java.rmi)<br />
Beispiel e<strong>in</strong>es von RMI-Anwendungen für das dynamische Laden von Code benötigten Security-Managers.<br />
Der RMI Class Loader kann ohne <strong>in</strong>stallierten Security-Manager ke<strong>in</strong>en Code von URLs, die auf e<strong>in</strong>en entfernten<br />
Rechner verweisen, laden.
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 824 – 01 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
• Auszuführende Schritte<br />
Erzeugung e<strong>in</strong>er RMI-Anwendung (1)<br />
▶ Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für die RMI-Aufrufe (remote <strong>in</strong>terface)<br />
▶ Erstellung e<strong>in</strong>es Servers (Implementierung des Interfaces und der Server-Start-Funktionalität)<br />
▶ Entwicklung e<strong>in</strong>es Clients, der unter Nutzung dieses Interfaces RMI-Aufrufe ausführt<br />
▶ Erzeugung der Stub-Klasse (ab dem JDK 5.0 nicht mehr erforderlich)<br />
▶ Starten der RMI-Registry auf dem Server-Rechner<br />
▶ Start des Servers und des Clients<br />
• Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für die RMI-Aufrufe (remote <strong>in</strong>terface)<br />
◇ Alle Methoden des Server-Objekts, die über RMI aufrufbar se<strong>in</strong> sollen, s<strong>in</strong>d <strong>in</strong> e<strong>in</strong>em Interface zu deklarieren<br />
(RMI-Methoden)<br />
◇ Eigenschaften dieses RMI-Interfaces :<br />
► Das Interface muß public deklariert werden<br />
► Das Interface muß von dem Interface java.rmi.Remote abgeleitet se<strong>in</strong> ( remote <strong>in</strong>terface).<br />
► Jede Methode des Interfaces muß die Exception java.rmi.RemoteException als werfbar deklarieren<br />
(Exception-Deklaration : throws java.rmi.RemoteException)<br />
◇ Die Klasse der RMI-Server-Objekte muß dieses Interface implementieren (RMI-Server-Klasse).<br />
Nur die Methoden der Server-Objekte, die <strong>in</strong> diesem Interface enthalten s<strong>in</strong>d, s<strong>in</strong>d auch entfernt aufrufbar.<br />
Alle weiteren eventuell vorhandenen Methoden s<strong>in</strong>d nur lokal ansprechbar.<br />
◇ Der Client muß das Stub-Objekt, das er als lokale Referenz auf das entfernte Server-Objekt erhält, immer als e<strong>in</strong>e<br />
Instanz dieses Interfaces referieren .<br />
Der hierfür notwendige Type-Cast ist zulässig, da auch die Stub-Klasse dieses Interface implementiert.<br />
◇ Übersetzung der <strong>Java</strong>-Quell-Datei (z.B. MyServer.java)<br />
Erzeugung e<strong>in</strong>er <strong>Java</strong>-Bytecode-Datei (MyServer.class)<br />
• Klassendiagramm für e<strong>in</strong>en e<strong>in</strong>fachen RMI-Server
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 824 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Erstellung e<strong>in</strong>es Servers<br />
◇ Zur Realisierung e<strong>in</strong>es RMI-Servers werden benötigt :<br />
Erzeugung e<strong>in</strong>er RMI-Anwendung (2)<br />
► E<strong>in</strong>e das RMI-Interface implementierende Klasse (RMI-Server-Klasse)<br />
► Die Server-Start-Funktionalität.<br />
Häufig wird die Server-Start-Funktionalität durch die ma<strong>in</strong>()-Methode der RMI-Server-Klasse realisiert.<br />
Diese ma<strong>in</strong>()-Methode kann aber auch <strong>in</strong> e<strong>in</strong>er anderen – speziell hierfür vorgesehenen - Klasse enthalten se<strong>in</strong>.<br />
◇ Die RMI-Server-Klasse muß<br />
► wenigstens e<strong>in</strong> RMI-Interface (remote <strong>in</strong>terface) implementieren<br />
► von e<strong>in</strong>er Unterklasse der Klasse java.rmi.server.RemoteServer abgeleitet se<strong>in</strong><br />
► e<strong>in</strong>en Konstruktor def<strong>in</strong>ieren, der die Exception java.rmi.RemoteException werfen kann<br />
► alle im implementierenden RMI-Interface enthaltenen Methoden def<strong>in</strong>ieren<br />
◇ Die Server-Start-Funktionalität be<strong>in</strong>haltet :<br />
▻ Erzeugung und Installation e<strong>in</strong>es Security Managers<br />
▻ Erzeugung e<strong>in</strong>es oder mehrerer RMI-Server-Objekte (Instanzen der RMI-Server-Klasse)<br />
▻ Registrierung wenigstens e<strong>in</strong>es dieser Objekte bei der RMI-Registry<br />
◇ Erzeugung und Installation e<strong>in</strong>es Security-Managers<br />
In jeder JVM, <strong>in</strong> der Code von anderen Quellen als den durch die CLASSPATH-Environmentvariable festgelegten<br />
geladen werden soll, muß e<strong>in</strong> Security-Manager <strong>in</strong>stalliert se<strong>in</strong>.<br />
Falls noch ke<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, muß der Server e<strong>in</strong>en <strong>in</strong>stallieren – entweder e<strong>in</strong>e Instanz der Klasse<br />
RMISecurityManager oder e<strong>in</strong>er selbstdef<strong>in</strong>ierten Security-Manager Klasse<br />
if (System.getSecurityManager()==null)<br />
{<br />
System.setSecurityManager(new RMISecurityManager());<br />
}<br />
◇ Registrierung e<strong>in</strong>es RMI-Server-Objektes bei der lokalen RMI-Registry<br />
Mittels der statischen Methode reb<strong>in</strong>d() der Klasse Nam<strong>in</strong>g :<br />
public static void reb<strong>in</strong>d(Str<strong>in</strong>g name, Remote obj) throws RemoteException,<br />
MalformedURLException<br />
Parameter : name - URL-formatierter Str<strong>in</strong>g, der das zu registrierende Objekt bezeichnet<br />
- Allgeme<strong>in</strong>e Form : "//host:port-nr/ObjectName".<br />
- Wenn die RMI-Registry auf dem Default-Port 1099 läuft, können die Angabe des Hosts<br />
(host) und der Port-Nr. (port-nr) weggelassen werden, es reicht die Angabe von<br />
"ObjectName".<br />
- "ObjectName" ist e<strong>in</strong> beliebiger Name unter dem das Objekt registriert werden soll.<br />
obj Name des Objekts unter dem es angelegt worden ist und im Programm referiert wird.<br />
Beispiel : Nam<strong>in</strong>g.reb<strong>in</strong>d("MyServer", serv);<br />
Die von der Methode werfbaren Exceptions müsssen gefangen werden.<br />
◇ Jeder Aufruf e<strong>in</strong>er RMI-Methode erfolgt <strong>in</strong> e<strong>in</strong>em eigenen Thread.<br />
E<strong>in</strong> mittels RMI realisierter Server ist grundsätzlich e<strong>in</strong> Multithread-Server.<br />
◇ Innerhalb e<strong>in</strong>er RMI-Methode kann der Rechner des aufrufenden Clients mittels der von RemoteServer geerbten<br />
statischen Methode getClientHost() ermittelt werden :<br />
public static Str<strong>in</strong>g getClientHost() throws ServerNotActiveException<br />
Funktionswert : Str<strong>in</strong>g-Repräsentation des Client-Rechners
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 824 – 03 – TH – 03<br />
------------------------------------------------------------------------------------<br />
• Entwicklung e<strong>in</strong>es Clients<br />
◇ Wesentliche Funktionalität des Clients :<br />
Erzeugung e<strong>in</strong>er RMI-Anwendung (3)<br />
► Erzeugung und Installation e<strong>in</strong>es Security-Managers<br />
► Erfragen e<strong>in</strong>er Referenz auf das entfernte RMI-Server-Objekt bei der RMI-Registry<br />
► Aufruf der RMI-Methoden über die erhaltene Referenz<br />
◇ Die Erzeugung und Installation e<strong>in</strong>es Security Managers erfolgt analog wie beim Server :<br />
if (System.getSecurityManager()==null)<br />
{<br />
System.setSecurityManager(new RMISecurityManager());<br />
}<br />
◇ Erfragen e<strong>in</strong>er Referenz auf das entfernte RMI-Server-Objekt bei der RMI-Registry<br />
Mittels der statischen Methode lookup() der Klasse Nam<strong>in</strong>g :<br />
public static Remote lookup(Str<strong>in</strong>g name) throws NotBoundException,<br />
MalformedURLException,<br />
RemoteException<br />
Parameter : name - URL-formatierter Str<strong>in</strong>g, der das zu suchende Objekt bezeichnet<br />
- Allgeme<strong>in</strong>e Form : "//host:port-nr/ObjectName".<br />
- Als Host (host) ist der Rechner (Name oder IP-Adresse) anzugeben, auf dem sich das<br />
gesuchte Objekt und die RMI-Registry bef<strong>in</strong>det.<br />
- Wenn die RMI-Registry auf dem Default-Port 1099 läuft, kann die Angabe der Port-Nr.<br />
(port-nr) weggelassen werden<br />
- "ObjectName" ist der Name des Objekts, unter dem es <strong>in</strong> der Registry registriert<br />
worden ist.<br />
Die Methode Nam<strong>in</strong>g.lookup() erzeugt unter Verwendung von Host und Port-Nr. e<strong>in</strong> Registry-Stub-Objekt,<br />
über das die Methode lookup() für die Registry mit "ObjectName" als Parameter aufgerufen wird.<br />
Diese gibt – sofern e<strong>in</strong> E<strong>in</strong>trag <strong>in</strong> der Registry vorhanden ist – e<strong>in</strong> Stub-Objekt für das gesuchte RMI-Server-Objekt<br />
zurück.<br />
Nam<strong>in</strong>g.lookup() gibt dieses Stub-Objekt als Referenz auf das RMI-Server-Objekt an den aufrufenden Client<br />
zurück (als Instanz des Interfaces Remote).<br />
Der Stub-Code wird – sofern er nicht lokal über die CLASSPATH-Environmentvariable gefunden wird – bis zum<br />
JDK 1.4 von der <strong>in</strong> der Registry für die Stub-Klasse abgelegten (und im Stub-Objekt angegebenen) Codebase geladen.<br />
Ab dem JDK 5.0 wird er lokal beim Client aus dem RMI-Interface erzeugt.<br />
Der Client wandelt den Typ des Stub-Objekts <strong>in</strong> den Typ des vom RMI-Server-Objekt implementierten RMI-Inter-<br />
faces um.<br />
◇ Der Client referiert das erhaltene Stub-Objekt als Instanz des vom RMI-Server-Objekt implementierten RMI-Inter-<br />
faces. Über diese Instanz erfolgt e<strong>in</strong> Aufruf der RMI-Methoden.
FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 824 – 04 – TH – 03<br />
------------------------------------------------------------------------------------<br />
Erzeugung e<strong>in</strong>er RMI-Anwendung (4)<br />
• Erzeugung der Stub- (und früher auch Skeleton-)Klassen<br />
◇ Ab dem (und für das) JDK 5.0 wird das Stub-Objekt dynamisch zur Laufzeit erzeugt<br />
ke<strong>in</strong>e explizite Erzeugung der Stub-Klasse erforderlich (ke<strong>in</strong> Aufruf von rmic).<br />
◇ Für Vor-JDK-5.0-Anwendungen muss die Stub-Klasse (und gegebenenfalls auch die Skeleton-Klasse) explizit mittels<br />
des RMI-Compilers (Stub-Generators) rmic aus der das RMI-Interface implementierenden RMI-Server-Klasse und<br />
dem RMI-Interface erzeugt werden.<br />
◇ Dem RMI-Compiler ist der voll-qualifizierte Package-Name der als <strong>Java</strong>-Byte-Code vorliegenden RMI-Server-<br />
Klasse als Parameter zu übergeben.<br />
◇ Die den <strong>Java</strong>-Byte-Code der RMI-Server-Klasse enthaltende Datei (.class-file) sowie die Datei mit dem <strong>Java</strong>-Byte-<br />
Code (oder mit dem Quell-Code) des RMI-Interfaces müssen über die CLASSPATH-Environment-Variable erreich-<br />
bar se<strong>in</strong>.<br />
◇ Zusätzlich kann beim Aufruf von rmic mit der "-d" Option angegeben werden, <strong>in</strong> welchem Ausgangs-Direc-<br />
tory die erzeugten <strong>Java</strong>-Byte-Code-Dateien (.class-files) für Stub (und gegebenenfalls Skeleton) abgelegt werden<br />
sollen (Ausgehend von diesem Directory erfolgt die Ablage <strong>in</strong> e<strong>in</strong>er dem vollqualifizierten Package-Namen entspre-<br />
chenden Directory-Struktur). Ohne diese Angabe dient das aktuelle Directory als Ausgangs-Directory.<br />
◇ Die von rmic erzeugten Klassen-Dateien für Stub (und gegebenefalls Skeleton) tragen den um _Stub bzw _Skel<br />
ergänzten Hauptnamen der RMI-Server-Klassen-Datei<br />
◇ Beispiel : (ohne Verwendung e<strong>in</strong>es Package-Namens)<br />
rmic –d G:\My<strong>Java</strong>\classes\ MyServerImpl<br />
Hierdurch werden die Dateien MyServerImpl_Stub.class und MyServerImpl_Skel.class im<br />
Directory G:\My<strong>Java</strong>\classes erzeugt.<br />
• Starten der RMI-Registry<br />
◇ Üblicherweise wird die RMI-Registry als eigener Prozeß (<strong>in</strong> e<strong>in</strong>er eigenen JVM laufend) auf dem Server-Rechner von<br />
der Kommandozeile aus mit dem Kommando rmiregistry gestartet. Falls die Registry nicht auf dem Default-<br />
Port 1099 arbeiten soll, muß die Port-Nr. beim Aufruf als Parameter angegeben werden.<br />
Beispiel : rmiregistry ( Registry läuft auf Port-Nr. 1099)<br />
rmiregistry 1248 ( Registry läuft auf Port-Nr. 1248)<br />
◇ Alternativ kann die Registry auch lokal für den Server-Prozeß von diesem erzeugt und gestartet werden<br />
(Statische Methode createRegistry() der Klasse LocateRegistry)<br />
◇ Achtung : Bis zum JDK 1.4 gilt : Die .class-Datei der Stub-Klasse(n) darf für die JVM der RMI-Registry nicht<br />
über die CLASSPATH-Environment-Variable erreichbar se<strong>in</strong>. Beim Start des Servers muss die Codebase, <strong>in</strong> der<br />
sich die Stub-Klasse bef<strong>in</strong>det, angegeben werden.<br />
Alternative ab dem JDK 5.0 : Der RMI-Registry kann statt der Stubklasse auch die .class-Datei des RMI-Interfaces<br />
zur Verfügung gestellt werden – entweder über die Codebase oder durch Bereitstellung e<strong>in</strong>er direkten Zugriffs-<br />
möglichket ( .class-Datei des RMI-Interfaces bef<strong>in</strong>det sich im Startverzeichnis der Registry oder die CLASSPATH-<br />
Variable enthält das Directory der .class-Datei )<br />
• Start des Servers und des Clients<br />
◇ Auf dem Server- und dem Client-Rechner s<strong>in</strong>d jeweils e<strong>in</strong>e JVM mit der jeweiligen Start-Klasse zu starten.<br />
◇ Als Optionen können die Codebase (URL) und die zu verwendende Policy-Datei (Dateipfad) angegeben werden<br />
(Default für die Policy-Datei : .java.policy im Heimat-Verzeichnis des Users)<br />
◇ Beispiel (für Server, ke<strong>in</strong> Package-Name) :<br />
java –Djava.rmi.server.codebase=http://cd2/~thomas/classes/<br />
-Djava.security.policy=my.policy MyServerImpl
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 825 – 01 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
• Zu lösende Aufgabe : Filterung von Text<br />
E<strong>in</strong>faches Demonstrationsbeispiel zu RMI <strong>in</strong> <strong>Java</strong> (1)<br />
◇ Lösung der Aufgabe des Demonstrationsbeispiels zur INET-Socket-Kommunikation mittels RMI<br />
◇ Def<strong>in</strong>ition e<strong>in</strong>es Remote-Interfaces, das die Methode filterStr<strong>in</strong>g() deklariert (RMI-Methode).<br />
◇ Das Remote-Interface wird durch e<strong>in</strong>e RMI-Klasse implementiert.<br />
In e<strong>in</strong>em Server-Programm wird e<strong>in</strong> Objekt dieser Klasse <strong>in</strong>stanziiert ( Remote-Objekt)<br />
◇ Die RMI-Klasse implementiert <strong>in</strong> ihrer ma<strong>in</strong>()-Methode auch die Server Start-Funktionalität.<br />
◇ Der zu filternde Text wird <strong>in</strong> e<strong>in</strong>em Client-Programm zeilenweise von der Standard-E<strong>in</strong>gabe e<strong>in</strong>gelesen<br />
Zur Filterung ruft der Client die RMI-Methode filterStr<strong>in</strong>g() des Remote-Objekts im Server auf.<br />
Der Name des Server-Rechners kann beim Client-Start durch Kommandozeilen-Parameter festgelegt werden.<br />
Falls das nicht erfolgt : Verwendung von Defaults.<br />
◇ Die RMI-Methode des Remote-Objekts des Servers filtert die erhaltenen Zeilen-Str<strong>in</strong>gs mittels e<strong>in</strong>es Filter-Objektes<br />
und gibt die gefilterten Str<strong>in</strong>gs als Funktionswert der RMI-Methode an den Client zurück.<br />
Das Filter-Objekt wird dem Remote-Objekt bei der Erzeugung im Konstruktor zu übergeben.<br />
◇ Das Client-Programm gibt die erhaltenen gefilterten Zeilen-Str<strong>in</strong>gs <strong>in</strong> die Standard-Ausgabe aus.<br />
◇ Die Art der Filterung wird durch die Klasse des vom Server-Programm e<strong>in</strong>gesetzten Filter-Objekts festgelegt.<br />
Diese muss das Interface TextFilter implementieren. (s. Beispiel zur INET-Socket-Kommunikation)<br />
Hier : Klasse UpcaseFilter (Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben)<br />
◇ Die RMI-Registry wird auf dem Default-Port 1099 gestartet.<br />
Das Remote-Objekt wird unter dem Namen "TextFilter" <strong>in</strong> der RMI-Registry registriert<br />
• Quelldatei mit der Def<strong>in</strong>ition des Remote-Interfaces (RMITextFilter.java)<br />
// RMITextFilter.java<br />
// Def<strong>in</strong>ition e<strong>in</strong>es Remote-Interfaces fuer Klassen zur TextFilterung<br />
import java.rmi.*;<br />
public <strong>in</strong>terface RMITextFilter extends Remote<br />
{<br />
public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str) throws RemoteException;<br />
}<br />
• Quelldatei mit Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für Text-Filter (TextFilter.java)<br />
(gleiches Interfaces wie im Beispiel zur INET-Socket-Kommunikation)<br />
// TextFilter.java<br />
// Def<strong>in</strong>ition e<strong>in</strong>es Interfaces fuer Klassen zur TextFilterung<br />
public <strong>in</strong>terface TextFilter<br />
{<br />
public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str);<br />
}
FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 825 – 02 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
E<strong>in</strong>faches Demonstrationsbeispiel zu RMI <strong>in</strong> <strong>Java</strong> (2)<br />
• Quelldatei mit der Def<strong>in</strong>ition der RMI-Server-Klasse (RMIFilterServer.java)<br />
// RMIFilterServer.java<br />
// Start-Klasse e<strong>in</strong>es Servers zum Filtern von Str<strong>in</strong>gs<br />
// Implementierung des Remote-Interfaces RMITextFilter<br />
// E<strong>in</strong>faches Demo-Beispiel zu RMI<br />
import java.rmi.*;<br />
import java.rmi.server.*;<br />
public class RMIFilterServer extends UnicastRemoteObject<br />
implements RMITextFilter<br />
{<br />
TextFilter fil;<br />
}<br />
public RMIFilterServer(TextFilter tf) throws RemoteException<br />
{ super();<br />
fil = tf;<br />
}<br />
public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str) throws RemoteException<br />
{<br />
try<br />
{ System.out.pr<strong>in</strong>tln("Remote-Aufruf von : " + RemoteServer.getClientHost());<br />
}<br />
catch (ServerNotActiveException ex)<br />
{ System.err.pr<strong>in</strong>tln("ke<strong>in</strong> Remote-Aufruf");<br />
}<br />
return fil.filterStr<strong>in</strong>g(str);<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
if (System.getSecurityManager() == null)<br />
System.setSecurityManager(new RMISecurityManager());<br />
try<br />
{ RMITextFilter fil = new RMIFilterServer(new UpcaseFilter());<br />
Nam<strong>in</strong>g.reb<strong>in</strong>d("TextFilter", fil);<br />
System.out.pr<strong>in</strong>tln("TextFilter bound <strong>in</strong> Registry");<br />
}<br />
catch (Exception ex)<br />
{ System.out.pr<strong>in</strong>tln("RMIFilterServer error : " + ex.getMessage());<br />
ex.pr<strong>in</strong>tStackTrace();<br />
}<br />
}<br />
• Beispiel e<strong>in</strong>er Text-Filter-Klasse : Quelldatei UpcaseFilter.java<br />
(gleiche Klasse wie im Beispiel zur INET-Socket-Kommunikation)<br />
// UpcaseFilter.java<br />
// Klasse zur Filterung von Str<strong>in</strong>gs : Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben<br />
// Implementierung des Interfaces TextFilter<br />
public class UpcaseFilter implements TextFilter<br />
{<br />
public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str)<br />
{<br />
return str.toUpperCase();<br />
}<br />
}
FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – 825 – 03 – TH – 02<br />
-----------------------------------------------------------------------------------<br />
E<strong>in</strong>faches Demonstrationsbeispiel zu RMI <strong>in</strong> <strong>Java</strong> (3)<br />
• Quelldatei mit der Def<strong>in</strong>ition der RMI-Client-Klasse (RMIFilterClient.java)<br />
// RMIFilterClient.java<br />
// Filterung von Str<strong>in</strong>gs, die ueber die Standarde<strong>in</strong>gabe e<strong>in</strong>gegeben werden<br />
// E<strong>in</strong>faches Demo-Beispiel zu RMI<br />
import java.rmi.*;<br />
import java.io.*;<br />
public class RMIFilterClient<br />
{<br />
static f<strong>in</strong>al Str<strong>in</strong>g DEF_HOST = "localhost";<br />
}<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />
{<br />
Str<strong>in</strong>g host = DEF_HOST;<br />
if (args.length>0)<br />
host = args[0];<br />
Str<strong>in</strong>g server = "//"+host+"/"+"TextFilter";<br />
if (System.getSecurityManager() == null)<br />
System.setSecurityManager(new RMISecurityManager());<br />
try<br />
{<br />
RMITextFilter fil = (RMITextFilter) Nam<strong>in</strong>g.lookup(server);<br />
Pr<strong>in</strong>tStream stdout = System.out;<br />
BufferedReader std<strong>in</strong> = new BufferedReader(new InputStreamReader(System.<strong>in</strong>));<br />
Str<strong>in</strong>g l<strong>in</strong>e;<br />
stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />
while ((l<strong>in</strong>e = std<strong>in</strong>.readL<strong>in</strong>e()) != null)<br />
{<br />
l<strong>in</strong>e = fil.filterStr<strong>in</strong>g(l<strong>in</strong>e); // RMI-Aufruf !!!<br />
stdout.pr<strong>in</strong>tln("Ausgabe : " + l<strong>in</strong>e);<br />
stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />
}<br />
}<br />
catch(Exception ex)<br />
{<br />
System.err.pr<strong>in</strong>tln("RMIFilterClient Exception : " + ex.getMessage());<br />
ex.pr<strong>in</strong>tStackTrace();<br />
}
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – A00 – 00 – TH – 01<br />
-----------------------------------------------------------------------------------<br />
<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />
Anhang A<br />
A. Modellierung von OOP-Programmen<br />
A.1. Klassenkategorien<br />
A.2. Klassembeziehungen<br />
A.3. Klassendiagramm und Sequenzdiagramm der UML
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – A11 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Klassenkategorien<br />
◇ E<strong>in</strong> objektorientiertes Softwaresystem (OO-Programm) ist als e<strong>in</strong>e Ansammlung <strong>in</strong>teragierender Objekte organisiert.<br />
◇ Die e<strong>in</strong>zelnen Objekte decken dabei unterschiedliche Aufgabenbereiche ab. Entsprechend ihrem jeweiligen Aufgaben-<br />
bereich können sie und damit die sie beschreibenden Klassen unterschiedlichen Kategorien zugeordnet werden.<br />
Objekte und Klassen besitzen e<strong>in</strong>en Stereotype.<br />
◇ Auch die gegebenenfalls zwischen Klassen bestehenden Beziehungen lassen sich <strong>in</strong> verschiedene Arten e<strong>in</strong>teilen.<br />
• Gebräuchliche Klassenkategorien<br />
▻ Entity-Klassen<br />
Das s<strong>in</strong>d Klassen, deren Objekte Bestandteil des Problembereichs s<strong>in</strong>d (Domänen-Klassen).<br />
Sie reflektieren entweder reale Objekte des Problembereichs oder sie werden zur Wahrnehmung <strong>in</strong>terner Aufgaben<br />
des Systems benötigt.<br />
Es kann sich dabei um konkrete technische Objekte (z.B. Pkw) handeln, es können aber auch Personen und deren<br />
Rollen (z.B. Student, Kunde) Orte, (z.B.Hörsaal), Organisationse<strong>in</strong>heiten (z.B.Fachbereich), Ereignisse (z.B. Unfall),<br />
Informationen über (Inter-)Aktionen (z.B. Kaufvertrag), Konzepte (z.B. Entwicklungsplan), sonstige allgeme<strong>in</strong>e<br />
oder problembereichsbezogene Begriffe (z.B.Lehrveranstaltung) usw. se<strong>in</strong><br />
Objekte von Entity-Klassen s<strong>in</strong>d typischerweise unabhängig von der Systemumgebung und von der Art und Weise,<br />
wie das System mit der Umgebung kommuniziert.<br />
Häufig s<strong>in</strong>d sie auch applikationsunabhängig, d.h. sie lassen sich <strong>in</strong> mehreren Applikationen e<strong>in</strong>setzen.<br />
▻ Interface-Klassen (Boundary Classes)<br />
Objekte dieser Klassen s<strong>in</strong>d für die Kommunikation zwischen der Systemumgebung und dem Inneren des Systems<br />
zuständig.<br />
Sie realisieren die Schnittstelle des Systems zum Sytembenutzer (Benutzeroberfläche) bzw zu anderen Systemen.<br />
Sie bilden den umgebungsabhängigen Teil e<strong>in</strong>es Systems.<br />
▻ Controller-Klassen (Control Classes)<br />
Objekte von Controller-Klassen steuern den Ablauf, d.h. die Zusammenarbeit der übrigen Objekte zur Realisierung<br />
e<strong>in</strong>es oder mehrerer Use Cases.<br />
Es handelt sich um aktive Objekte.<br />
Typischerweise s<strong>in</strong>d sie applikationsspezifisch.<br />
▻ Service-Klassen<br />
Objekte von Service-Klassen stellen anderen Objekten (<strong>in</strong>sbesondere den Controller-Objekten) Dienste zur Verfügung.<br />
Häufig handelt es um Klassen aus e<strong>in</strong>er Bibliothek.<br />
Sie können aber auch durch Auslagerung von Funktionalitäten anderer Klassen gebildet werden.<br />
▻ Utility-Klassen<br />
Sie kapseln Daten und Operationen (Funktionen), die global verfügbar se<strong>in</strong> sollen.<br />
Im allgeme<strong>in</strong>en werden sie nicht <strong>in</strong>stanziiert.<br />
Beispiel : mathematische Konstanten u. mathematische Funktionen.<br />
Die konsequente Unterscheidung und Trennung von Entity-, Interface- und Controller-Klassen führt zur "Model-View-<br />
Controller"-Architektur (MVC-Architektur), e<strong>in</strong> allgeme<strong>in</strong> e<strong>in</strong>geführtes OOP-Paradigma.<br />
Das User-Interface (View) ist von der eigentlichen Problembearbeitung (Model) getrennt und weitgehend entkoppelt.<br />
Die Verb<strong>in</strong>dung zwischen beiden wird über e<strong>in</strong>en Controller hergestellt.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – A21 – 00 – TH – 04<br />
-----------------------------------------------------------------------------------<br />
• Vererbungsbeziehung<br />
Beziehungen zwischen Klassen<br />
◇ Beziehung zwischen Klassen, deren Komponenten sich teilweise überdecken<br />
◇ E<strong>in</strong>e abgeleitete Klasse erbt die Eigenschaften und Fähigkeiten (Komponenten) der Basisklasse(n).<br />
"ist"-Beziehung e<strong>in</strong> Objekt der abgeleiteten Klasse ist auch e<strong>in</strong> Objekt der Basisklasse(n)<br />
◇ Ordnungspr<strong>in</strong>zip bei der Spezifikation von Klassen.<br />
Generalisierung / Spezialisierung<br />
• Nutzungsbeziehungen<br />
◇ Unter e<strong>in</strong>er (statischen) Nutzungsbeziehung versteht man e<strong>in</strong>e <strong>in</strong> e<strong>in</strong>em konkreten Anwendungsbereich geltende<br />
Beziehung zwischen Klassen, deren Instanzen vone<strong>in</strong>ander Kenntnis haben und die dadurch mite<strong>in</strong>ander kommuni-<br />
zieren können<br />
Nutzungsbeziehungen s<strong>in</strong>d notwendig für die Interaktion von Objekten<br />
◇ Assoziation<br />
- Spezielle Beziehung zwischen Klassen bzw Objekten, bei der die Objekte unabhängig vone<strong>in</strong>ander existieren und<br />
lose mite<strong>in</strong>ander gekoppelt s<strong>in</strong>d<br />
Beispiel : e<strong>in</strong>em Objekt wird e<strong>in</strong> anderes Objekt als Parameter übergeben.<br />
- Name : Kennzeichnung der Semantik der Beziehung zwischen den Klassen<strong>in</strong>stanzen<br />
- Navigationsrichtung : legt die Kommunikationsrichtung und die Richtung, <strong>in</strong> der e<strong>in</strong> Objekt der e<strong>in</strong>en Klasse e<strong>in</strong><br />
Objekt der anderen Klasse referieren kann, fest.<br />
bidirektional (Kommunikation <strong>in</strong> beiden Richtungen möglich) oder unidirektional<br />
- Rolle : E<strong>in</strong> Name für die Aufgabe, die e<strong>in</strong> Objekt der assoziierten Klasse aus der Sicht e<strong>in</strong>es Objekts der assoziie-<br />
renden Klasse wahrnimmt.<br />
- Kard<strong>in</strong>alität (multiplicity) : bezeichnet die mögliche Anzahl der an der Assoziation beteiligten Instanzen e<strong>in</strong>er<br />
Klasse.<br />
◇ Aggregation<br />
- Spezielle Beziehung zwischen Klassen bzw Objekten, bei der die Objekte der e<strong>in</strong>en Klasse Bestandteile (Kompo-<br />
nenten) e<strong>in</strong>es oder mehrerer Objekte der anderen Klasse s<strong>in</strong>d. zwischen den Objekten besteht e<strong>in</strong>e feste Kopplung<br />
- "hat"-Beziehung bzw "ist Teil von"-Beziehung<br />
- Das "umschließende" Objekt bildet e<strong>in</strong>en Conta<strong>in</strong>er für das bzw die enthaltene(n) Objekt(e)<br />
- Aggregation kann als Spezialfall der Assoziation aufgefaßt werden.<br />
die für Assoziationen möglichen Kennungen (Name usw.) lassen sich auch für Aggregationen verwenden.<br />
- e<strong>in</strong>e Aggregation ist i.a. aber e<strong>in</strong>e unidirektionale Beziehung (Navigation vom umschließenden Objekt zu den Kom-<br />
ponenten-Objekten)<br />
Je nach dem Grad der Kopplung unterscheidet man :<br />
▻ e<strong>in</strong>fache Aggregation<br />
Das umschließende Objekt (Aggregat) und die Komponenten s<strong>in</strong>d nicht existenzabhängig<br />
E<strong>in</strong>e Komponente kann zusätzlich noch weiteren Aggregaten der gleichen oder e<strong>in</strong>er anderen Klasse zugeordnet<br />
se<strong>in</strong>.<br />
Bei Löschung des Aggregats bleiben die Komponenten unabhängig vom Aggregat erhalten.<br />
Beispiel : Klasse mit dynamisch erzeugten Komponenten<br />
▻ echte Aggregation (Komposition, composite aggregation)<br />
Die Komponenten können nur e<strong>in</strong>em Aggregat zugeordnet se<strong>in</strong> und nur <strong>in</strong>nerhalb des Aggregats existieren.<br />
Bei Löschung des Aggregats werden auch die Komponenten gelöscht.<br />
Beispiel : Klasse mit statisch allozierten Komponenten<br />
◇ Anmerkung :<br />
In der Praxis kann es im E<strong>in</strong>zelfall sehr schwierig se<strong>in</strong>, zwischen Assoziation und Aggregation und den verschiedenen<br />
Formen der Aggregation zu unterscheiden.
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
FG TECHNISCHE INFORMATIK V – JV – A31 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Allgeme<strong>in</strong>es<br />
Modellierung<br />
◇ Das zu entwickelnde Software-System sowie der von ihm abzudeckende Problembereich s<strong>in</strong>d häufig so komplex,<br />
dass sie sich nur mit Hilfe geeigneter Hilfsmittel ausreichend erfassen lassen.<br />
E<strong>in</strong> derartiges Hilfsmittel stellt die Modellierung dar.<br />
◇ I.a. ist es wenig s<strong>in</strong>nvoll das Gesamtsystem <strong>in</strong> e<strong>in</strong>em e<strong>in</strong>zigen – alle E<strong>in</strong>zelheiten erfassenden – Modell darzustellen.<br />
Vielmehr setzt man unterschiedliche Modelle e<strong>in</strong>, die jeweils verschiedene Teilaspekte des Systems repräsentieren.<br />
Diese Modelle erleichtern nicht nur das Problembereichs- und Systemverständnis, sondern bilden auch e<strong>in</strong> wesentliches<br />
Kommunikationsmittel aller an der Systementwicklung beteiligten Personen und stellen damit auch e<strong>in</strong>en wichtigen<br />
Bestandteil der Systemdokumentation dar.<br />
◇ Voraussetzung für die Bildung adäquater, ausagekräftiger, e<strong>in</strong>deutiger und leicht verständlicher Modelle ist e<strong>in</strong>e geeig-<br />
nete Notation zur Modelbeschreibung.<br />
Für den Bereich der objektorientierten Systementwicklung ist dies die Unified Model<strong>in</strong>g Language (UML), mit der<br />
Mo delle <strong>in</strong> überwiegend graphischer Notation ( Diagramme) dargestellt werden können.<br />
◇ Die UML stellt Sprachmittel zur Formulierung zahlreicher unterschiedlicher Diagramme zur Verfügung, die zur<br />
Beschreibung der verschiedenen Modelle geeignet s<strong>in</strong>d.<br />
• Modelle und zugeordnete UML-Diagramme<br />
◇ Modell der Systemnutzung<br />
▻ Nutzungsfallmodell (Anwendungsfallmodell) Use-Case-Diagramm<br />
◇ Logisches Modell<br />
▻ Statisches Modell<br />
grobe Systemarchitektur (Aufbaustruktur) Paketdiagramm<br />
detaillierte Systemarchitektur Klassendiagramm<br />
▻ Dynamisches Modell<br />
Zusammenarbeit mehrerer Objekte (Objekt-Interaktion) Interaktionsdiagramme :<br />
Sequenzdiagramm<br />
Kollaborationsdiagramm<br />
Objektverhalten (<strong>in</strong> mehreren Use Cases) Zustandsdiagramm<br />
Systemverhalten Aktivitätsdiagramm<br />
◇ Physikalisches Modell<br />
▻ Implementierungsmodell Komponentendiagramm (Moduldiagramm)<br />
▻ Konfigurierungsmodell Verteilungsdiagramm (Deployment Diagram)<br />
(topologische Strukturierung und Verteilung/Zuordnung<br />
der Soft- und Hardwarekomponenten des Gesamtsystems)
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – A32 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Klassendiagramm<br />
Unified Modell<strong>in</strong>g Language (UML) (1)<br />
◇ E<strong>in</strong> Klassendiagramm beschreibt die im System e<strong>in</strong>gesetzten Klassen und ihre statischen Beziehungen (Vererbungs-<br />
beziehungen und Nutzungsbeziehungen).detailliertes statisches Systemmodell<br />
◇ Zur Erhöhung der Übersichtlichkeit kann die Gesamtheit der Klassen e<strong>in</strong>es Systems auf mehrere Teildiagramme<br />
aufgeteilt se<strong>in</strong><br />
• Elemente des Klassendiagramms<br />
Vererbung<br />
Nam eOfClass<br />
attribut : ty pe = <strong>in</strong>itval<br />
operation(argnam e : type) : returnTy pe<br />
M yS tr<strong>in</strong>g<br />
M yS trM itF arbe<br />
Class A<br />
Klasse<br />
Assoziation (bidirektional)<br />
CharF ilter<br />
theRoleA<br />
theRoleB<br />
1<br />
1<br />
Assoziation (unidirektional)<br />
Aggregation<br />
ClassB<br />
M yS tr<strong>in</strong>g<br />
Tex tF ilterCtrl CharFilt er<br />
Order Task<br />
1 1. .*<br />
Komposition (echte Aggregation)
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – A33 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Beispiel für Klassendiagramme<br />
Manager<br />
*<br />
TextFileReader<br />
Unified Modell<strong>in</strong>g Language (UML) (2)<br />
1<br />
1<br />
1<br />
Person<br />
Firma<br />
*<br />
1<br />
Entwickler<br />
1<br />
1<br />
2..n<br />
Projektleiter<br />
Auftraggeber<br />
TextFilterCtrl<br />
1<br />
CharFilter<br />
1..*<br />
1<br />
Projekt<br />
*<br />
TextFileWriter
HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />
BEREICH DATENTECHNIK V – JV – A34 – 00 – TH – 05<br />
-----------------------------------------------------------------------------------<br />
• Sequenzdiagramm<br />
Unified Modell<strong>in</strong>g Language (UML) (3)<br />
◇ E<strong>in</strong> Sequenzdiagramm beschreibt die Interaktion mehrerer Objekte.<br />
◇ Für jedes Scenario jedes Use Cases sollte e<strong>in</strong> eigenes Diagramm erstellt werden.<br />
• Beispiel für e<strong>in</strong> Sequenzdiagramm