20.07.2013 Aufrufe

Programmieren in Java - LSW

Programmieren in Java - LSW

Programmieren in Java - LSW

MEHR ANZEIGEN
WENIGER ANZEIGEN

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

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

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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!