211
5 Ziele der Vorlesung Programmierung Kontext: Programmierung im Software-Entwicklungsprozess Grundlegende objektorientierte Konzepte Programmieren in Java Neugier auf weiterführende Java-Themen 6 Anforderungen an die Beteiligten Dozent: Vermitteln des Stoffes in angemessenem Tempo Gratwanderung zwischen Breite und Tiefe Ausgleich der unterschiedlichen Vorkenntnisse Blick über den Vorlesungstellerrand Übungsorganisatoren / Tutoren: Vertiefen der Vorlesungsinhalte durch Übungen Einführung in die praktische Nutzung einer Programmiersprache Lernhilfen und zusätzliche Herausforderungen 7 Anforderungen an die Beteiligten Studierende: eigenständige Nachbearbeitung Auseinandersetzung mit Primär- und Sekundärliteratur Teilnahme an der Vorlesung und an den Übungen Überwinden der Praxisschwelle vorbelastete Studierende (also die, die meinen sie könnten Java und/oder programmieren): darauf achten, dass der geeignete Einsprungpunkt nicht verpasst wird! 8 Hinweise zum Feedback Mehrfache Abfrage Ihres Feedbacks und direkte Veröffentlichung der Ergebnisse Versuch der Umsetzung der erkannten Verbesserungsmaßnahmen Interaktives Feedback jederzeit willkommen!

Java

Embed Size (px)

Citation preview

Page 1: Java

5

Ziele der Vorlesung Programmierung

Kontext: Programmierung im Software-Entwicklungsprozess

Grundlegende objektorientierte Konzepte

Programmieren in Java

Neugier auf weiterführende Java-Themen

6

Anforderungen an die Beteiligten

Dozent:Vermitteln des Stoffes in angemessenem TempoGratwanderung zwischen Breite und TiefeAusgleich der unterschiedlichen VorkenntnisseBlick über den Vorlesungstellerrand

Übungsorganisatoren / Tutoren:Vertiefen der Vorlesungsinhalte durch ÜbungenEinführung in die praktische Nutzung einerProgrammierspracheLernhilfen und zusätzliche Herausforderungen

7

Anforderungen an die Beteiligten

Studierende:eigenständige NachbearbeitungAuseinandersetzung mit Primär- und SekundärliteraturTeilnahme an der Vorlesung und an den ÜbungenÜberwinden der Praxisschwelle

vorbelastete Studierende (also die, die meinen sie könnten Javaund/oder programmieren):darauf achten, dass der geeignete Einsprungpunkt nichtverpasst wird!

8

Hinweise zum Feedback

Mehrfache Abfrage Ihres Feedbacks und direkte Veröffentlichungder Ergebnisse

Versuch der Umsetzung der erkanntenVerbesserungsmaßnahmen

Interaktives Feedback jederzeit willkommen!

Page 2: Java

9

Hinweise zu MaterialienFolienskrip wird zur Verfügung gestellt, einige Teile werden in der

Vorlesung entwickelt!

Zu allen fehlenden Teilen wird auf Literatur verwiesen.

Folien sind Stichpunkte! Es gilt das gesprochene Wort!Übungenoptionale Abschnitte

Hilfreich: Anmerkungen in den Folien und handschriftlicheErgänzungen (-> aktive Teilnahme)

10

Literatur

• Originalliteratur von JavaSoft

http://www.javasoft.com/docs/index.html

• Sonstige Literatur

11

Literatur von JavaSoft

• The Java Tutorial– Als Online- und Downloadversion– Als Buchversion in deutsch und englisch (meist nicht so aktuell)– Sehr umfangreich, ausführliche Beschreibung vieler Aspekte der

Sprache und Einführung in den Umgang mit Klassenbibliotheken– Gesamtübersicht der Klassenbibliotheken liefert

"JDK 1.2 Documentation“/Java 2 SDK, SE v1.3 Documentation– Für exakte Syntaxdefinition der Sprache ist die "Java Language

Specification" gedacht.– Es ist kein Programmierlehrbuch.

12

Literatur von JavaSoft

• JDK 1.2 /Java 2 SDK, SE v1.3 Documentation– Als Online- und Downloadversion– Gesamtbeschreibung der Klassenbibliothek– Als Nachschlagewerk gedacht, kein Tutorial

• Java Language Specification– Als Online- und Downloadversion– Komplette Beschreibung der Syntax– Sehr schwer zu lesen– Syntaktische Feinheiten, die im Tutorial nicht deutlich werden

Page 3: Java

13

Literatur von JavaSoft

• Java Virtual Machine Specification– Spezifikation der virtuellen Maschine– Nur für Leute gedacht, die selbst Java-Compiler schreiben wollen– Wichtig, um offenen Standard zu gewährleisten (im Gegensatz zu vielen

Microsoft-Produkten)

• Java Developer Connection– http://www.javasoft.com/jdc– Kostenlose Anmeldung erforderlich– Viele Informationen über neueste Entwicklungen– Downloadmöglichkeit von Beta-Versionen

14

Sonstige Literatur

• "Einführung in die objektorientierte Programmierung mit Java"– Autoren: E.-E. Doberkat / S. Dißmann– Erschienen 1998 im Oldenbourg Verlag, München, ISBN 3-486-24786-7– Programmierlehrbuch, beschreibt verschiedene Programmiertechniken,

Begleitung zur Vorlesung an der Universität Dortmund

• "Java 1.1 lernen"– Autor: Guido Krüger– Erschienen bei Addison-Wesley-Longman 1997– Einführungsbuch, gut für erste Schritte– Keine erschöpfende Behandlung vieler Themen, nur erster Überblick– Nicht als Nachschlagewerk zu empfehlen

Inde

rU

ni-B

iblio

thek

verf

ügba

r!

15

Sonstige Literatur

• ”Thinking in Java”– Autor: Bruce Eckel– http://www..eckelobjects.com/javabook.html

16

Sonstige Literatur

• "Java in a nutshell"– Autor: David Flanagan, deutsche Übersetzung: Peter Klicman– Erschienen bei O'Reilly 1998– Lehrbuch für den Fortgeschritten– gut geeignet für C/C++ - Programmierer– Erschöpfende Klassenübersicht– Wichtige Details für die Praxis

• "Foundations of Computer Science”– Autor: Alfred V. Aho, Jeffrey D. Ullman– Erschienen bei W.H. Freeman and Company 1995– Grundlegende Konzepte und Datenstrukturen

Page 4: Java

17

Sonstige Literatur

• "Fundamentals of Software Engineering"– Autor: Carlo Ghezzi, Mehdi Jazayeri, Dino Mandrioli– Erschienen bei Prentice-Hall, 1991– guter Überblick über Software-Technologie und die Einbettung der

Programmierung

18

Gliederung der Vorlesung1 Vorwort und Zielsetzung2 Einordnung der Vorlesung “Programmierung”

2.1 Kontext Informatik2.2 Kontext Software-Entwicklung

3 Objektorientierte Analyse und objektorientierter Entwurf4 Grundbegriffe zu Programmiersprachen5 Java als objektorientierte Programmiersprache6 Ein erstes Java-Beispiel

19

Gliederung der Vorlesung

7 Java-Syntaxkonstrukte

7.1 Primitive Datentypen, Literale und Variablen7.2 Aufruf von Objekten, einfacher Nachrichtenaustausch7.3 Operatoren, Ausdrücke, Zuweisungen7.4 Anweisungen

8 Programmierkonventionen und Dokumentation9 Rekursive Methoden

10 Innere Klassen11 Elementare Java-Klassen

11.1 String11.2 Felder11.3 Object

20

Gliederung der Vorlesung12 Ähnliche Objekte (Vererbung)13 Schnittstellen (Interfaces)14 Ausnahmen (Exceptions)15 Pakete und Zugriffskontrolle16 Überblick über Java-Klassenbibliotheken17 Dynamische Datenstrukturen, ihre Anwendung und ihre

Realisierung mit Java17.1 Listen17.2 Bäume17.3 Graphen17.4 Schlangen17.5 Stapel17.6 Mengen

Page 5: Java

21

Gliederung der Vorlesung18 Ein- und Ausgabe (java.io)19 Graphische Oberflächen (java.awt, java.swing)20 Applets (java.applet)21Threads22 Rückblick, Ausblick, Fazit Kapitel 2

Einordnung der Vorlesung Programmierung

Kapitel 2.1

Kontext Informatik

24

Kontext Informatik

Informatik:keine Naturwissenschaft(noch?) keine Ingenieurwissenschaft

weil• bewährte Abstraktionen / Lösungsmuster fehlen• nicht einheitlich bezeichnet und verwendet werden• zuverlässige Planungen der Erstellung von Lösungen kaum möglich

sind

Page 6: Java

25

Aufteilung Informatik

Theoretische Informatik : allgemeingültige Berechnungsmodelle,Gesetzmäßigkeiten, zunächst: anwendungsunabhängig

Praktische Informatik : Anwendung der Ergebnisse undErkenntnisse der theoretischen Informatik auf Probleme derNutzbarmachung von Rechnern, Bau von Compilern, Entwurfvon Spezifikationssprachen

Angewandte Informatik : Anwendung der Ergebnisse dertheoretischen und praktischen Informatik zum Zweck derLösung real existierender Probleme, Ziel: Wirtschaftlichkeit

26

Kontext Informatik

Modellbildung und Abstraktion als durchgängig verwendetePrinzipien in der Informatik, z.B:

– von der realen Welt zur Beschreibung der relevanten Teile– von realen Problemen zu Entwürfen– von Entwürfen zu Programmen

Hierbei die immer gleiche Frage:Was gehört ins Modell?Was wird wegabstrahiert?

27

Kontext Informatik

Wahl der richtigen Abstraktion oft schon entscheidend fürden Erfolg der Entwicklung vonDatenverarbeitungslösungen!

Eine der wesentlichen Abstraktionen manifestiert sich inProgrammen. Hierin spiegelt sich die Entscheidung, bestimmteMerkmale der realen Welt als für den Problembereichaufzufassen und diese in bestimmter Weise abzubilden.

28

Kontext Informatik

Die Vorlesung „Programmierung“ beschäftigt sich mit der Frage,wie das Ergebnis der Abbildung (Programme) aussehen sollte.Hierbei wird angenommen, dass Klassen und Objekte diegrundlegenden Konstrukte sind, um Programme zurepräsentieren / zu strukturieren.

In der Vorlesung „Programmierung“ wird genau eine Sprache zurFormulierung von Programmen vermittelt. Diese Sprache heißtJava. Java ist objektorientiert.

Page 7: Java

Kapitel 2.2

Kontext Software-Entwicklung

30

Kontext Software-Entwicklung

Obwohl eine hohe volkswirtschaftliche und betriebswirtschaftlicheAbhängigkeit von Software besteht

– komplexe Software in allen Bereichen des Lebens– eingebettete Software in PKWs, Haushaltsgeräten– Steuerung in der Verkehrs- und Energietechnik– admininistrative Geschäftsprozesse in fast allen Unternehmen– Software-Kosten als substantieller Anteil in vielen IT-Etats (häufig:

Wartung)– Einfluß auf fast alle Innovationen

ist die Entwicklung von Software nach wie vor mit hohen Risikenbehaftet.

31

Anzahl Function Points Früher als geplant Termingerecht Verspätet Abgebrochen1 FP 14,86 % 83,16 % 1,92 % 0,25 %

10 FP 11,08 % 81,25 % 5,67 % 2,00 %100 FP 6,06 % 74,77 % 11,83 % 7,33 %

1.000 FP 1,24 % 60,76 % 17,67 % 20,33 %10.000 FP 0,14 % 28,03 % 23,83 % 48,00 %

100.000 FP 0,00 % 13,67 % 21,33 % 65,00 %Durchschnitt 5,53 % 56,94 % 13,71 % 23,82 %

Quelle: C. Jones, Large Software System Failures and Successes,in: American Programmer, Vol. 9, No. 5, September 1996

Abbruchrate von Software-Entwicklungsprojekten

32

Ursachen der Unzuverlässigkeit von Software-Entwicklung nach [CKI88]

B. Curtis, H. Krasner, N. Iscoe, A Field Study of the Software Design Process for Large Systems,Communications of the ACM, November 1988, Vol. 31, No. 11, pp 1268 - 1287

Thin Spread of Application Domain KnowledgeProjekte in neuer BrancheTechnologiezentriertheit

Fluctuating and Conflicting RequirementsMarktverschiedene Kunden

ErkenntnisprozesseMißverständnisse

Communication and Coordination Breakdownsunterschiedliche Vorstellungen und ZielsetzungenInkongruenzen zwischen Kompetenz und VerantwortungKapitulation

Page 8: Java

33

Aspekte der Software-EntwicklungUnter Software-Entwicklung verstehen wir das Zusammenspiel

der folgenden vier Bereiche:

Projektmanagement :Kosten, Zeit, Personal

Qualitätsmanagement :Übereinstimmung mit den Anforderungen

Konfigurationsmanagement :Verwalten aller Bestandteile einerDatenverarbeitungslösungen und ihrer Versionen

Software-Erstellung:Erstellen aller Modelle (z.B. Programme)

34

Prinzipien des SWE

Prinzip: Grundsatz, den man seinem Handeln zugrundelegtTechnik: Vorschrift zur Durchführung einer Tätigkeit (Was ist wie zu tun?)

Methode: Planmäßig anwendbare, begründete Technik zur Erreichung vorgegebenerZiele (Was ist wie und unter welchen Rahmenbedingungen zu tun, so daß eingutes Ergebnis erreicht wird?)

Werkzeuge: Rechnerunterstützung für Techniken und MethodenSprache: syntaktische Regeln zur Unterstützung einer Methode oder Technik. Eine

Sprache besteht aus ihrer Syntax und ihrer Semantik:

formale Sprachen haben eine formale Syntax- und Semantikdefinition (Aussagenlogik,Prädikatenlogik)

semiformale Sprachen haben eine formale Syntax, aber keine klar definierte Semantik(SADT, UML)

informale Sprachen haben weder eine formale Syntax noch eine formale Semantik(Deutsch, Englisch)

35

Prinzipien des SWE

Prinzipien

Methoden(Techniken)

Sprachen

Werkzeuge

Dekomposition

OO / funktional

UML/SADT

OTW/PRADOS

36

Prinzip Striktheit und Formalität

strikte Anforderungsdefinitionstrikte Dokumentation des Software-Prozesses und seiner

Ergebnissestrikter Entwurfstrikte Spezifikation aller Dokumenteformale Beschreibung an kritischen Stellen

kritisch für das Verständniskritisch im Hinblick auf spätere Änderbarkeitkritisch im Hinblick auf das Schadenspotential von Mißverständnissen

Page 9: Java

37

(separation of concerns / Unterteilung in Aspekte)

Beispiele von AspektenFunktionalität

RobustheitPerformanz und RessourcenverbrauchOrganisation der Software-Entwicklung

Konfigurations-Managementund viele andere concerns Striktheit und Formalität

Abhängigkeit zwischen AspektenPerformanz und DatenintegritätFunktionalität und Zielplattform

Prinzip Strukturierung

38

Arten der Unterteilung

zeitliche Unterteilung: Anforderungsanalyse / Entwurf / Programmierung / Testqualitative Unterteilung: Effizienz / Robustheit / Korrektheit

perspektivische Unterteilung: Verwendung von Datenstrukturen / Datenfluß /Kontrollfluß

Dekomposition (Unterteilung in Bestandteile): Komponente 1, Komponente 2

Prinzip Strukturierung

39

Dekomposition Komposition

Legende

Komponente /Modul

A

B

A ruft B auf

Prinzip Strukturierung

40

Trennung von wichtigen und unwichtigen Merkmalen„Unterschlagung“ / „Wegabstraktion“ der unwichtigen und Betonung der

wichtigen zum Zweck der Konzentration auf das WesentlicheGängige Abstraktionen

die Signatur einer Operation abstrahiert von der Realisierung der Operation

die Konstrukte einer Programmiersprache abstrahieren von Prozessorendetailsein Datenflußdiagramm abstrahiert von den Aufrufstrukturen zwischen Komponenten

Prinzip Abstraktion

Page 10: Java

41

Wichtigkeit und Unwichtigkeit ist relativ zum Zweck der Abstraktion

Realität Modell

verkürzendeEigenschaften

erweiterndeEigenschaften

Erde Landkarte

Verkürzende Eigenschaften im Modell „Landkarte“:

• Wassertemperatur• Fauna / Flora

Erweiternde Eigenschaften:

• Längen- und Breitengrade

Prinzip Abstraktion

42

Software ist Gegenstand von Änderungen. Ursachen fürÄnderungen:

Beseitigung von Fehlern (korrektive Wartung)Verbesserung nicht funktionaler Eigenschaften (perfektive Wartung)Erweiterung der Funktionalität wegen sich ändernder

Rahmenbedingungen (adaptive Wartung)Erweiterung der Funktionalität wegen Erkenntnisgewinn während der

Entwicklung

Prinzip Annahme der Änderungsnotwendigkeit

43

unklareAnforderungen

Software1.Version

geklärteAnforderungenan die Software

Software2. Version

weiter geklärteAnforderungenan die Software

Software-Prozeß

. . .

Software-Prozeß ist kein typischer Fertigungsprozeß !

Software-Prozeß

Prinzip Annahme der ÄnderungsnotwendigkeitPrinzip Annahme der Änderungsnotwendigkeit

44

Aktivitäten der Software-Entwicklung

In der Software-Erstellung gibt es eine Vielzahl von Aktivitäten, zuden wichtigsten gehören:

AnforderungsanalyseSpezifikationEntwurfProgrammierungTestenInbetriebnahme

A software engineer must of course be agood programmer, be well-versed indata structures and algorithms, and befluent in one or more programminglanguages. ... The software engineermust be familiar with several designapproaches, be able to translate vaguerequirements and desires into precisespecifications, and be able to conversewith the user of a system in terms ofthe application rather than in‚computerese‘.Ghezzi,Jazayeri,Mandrioli 1991, vgl.Literaturliste

Page 11: Java

45

Programmierung

Programmierung:Verwendung einer Programmiersprache, um Anforderungen,Spezifikationen, Entwürfe in maschinenausführbare Form zuformulieren.Um genau zu sein: um eine Form zu erreichen, dieautomatisch in eine maschinenausführbare Form übersetztwerden kann.

46

Objektorientierte Software-Erstellung

• Drei Aktivitäten auf der Grundlage der gleichenGrundkonstrukte:– Objektorientierte Analyse (OOA)– Objektorientiertes Design (OOD)– Objektorientierte Programmierung (OOP)

• Analyse / Design wird durch objektorientierteModellierungssprachen unterstützt– OMT (Object Modeling Technique)– UML (Unified Modeling Language)

=> siehe http://www.rational.com

• Programmierung mit objektorientierter Programmiersprache– Smalltalk, C++, Objective C, Java, Classic Ada, Delphi, Eiffel, Beta

• hohes Wiederverwendungspotential

47

Kapitel 3

Objektorientierte Analyse und Designvgl separate pdf-Datei

Kapitel 4

Grundbegriffe zu Programmiersprachen

Page 12: Java

49

Programmiersprache

Die Syntax einer Programmiersprache legt fest, welchen AufbauProgramme haben.

Lexikalische Ebene: wie werden aus Zeichen Wörtergebildet?

Syntaktische Ebene: wie werden aus Wörtern Sätzegebildet?

Die Syntax wird durch eine Grammatik festgelegt.

50

Programmiersprache

Eine Grammatik ist gegeben durch ein Viertupel (S, T, N, P) mit:S ist ein Startsymbol

T ist eine Menge von TerminalsymbolenN ist eine Menge von NichtterminalsymbolenP ist eine Menge von Produktionen / Ableitungsregeln

51

Programmiersprache

Terminalsymbole beschreiben Symbole, die in den Sätzen derSprache vorkommen.

Nicht-Terminalsymbole kommen nicht in den Sätzen der Sprachevor. Sie werden gebraucht, um die Anwendung derAbleitungsregeln zu koordinieren.

Das Startsymbol ist ein ausgezeichnete Nicht-Terminalsymbol.Es legt fest, mit welcher Ableitungsregel begonnen wird, um zueinem syntaktisch korrekten Satz der Sprache zu kommen.

Die Ableitungsregeln legen fest, wie eine Sequenz von Nicht-Terminal- und Terminalsymbolen durch eine Folge andererTerminalsymbole und Nicht-Terminalsymbole ersetzt werdenkann.

52

Programmiersprache

Beispiel einer Produktion:einfacher-deutscher-Satz = Subjekt Prädikat Objekt {adverbiale-Bestimmung}Subjekt = Nomen | PersonalpronomenPersonalpronomen = Ich | Du | ...

{} steht für 0 bis n-fache Formulierung[] steht für Optionalität (0 oder einfaches Vorkommen)| trennt Varianten voneinanderfett: Terminalsymbole,kursiv: Nicht-Terminalsymbole

Page 13: Java

53

ProgrammierspracheWie ändert sich die Grammatik, wenn immer mindestens eine adverbiale

Bestimmung vorkommen muß?

Wie ändert sich die Grammatik, wenn ich zwischen adverbialen Bestimmungendes Ortes, der Zeit und der Art unterscheiden möchte?

54

Beispiel einer Produktion:ClassDeclaration = {ClassModifier} class Identifier [extends SuperClass][implements Interfaces] {FieldDeclarations}

Beispiel einer Grammatik:

Grammatik völlig-simpel = ( START, {(,),+,1,leer }, {S,START},{START = S | leer ,

S = S+S | 1 | (S)} )Prüfung, ob der Satz (1+1) +1 in der Sprache völlig-simpel gültig ist:

START -> S -> S+S

Programmiersprache

(S) -> S+S1

1 1

55

ProgrammierspracheWelche Sprache wird durch die folgende Grammatik erzeugt?

Grammatik unklar = ( S, {a,b,c}, {S,A,B},{S = abc,

S = aAbc,Ab = bA,Ac = Bbcc,bB = Bb,aB = aaA,aB = aa} )

56

Programmiersprache

L(G) = {anbncn | n ≥ 1}, wobei L(G) die Menge der Sätze bezeichnet, die sichgemäß der Grammatik G erzeugen lassen.

Page 14: Java

57

ProgrammierspracheBeweis von L(G) = {anbncn | n ≥ 1}:

Induktionsanfang:Jede Ableitung beginnt mit der Anwendung der ersten oder zweiten Ableitung.

Die erste liefert direkt abc (gehört zur Sprache).

58

S = abc, S = aAbc, Ab = bA, Ac = Bbcc, bB = Bb, aB = aaA, aB = aa

Induktionsschritt:Nun betrachten wir den Satz: D = aiAbici mit i ≥ 1.Annahme: Von diesem Satz aus erreichen wir nur Sätze in der

angenommenen Sprache.Beweis: Erst mal muß i-mal die Ableitung Ab = bA angewendet werden,

denn nur so wandert das A nach rechts.

Ergebnis: aibiAci

Danach kann nur die Ableitung Ac = Bbcc angewendet werden.

Ergebnis: aibiBbccci-1 = aibiBbc i+1

Danach kann nur noch i-mal bB = Bb angewendet werden.

Ergebnis: aiBbi+1ci+1

Aus diesem Satz ergibt sich nun entweder:

ai+1bi+1ci+1 (gemäß aB = aa)

oder ai+1Abi+1ci+1 (gemäß aB = aaA)

59

ProgrammierspracheFazit:

Also enthält L(G) genau die betrachteten Wörter (genau deshalb, weil es imInduktionsschritt keine weiteren Möglichkeiten der Anwendung vonAbleitungen gab!)

Bemerkung: Die betrachtete Sprache ist eine der typischen kontextsensitivenSprachen!

Um zu verstehen, daß der Kontext nötig ist, möge man versuchen die gleicheSprache mit einer kontextfreien Grammatik zu erzeugen.

60

Programmiersprache

Wenn auf der linken Seite aller Produktionen nur jeweils einNicht-Terminalsymbol steht, dann heißt die Grammatikkontextfrei.

Das bedeutet: die Ersetzung eines Nicht-Terminalsymbolen hängtnicht davon ab, in welchem Kontext das Nicht-Terminalsymbolen vorkommt.

Java-Grammatik: www1.arcs.ac.at/users/mt/java/java-syntax.html#Number

Page 15: Java

61

Syntax-Beispiele Java

ClassDeclaration ={ClassModifier}class Identifier[extends SuperClass][implements Interfaces]{ FieldDeclarations }

FieldDeclarations ={FieldDeclaration}

FieldDeclaration =[DocComment] MethodDeclaration[DocComment] abstract

InterfaceMethodDeclaration[DocComment] native

NativeMethodDeclaration[DocComment]

ConstructorDeclaration[DocComment] VarDeclarationStaticInitializer ;

62

Syntax-Beispiele Java

MethodDeclaration ={MethodModifier}ResultType Declarator ( [

ParameterList ] )[ throws Exceptions ]Block

MethodModifier =public | protected | privatestaticfinal | synchronized

ConstructorDeclaration =ConstructorModifierClassName ( [ ParameterList ] )[ throws Exceptions ]ConstructorBody

63

Programmiersprache

Die Semantik einer Programmiersprache legt fest, was diesyntaktisch korrekten Sätze der Sprache bedeuten.

Die Semantik kann durch die Abbildung auf ein mathematischesModell definiert werden (zum Beispiel auf Aussagen- oderPrädikatenlogik).

Üblicherweise wird die Semantik einer Programmiersprachejedoch operational festgelegt. Das heißt, die Bedeutung einesSatzes wird durch das Verhalten des Programms (das diesemSatz entspricht) auf einer Referenzmaschine definiert.

64

Übersicht über die Entwicklung vonProgrammiersprachen

Maschinensprache001001

AssemblerBspe: RS600-Assembler

Konstrukte: MV, ADD, GET)

Imperative / Prozedurale SprachenBspe: Fortran, Cobol, Algol, PL1, Ada, C

Prozeduren, while, case, if

Logische SprachenBsp: Prolog

Konstrukte: Fakten, Regeln

Objektorientierte SprachenBspe: C++, Smalltalk, Eiffel, Java

Funktionale SprachenBspe: LISP, ML, MirandaKonstrukte: Funktionen

Vorgängerbeziehung

Zeit

Page 16: Java

Kapitel 5

Java als objektorientierte Programmiersprache

66

Charakterisierung / Vergleich

• Java ist aus einem Projekt entstanden, Software fürelektronische Geräte zu entwickeln

• Daraus entstanden Anforderungen, die von Sun formuliertwurden

• Sun wirbt heute damit, dass Java diese Anforderungen erfüllt• Werbung und Wirklichkeit sind jedoch nicht deckungsgleich

=> Charakterisierungen von Java sind diskussionsbedürftig

67

Einfach

• Sun: Java ist einfach– Design nahe an C++, um Umstieg zu erleichtern– Selten benutzte und schwer verständliche Eigenschaften aus C++

wurden beseitigt• Überladen von Operatoren

• Mehrfachvererbung

– Garbagecollection vereinfacht Umgang mit Objekten, Programmierermuß Speicher nicht selbst freigeben

• Diskussion– Mehrfachvererbung ist sicher überflüssig– Überladen von Operatoren kann Lesbarkeit von Programmen erhöhen– Java ist sehr mächtig, daher nicht schnell zu erlernen– Es ist einfach, verständlich zu programmieren

68

Objektorientiert

• Sun: Java ist objektorientiert– Objektorientierte Funktionalität realisiert– Beste Konzepte der Sprachen C++, Objective C, Eiffel und Smalltalk

• Diskussion– Ausgereifte Realisierung objektorientierte Eigenschaften ist eine Stärke

von Java

Page 17: Java

69

Verteilt

• Sun: Java ermöglicht verteilte Programmierung– Standardprotokolle, wie TCP/IP, HTTP und FTP werden angeboten– Zugriff auf Dateien über URL's genauso einfach, wie Zugriff auf lokale

Dateien

• Diskussion– Plattformspezifische Unterschiede zwischen Unix und Windows bereiten

jedoch Schwierigkeiten– Diese sind jedoch lösbar

70

Robust

• Sun: Java ist ideal für robuste Programmierung– Java ist streng getypt, im Gegensatz zu C++– Java hat kein Zeigermodell

=> keine Integer-Zeiger-Konvertierung– Garbagecollection

• Diskussion– Oben aufgeführte Schwachstellen in C++ sind in Java beseitigt

aber:– Klassenbibliotheken sind oft unausgereift

71

Sicher

• Sun: Java legt viel Wert auf Unterstützung sichererNetzwerkprogrammierung– Authentifizierungsalgorithmen basierend auf asymmetrischer

Kryptographie– Pointer-Semantik kann nicht manipuliert werden– Applets können durch Signierung Rechte erhalten

• Diskussion– Die amerikanische Exportpolitik verhindert leider den direkten Export

starker Verschlüsselungssoftware– Sicherheit eines Bytecode Verifyers nicht formal bewiesen, erfolgreiche

Einbrüche jedoch nicht bekannt

72

Architekturneutral / Portabel

• Sun: Java ermöglicht plattformunabhängige Software-Entwicklung– Bytecode kann überall interpretiert werden– AWT wird auf alle Plattformen abgebildet– Sprache plattformunabhängig definiert, z.B. ist "int " immer 32 Bit lang,

unabhängig von der Architektur

• Diskussion– Leider sind API-Fehler plattformabhängig

=> "Write once test everywhere" :-)– Portierung ist jedoch immer noch einfacher, als mit vielen anderen

Sprachen

Page 18: Java

73

Dynamisch

• Sun: Java ermöglicht dynamische Programmierung– Bibliotheken können im laufenden System ausgetauscht und aktualisiert

werden– Keine Neucompilierung nötig

74

Von C/C++ nicht übernommene Eigenschaften

• Kein Präprozessor– kein #define , #include oder typedef

=> Programmtext ist einfacher zu lesen

• Keine Structures und Unions– Klassen erfüllen gleichen Zweck

• Keine Funktionen– Reiner objektorientierter Ansatz– Es gibt aber Klassenmethoden, die ähnliche Funktionalität bieten

• Keine Mehrfachvererbung von Klassen– Mehrfachvererbung in Interfaces jedoch möglich

75

Von C/C++ nicht übernommene Eigenschaften

• Kein goto -Befehl– In strukturierter Programmierung nicht nötig– Multilevel-break und Multilevel-continue kann goto ersetzen

• Kein Überladen von Operatoren• Keine automatische Typwandlung mit Informationsverlust

– Expliziter Cast nötig

• Keine Zeiger– Arrrays und Strings sind Objekte– Objekte werden referenziert

76

Zusammenfassende Diskussion

• Es ist Sun gelungen, den Bereich der Entwicklung verteilterSoftware-Systeme mit Java zu besetzen

• Sun hat bei dem Vorhaben eine breite Industrieunterstützung• Entwicklungen von komplexen Software-Paketen kommt

aufgrund von Performance- und Stabilitätsproblemen etwaslangsamer voran

Page 19: Java

77

Die Java Welt

Java ist mehr als eine Programmiersprache ...

• objektorientierte Programmierung• plattformunabhängige Programme• Klassenbibliothek und Programmier-Schnittstellen

(Application Programming Interface API)• Entwicklung und Vertrieb durch Sun Microsystems

– Java Development Kit (JDK)/Software Development Kit (SDK)frei verfügbar

Überblick zu Java

78

Die Java Welt

• Entwicklung von Internet-Anwendungen• Entwicklung von verteilten Anwendungen• Java Applets

– integriert in WWW-Seiten– verbreitet über das Internet

• Java Applikationen– entworfen, um als separate Prozesse in einer Laufzeit-Umgebung auf

beliebiger Plattform zu laufen– kann auch über das Internet vertrieben werden

Überblick zu Java

79

Übersetzen des Programmtexts

• Aus Java-Programmtext erzeugt der Java-Compiler eine Java-Bytecode-Datei

• Auf dem Zielrechner interpretiert die Java Virtual Machine JVMdiesen Bytecode und führt das Programm aus– Geschwindigkeitsprobleme

Überblick zu Java

80

Vorteil: Plattformunabhängigkeit

• Compilierte Java Programme (d.h. Bytecode) laufen auf jederJVM-fähigen Plattform

Überblick zu Java

Page 20: Java

81

Bytecode / Class-Files

• Java wird vom Java Compiler zu einer fest definiertenZielsprache übersetzt

• Die Zielsprache ist der Bytecode– sie ist maschinenähnlich, hat z.B. Register– kann einfach interpretiert bzw. in Maschinencode anderer Plattformen

übersetzt werden

• Jede Java-Klasse wird separat übersetzt und– in separater Datei, dem Class-File gespeichert.– Das Format der Dateien wird Bytecode genannt.– Auch andere Sprachen lassen sich nach Bytecode übersetzen.

82

JDK / JRE• Java Development Kit (JDK)/Software Development Kit (SDK)

ist eine– kostenlose Software-Entwicklungsumgebung der Firma JavaSoft, um

Java-Programme zu entwickeln– Alle Entwicklungen sind mit JDK/SDK alleine möglich, kommerzielle

Tools können jedoch Entwicklung unterstützen:• Visual Age (IBM)• JBuilder (Inprise, Borland)• Visual J++ (Microsoft)• Java Workshop / Studio (Sun)

– Darf nicht ohne Lizenzgebühren weiterverkauft werden

• Java Runtime Environment (JRE) ist eine– Untermenge des JDK/SDK, die benötigt wird, um Java-Applikationen

laufen zu lassen– Darf ohne Lizenzgebühren eigenen Produkten beigefügt werden

83

Virtual Machine / JIT-Compiler

• Virtual Machine ist der Teil des JRE, der benötigt wird, umBytecode zu interpretieren

• Classfiles werden nur bei Bedarf geladen und– entweder interpretiert– oder vor Verwendung "just in time" in die Maschinensprache der

Zielplattform übersetzt

• JIT-Compiler (Just-In-Time-Compiler) ist ein Compiler, derKlassen nur bei Bedarf zur Ausführungszeit übersetzt– Es gibt in der Regel Geschwindigkeitsvorteile im Vergleich zur

Interpretation

84

Java Virtual Machine (JVM)

• Bestandteile:– Byte Code Loader– Byte Code Verifier– Byte Code Interpreter

Überblick zu Java

Page 21: Java

85

Java Applikationen vs. Java Applets

• Java Applets– laufen innerhalb der JVM eines Webbrowsers– haben eigene, festgelegte Zeichenfläche im Webbrowser

• Java Applikationen– eigenständige Applikationen– laufen innerhalb der JVM– werden auf der Befehlszeilenebene oder als Windows-Applikation

gestartet

• Programmieren in Java für beide identisch

Überblick zu Java

86

Zusammenfassung

• Applets / Applikationen

• Java Development Kit (JDK)/Software Development Kit (SDK)• Compiler

• Java Runtime Environment (JRE)• Java Virtual Machine (JVM)• Interpreter, Just-in-time-Compiler (JIT)• Bytecode, Class-Files

• Webbrowser• Plattformunabhängigkeit

Überblick zu Java

Kapitel 6

Ein erstes Java-Beispiel

88

Klassen: Gleichartige Objekte Klassen in Java

public class Girokonto {

private int kontostand; // in Pfennigen gerechnet

public Girokonto() {

kontostand = 0;

}

/* Einzahlen und Abheben */

public void zahle ( int pfennige){

kontostand = kontostand + pfennige;

}

public int holeKontostand() {

return (kontostand);

}

}

Modifier class Klassenname {

Attribut-Deklarationen

Methoden

}

// Kommentar

/* Kommentar */

Page 22: Java

89

Von Klassen zu Objekten

• Exemplare aus einer Klassen-Schablone:

– ErzeugenGirokonto einKonto= new Girokonto();

– Löschen: wenn nirgendwo mehr benutzt (automatische Garbage-Collection)

– Zustand eines Objekts verändern (→ Attribute)Nachrichten an ein Objekt senden (→ Methoden)

Klassen in Java

Klasse ObjName =

new Klasse(Typ1 name1, ...)

Girokonto

Kontostand (in Pfennigen)

•Ein-/Auszahlen•Kontostand abfragen

Objekt

Objekt

Objekt

Objekt

90

Attribute Klassen in Java

• Teile des Gesamtzustands eines Objekts

private int kontostand;private Girokonto meinKonto;

• Verändern von Attributenkontostand = kontostand + pfennige;

• Einkapseln von Attributen (→ Ziel: möglichst alle Attribute einkapseln)– privat d.h. nur innerhalb des Objekts sichtbar (private)

– öffentlich d.h. auch außerhalb des Objekts sichtbar (public)

Modifier Datentyp attributname

91

Methoden (1/2) Klassen in Java

• Teile des möglichen Verhaltens eines Objekts(d.h. Nachrichten, die vom Objekt verarbeitet werden können)

public void zahle ( int pfennige){

kontostand = kontostand + pfennige;

}

public int holeKontostand() {

return (kontostand);

}

Modifier Rückgabetyp Methodenname (Typ1 ParamName1,Typ2 Param...){

Liste von Anweisungen;

[ return (Rückgabewert) ]

}

Spezieller Rückgabewert: void

92

Methoden (2/2) Klassen in Java

• Aufruf von Methoden eines Objektes (Punkt-Notation,qualifizierter Zugriff)

konto.holeKontostand();

konto.zahle(+100);

• Übergeben von Parametern– statt komplette Objekte zu übergeben, nur Zeiger darauf („by reference“)– bei einfachen Datentypen als Wert kopiert („by value“)

• Einkapseln von Methoden– privat, d.h. nur als interne Hilfs-Methode zugreifbar (private)

– öffentlich, d.h. extern sichtbar (public)

Page 23: Java

93

• Einsprungpunkt bei "Ausführen" einer Applikation– Übergeben von Argumenten aus der Kommandozeile möglich– für Testen von Klassen-Implementierungen geeignet

public class TestGirokonto {

...

public static void main(String[] args) {

... // Hier Code zum Testen einfügen

}

...

}

Spezielle Methode "main" Klassen in Java

94

Hilfsklasse „Bildschirm“

• Benutzereingaben und Bildschirmausgaben später detaillierter,im Augenblick genügt Anwendersicht: "Welche Methoden gibt es?"

– komfortable Ausgabe auf den BildschirmBildschirm.gibAus (text)

– komfortable Eingabe eines Textes von Tastatureingabetext = Bildschirm.gibEin()

– Warten auf TastendruckBildschirm.warteAufTastendruck()

95

Motivation• Klasse erweitern um Attribute, Methoden• Erzeugen von Objekten und Nachrichtenaustausch (Methoden) zwischen Objekten

Aufgaben• Ergänzen Sie die Klasse "Girokonto":

– zum Sperren eines Kontos: boolesches Attribut istGesperrt mit denMethoden void sperre(), void entsperre() und boolean istGesperrt()

– zum Überschreiben des aktuellen Kontostandes mit einem übergebenen Betragdie Methode setzeKontostand()

• Testen der Klasse "Girokonto" (siehe: Methode "main" in der Klasse "TestGirokonto" )

– Erzeugen eines Girokonto-Objekts– Nacheinander Einzahlen von 100 Pfennigen, Abheben von 20 Pfennigen und

Einzahlen von 30 Pfennigen– Anschließend Kontostand ausgeben

Übung: Attribute und Methoden

96

Übung: Attribute und Methoden

Lösung 1:public class Girokonto {

...

private boolean istGesperrt;...

public void sperre() {

istGesperrt=true;

}

public void entsperre(){

istGesperrt=false;

}

public boolean istGesperrt (){

return (istGesperrt);

}...

}

Page 24: Java

97

Übung: Attribute und Methoden

Lösung 2:public class TestGirokonto {

public static void main(String[] args) {

// erzeuge neues Konto

Girokonto konto = new Girokonto();

// führe Transaktionen durch

konto.zahle(+100);

konto.zahle(+30);

konto.zahle(-20);

// gib Kontostand aus

int aktuellerStand = konto.holeKontostand();

Bildschirm.gibAus(aktuellerStand);

}

}

Klasse „Bildschirm“

Einsprung von der Kommando-zeile [optional für jede Klasse]

98

Zusammenfassung

• Programm = Mehrere Objekte, die Nachrichten austauschen

• Klassen: Schablonen für Objekte– Attribute, Methoden

• Objekte– Erzeugen

• Nachrichtenaustausch– Aufruf von Methoden eines Objektes (Punkt-Notation)

z.B. konto.holeKontostand()

Kapitel 7

Java-Syntaxkonstrukte7.1 Primitive Datentypen, Literale und Variablen7.2 Aufruf von Objekten, einfacher Nachrichtenaustausch7.3 Operatoren, Ausdrücke, Zuweisungen7.4 Anweisungen

Kapitel 7.1

Primitive Datentypen, Literale und Variablen

Page 25: Java

101

Primitive Datentypen

Ganze Zahlen:byte , short , int , long

Fließkommazahlen:float , double

Andere Typen:char , boolean

Keine primitiven Datentypen:String , Arrays (auch von einfachen Typen), Klassen allgemein

102

Primitive Datentypen: ganze Zahlen

• 2er Komplement Datentypen• vorzeichenbehaftet• feste Größe, unabhängig von Maschinenwortgröße

• Vergleich C/C++: (short : 16 Bit, long : 32 Bitint : Maschinenwortlänge)

Typ Größe Wertebereich

byte 8 Bit (1 Byte) -27 ... 0 ... (27-1)

short 16 Bit (2 Byte) -215 ... 0 ... (215-1)

int 32 Bit (4 Byte) -231 ... 0 ... (231-1)

long 64 Bit (8 Byte) -263 ... 0 ... (263-1)

103

2er Komplement (Hier 8 Bit)

• Höherwertige Bitsstehen links

• HöchstwertigesBit istVorzeichenbit

Bit Nummer7 6 5 4 3 2 1 0

Dezimalwert

0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 1 10 0 0 0 0 0 1 0 20 0 0 0 0 0 1 1 30 0 0 0 0 1 0 0 40 1 1 1 1 1 1 1 1271 0 0 0 0 0 0 0 -1281 0 0 0 0 0 0 1 -1271 1 1 1 1 1 1 0 -21 1 1 1 1 1 1 1 -1

Vorzeichenbit

104

Primitive Datentypen: Fließkommazahlen

• Fließkommazahlen nach IEEE 745• Mantisse und Exponent definiert Wert• Unendlich ist ein definierter Wert

(POSITIVE_INFINITY und NEGATIVE_INFINITY )• NaN (Not a number) ist ein definierter Wert

Typ Größe Wertebereich Genauigkeit

float 32 Bit (4 Byte) +/- 3.4*1038 ca. 7 Dezimalst.

double 64 Bit (8 Byte) +/- 1.8*10308 ca. 15.5 Dezimalst.

Page 26: Java

105

IEEE 745 Standard

Fließkommazahlen nach IEEE 745 setzen sich zusammen aus:• Sign-Bit S (1 Bit)• Exponent E (8 Bit für float und 11 Bit für double )• Mantisse M (23 Bit für float und 52 Bit für double )

Sind in E alle Bits gefüllt, ist dies ein reservierter Zustandum Unendlich und NaN darstellen zu können

106

Primitive Datentypen: boolean

• boolean kennt nur zwei Werte, true und false

• Sämtliche boolsche Logik in Java wird mit dem Datentypboolean realisiert. Mißbrauch von Integertypen für boolscheAusdrücke, wie in C und C++ üblich, ist in Java nichtvorgesehen.

• boolean benötigt 1 Byte (=8 Bit) Speicher. Dies liegt nicht ander Java-Sprachsyntax, sondern am Mapping auf die VirtualMachine, die keine 1-Bit-Datentypen kennt.

107

Primitive Datentypen: Zeichen

• char ist ein 16-Bit-Zeichen nach dem Unicode-Standard

• Untere 7 Bit (128 Zeichen) von Unicode sind ASCII-kompatibel(bzgl. ASCII nach ANSI X3.4)

• Sonstige Bits werden benötigt um internationale Zeichensätzeabbilden zu können.

• Verantwortlich ist das Unicode Consortium(http://www.unicode.org)

108

Klasse String

• Zeichenketten werden durch Objekte der Klasse Stringdargestellt

• allgemeine Objekte und Klassen werden später gründlicheruntersucht

• String ist jedoch besondere Klasse, da Literale (konstanteZeichenketten) und Operatoren (+ zur Konkatenation) definiertsind

• Anders als in C/C++ sind Strings keine Zeiger auf char bzw.Array von char , in Java gibt es keine Zeiger und Arrays sindgesonderte Konstruktionen, die nichts mit der Klasse Stringzu tun haben

Page 27: Java

109

Anwendungsbereich Java-Datentyp Beispiel

• Logik boolean true und false

• Buchstaben char z.B. ´a´,´b´,´c ´ ...

• Ganze Zahlen byte ( 8 Bit) z.B. -13 , -1 , 0,1short (16 Bit)

int (32 Bit)

long (64 Bit)

• Fließkomma float (32 Bit) z.B. -3.3e-22f ,double (64 Bit) z.B. 3.4E32

Primitive Datentypen in Java

110

Literale

• Literale sind konstante Zahlen, Zeichen bzw. Zeichenketten,die zur Initialisierung von Datentypen verwendet werden

• Jedes Literal hat einen eindeutigen Typ, bei Zuweisungen mußauf Typkonsistenz geachtet werden.

• Literale existieren für die einfachen Datentypenint , long , float , double , char und booleansowie für die Klasse String .

111

Literale: Wahrheitswerte

• Für den primitiven Datentyp boolean gibt es die Literaletrue und false .

112

Literale: ganze Zahlen

• Ganze Zahlen lassen sich einfach durch den Dezimalwertdarstellen (z.B. 0, 20 , 4332 , etc.)

• Ein Vorzeichen kann der Zahl vorangestellt werden(z. B. -323, +4238 )

• Durch vorangestelltes "0x " lassen sich Zahlen durch ihreHexadezimalwerte definieren. Die Buchstaben A bis F könnenhier sowohl klein, als auch groß geschrieben werden (z. B.0x3AF , 0xfff178 )

• Durch eine vorangestelle Null "0" werden Zahlen imOktalsystem definiert (z. B. 04123 , 01114 )

Page 28: Java

113

Literale: ganze Zahlen

• Standardmäßig sind Ganzzahlkonstanten vom Typ int ,long -Konstanten werden durch ein Anfügen des BuchstabensL bzw. l erzeugt (z. B. 0L , 100000000000L )Achtung: l ist leicht mit 1 zu verwechseln, daher sollte Lbenutzt werden

• Für die Datentypen byte und short existieren keine eigenenLiterale, es dürfen int -Literale verwendet werden, sofern derWert klein genug ist

114

Literale: Fließkommazahlen

• Fließkommazahlen bestehen aus einer Mantisse und einemoptionalen Exponenten (zur Basis 10).

• Der Exponent wird durch ein "E" bzw. "e" von der Mantissegetrennt. (10E3 entspricht z. B. dem Wert von 1000)

• Sowohl Mantisse als auch Exponent könnenvorzeichenbehaftet sein (z. B. -10E8 , +3e-4 )

• Die Mantisse darf auch als Dezimalbruchdarstellunggeschrieben werden (z. B. -5.334E+27 )

115

Literale: Fließkommazahlen

• float -Typen lassen sich durch ein angefügtes f bzw. Fdefinieren. (z. B. 7f , 3.8F )

• double -Typen lassen sich durch ein angefügtes d bzw. Ddefinieren. (z. B. 121D, 1.4E7d )

• Fließkommazahlen lassen sich als solche von ganzen Zahlenunterscheiden, wenn eine der folgenden Eigenschaften erfülltist:a) Es existiert ein Exponent (z.B. 1E3)b) Die Mantisse enthält den Dezimalpunkt (z. B. 3.0 )c) f , F, d oder D beendet das Literal

• Ist ein Fließkommaliteral nicht durch f bzw. F spezifiziert, hates den Typ double

116

Literale: Zeichen

• Zeichen (char -Literale) werden durch einfacheAnführungsstriche definiert. (z. B. 'a' , '#' , '=' )

• Für Sonderzeichen gibt es Escape-Sequenzen, die durcheinen Backslash "\ " eingeleitet werden. (z. B. '\n' )

• Hierbei bedeutet:'\b' : backspace BS (Zeichen zurück) (ASCII: 8)'\t' : horizontal tab HT (horizontaler Tabulator) (ASCII: 9)'\n' : line feed LF (Zeilenvorschub) (ASCII: 10)'\f' : form feed FF (Seitenvorschub) (ASCII: 12)'\r' : carriage return CR (Wagenrücklauf) (ASCII: 13)'\”' : double quote (doppeltes Anführungszeichen)'\'' : single quote (einfaches Anführungszeichen)'\\' : backslash (Rückwärts-Schrägstrich)

Page 29: Java

117

Literale: Zeichen

• In einer Escape-Sequenz kann auch direkt der ASCII-Wert alsOktalzahl angegeben werden (z. B. '\17' , oder '\3' )

• Durch '\uxxxx' wird der Wert als Unicode-Sequenzangegeben, wobei für jedes x eine Hexadezimalzifferangegeben werden muß. (z. B. '\0022' entspricht '\"' )

• Achtung: die Unicode-Escape-Sequenzen werden in einersehr frühen Phase des Compilers ausgewertet.Ein Zeilenvorschub als Unicode-Escape-Sequenz wird dahergenauso behandelt wie eine neue Zeile im Editor.

118

String-Literale

• Strings sind Verkettungen von Zeichen.• String -Literale werden durch doppelte Anführungszeichen

gekennzeichnet• Alle Zeichen lassen sich analog den char -Literalen

konstruieren.• Beispiele für String -Literale:

"Begrenzung durch Anführungszeichen""Das ist ein Text\nmit Zeilenvorschub"

119

Variablen

• Variablen dienen dazu, Werte von speziellen Datentypen zuspeichern und zu verarbeiten, die gespeicherten Werte könnenwährend der Ausführung eines Programms geändert werden;sie sind halt variabel.

• Die Werte, die eine Variable annehmen kann, sind durch ihrenTyp festgelegt.

• Als erster Schritt muß eine Variable dem Compiler bekanntgemacht werden, diesen Vorgang nennt man Deklaration

• Dann muß ein Anfangswert (initialer Wert) zugewiesen, diesenVorgang nennt man Initialisierung

• Verkürzend können beide Aktionen auch in einer Zeile erledigtwerden.

120

Variablen

• Ohne Deklaration kann keine Variable initialisiert werden• Ohne Initialisierung kann keine Variable weiterverarbeitet

werden (z. B. in Ausdrücken)

Page 30: Java

121

• Speicherung von Werten– Variablenname und Datentyp– bei Initialisierungen müssen beide Seiten zuweisungskompatibel sein

...

int kontostand;

oder:int kontostand = 0;

...

kontostand = kontostand + pfBetrag;

Variablen

Deklaration [mit Initialisierung]Datentyp Variablenname [= Wert]

122

Variablennamen

• Variablennamen (sowie alle Bezeichner in Java) sind case-sensitive , also man unterscheidet zwischen Groß- undKleinschreibung

• Variablennamen beginnen stets mit Buchstaben (JavaLetter),dann können Buchstaben oder Zahlen folgen.Der Unterstrich "_" gehört aus historischen Gründen auch zuden Buchstaben, kommt aber in der offiziellenNamenskonvention nicht vor, sollte daher nicht verwendetwerden.

123

Deklaration

• Variablen werden durch den Typ gefolgt von demVariablennamen deklariert

• Mehrere Variablennamen können durch Kommata getrenntaufgeführt werden, sie sind dann vom gleichen Typ

• Deklarationen sind Anweisungen, die mit Semikolonabgeschlossen werden

Beispiel:int anzahlPersonen;

long millisekundenSeitGeburt;

float größeInCm, gewichtInKg;

String name, wohnort;

124

Initialisierung

• Initialisierungen werden mit Hilfe des Gleich-Operatorsrealisiert, der rechte Wert wird dem linken zugewiesen.

• Initialisierungen sind Ausdrücke, die mit einem Semikolonabgeschlossen werden

• Bei Initialisierungen müssen beide Seiten den gleichen Typhaben

Beispiel:anzahlPersonen = 20;

milliSekundenSeitGeburt = 568000000000L;

größeInCm = 185F;

name = "Hans Mustermann";

Page 31: Java

125

Type Casting

• Datentypen byte und short haben keine eigenen Literale• Es muß das Literal von int genommen werden und der Wert

nach byte bzw. short gewandelt werden (casting)

• Dies geschieht durch vorangestellte runde Klammern (Cast-Operator)

Beispiel:byte alterInJahren;

alterInJahren = (byte)18;

126

Deklaration / Initialisierung in einer Zeile

• Deklarationen und Initialisierungen können in einer Zeileerfolgen

• Auch hier lassen sich mehrere Deklarationen vom gleichen Typdurch Kommata voneinander trennen

Beispiel:float größeInCm = 185, gewichtInKg = 79;

String name="Hans Mustermann";

127

Zusammenfassung

• primitive Datentypen– boolean, char, byte, short, int, long, float, double

• Literale– Wahrheitswerte, ganze Zahlen, Fließkommazahlen, Zeichen, String-Literale

• Variablen– Namen

– Deklaration– Initialisierung

Kapitel 7.2

Aufruf von Objekten, einfacher Nachrichtenaustausch

Page 32: Java

129

Aufruf von Objekten

• Konstruktoren: Aktivitäten bei Objekterzeugung• Referenzen als Verweise auf Objekte• Garbage Collection• Übergabe von Parametern an Methoden• Klassenattribute / Klassenmethoden• Namensraum

– Überladen von Methoden– Überdecken von Attributen

• Vertiefung OO-Programm = Mehrere Objekte + Nachrichtenaustausch– Aufgaben verteilen („Spezialisten“)

130

Konstruktor

• Methode, die automatisch bei Erzeugung eines Objektesaufgerufen wird

• Wird in der Regel benutzt, um Attribute zu initialisieren• Dadurch charakterisiert, daß der Methodenname mit dem

Klassennamen übereinstimmt• Konstruktoren besitzen keinen Rückgabewert (auch nicht

void )

• Überladen von Konstruktoren ist möglich

131

Konstruktoren Aufruf von Objekten

• Methoden für das Durchführen von Arbeiten direkt bei der Objekt-Erzeugung:– Methodenname = Klassenname– Folge von Anweisungen, die abzuarbeiten sind– kein Rückgabewert

class Girokonto {...public Girokonto() {

kontostand = 0;

...

}

}

132

Konstruktor

• Argumente der Konstruktormethode werden beiObjekterzeugung durchnew Klassenname ( Argument1 , Argument2 , ...)an den Konstruktor übergeben

• Ohne Angabe eines Konstruktors ist nur der leere Konstruktorohne Argumente definiert

• Ist ein (nicht leerer) Konstruktor definiert, muß der leereKonstruktor explizit definiert werden, um noch benutzt werdenzu dürfen

Page 33: Java

133

Referenzen auf Objekte

• Bei primitiven Datentypen enthält eine Variable direkt denInhalt (z. B. einen Int-Zahlenwert)

• Bei Objekten von Klassen symbolisiert die Variable nur eineReferenz (einen Verweis) auf das Objekt

• Es können auch mehrere Referenzen auf ein Objekt zeigen• Ein Referenz kann auch leer sein, null ist das Schlüsselwort

für die leere Referenz

Beispiel:Girokont o k = null;

134

Referenzen auf Objekte

• Mit dem ==-Operator kann man zwei Referenzen aufGleichheit testen:

Beispiel:Girokonto k1 = new Girokonto();

...

Girokonto k2 = k1;

...

if (k1 == k2)

System.out.println( ”k1 und k2 verweisen aufdasselbe Objekt");

135

Referenzen auf Objekte

• Mit dem ==-Operator kann man ebenso abfragen, ob eineReferenz leer ist:

Beispiel:Girokonto k;

...

if (k == null)

System.out.println(”k ist leere Referenz");

136

Garbage Collection

• Ist die letzte Referenz auf ein Objekt verschwunden da– die Referenzen den Gültigkeitsbereich verlassen haben, oder da– null -Referenzen zugeweisen wurden

wird das Objekt der Garbage Collection zugeführt=> es sind keine free - oder delete -Methoden nötig

• Dies funktioniert auch, falls sich Objekte gegenseitig nochzyklisch referenzieren

• MitSystem.gc();

wird eine Empfehlung an die Garbage Collection ausgegeben,aktiv zu werden, in der Regel ist dies aber nicht nötig

Page 34: Java

137

Klassenattribute und -methoden

Attribute und Methoden gehören zu Objekten (also Instanzen)einer Klasse

Aber: es gibt Klassenattribute und -methoden, die nicht zuInstanzen (also Objekten) gehören, sondern zu den Klassenselbst

138

Klassenvariablen

• Attribute, die für jedes Objekt neue Instanzen bilden, heißenInstanzvariablen (Standardfall)

• Werden Attribute mit static gekennzeichnet, handelt es sichum Klassenvariablen , die für die gesamte Klasse nur eineInstanz besitzen

• Klassenvariablen existieren auch ohne die Existenz einesObjektes. Auf sie kann durch Klassenname. Attributnamezugegriffen werden.

139

Klassenmethoden

• Methoden, die ausschließlich auf Klassenvariablenzurückgreifen, dürfen mit static gekennzeichnet werden, sieheißen Klassenmethoden . Klassenmethoden dürfen auch nurKlassenmethoden benutzen

• Klassenmethoden können auch ohne Existenz eines Objektesmit Klassenname.Methodenname( ...) aufgerufen werden.

• Die main() -Methode ist eine Klassenmethode, da zu Beginnnoch keine Objekte erzeugt wurden

140

Beispielclass Demo {

int a;static int b;

public static void main(String[] args) {

a = 1; // nicht erlaubtb = 1; // erlaubttest(); // nicht erlaubtnew Demo().test(); // erlaubttest2(); // erlaubtnew Demo().test2();// erlaubt

}

void test() {a = 2; // erlaubtb = 2; // erlaubt

}

static void test2() {b = 3;

}}

...Demo d = new Demo();d.a = 1; // erlaubtd.b = 1; // erlaubtDemo.a = 1; // nicht erlaubtDemo.b = 1; // erlaubtDemo.test(); // nicht erlaubtDemo.test2(); // erlaubt

...

Page 35: Java

141

Überladen von Methoden Aufruf von Objekten

Wunsch für Methoden/Attribute: Gleiche Namen für gleiche Zwecke– z.B. Girokonto erzeugen ohne/mit einem initialem Kontostand

• Benutzt werden sollen Methoden mit gleichen Namen• Problem: Wie diese Methoden auseinanderhalten?• Idee: unterscheide anhand Parameter-Typen:

Methoden gleichen Namens müssen sich also im Typ von mindestenseinem Parameter oder in der Anzahl der Parameter unterscheiden

zahle ( int betrag)zahle ( int betrag, String verwendungszweck)

142

Überladen von Methoden

• Unterschiedliche Methoden müssen sich im Methodennamenoder in der Übergabeparameterliste (oder in beidem)unterscheiden

• Hat eine Klasse mehrere Methoden mit identischem Namennennt man diese Methode überladen

• In unterschiedlichen Klassen dürfen auch Methoden mitidentischem Namen und identischen Übergabeparameterlistendeklariert werden

143

Überdecken von Attributen Aufruf von Objekten

• Verwenden von Variablen mit bereits benutzten Namen• Zugreifen auf überdeckte Attribute über this

public class Girokonto {

private int kontostand; // in Pfennigen gerechnet

...

public void setzeKontostand( int kontostand) {this .kontostand = kontostand;

}

...

}

144

Zugriff auf überdeckte Attribute

• Variablendeklarationen in Klassenmethoden überdecken dieAttribute der Klasse

• Die Attribute sind nur überdeckt, nicht überschrieben• Auf Attribute der Klasse kann dann über das Schlüsselwort

this zugegriffen werden• this ist eine Referenz auf das zur Methode zugehörende

Objekt

Page 36: Java

145

Übung: Überladen von Konstruktoren, Methoden

Lernziele:

• Erweitern einer Klasse um Attribute und Methoden• Übersicht behalten durch sinnvolles, sparsames Vergeben von Methodennamen

(Namen mehrfach in einer Klasse vergeben)

Aufgabe:

• Implementieren Sie eine zweite Konstruktor-Methode für die Klasse „Girokonto“. Siesoll es ermöglichen, daß schon bei der Erzeugung eines Girokonto-Exemplars einWert für den initialen Kontostand übergeben werden kann. Welchen Namen mußdiese Methode tragen? Der übergebene Parameter soll kontostand heißen. Esgibt in der Klasse "Girokonto" bereits ein Attribut mit diesem Namen.Stellt dies ein Problem dar?

146

Übung: Überladen

Lösungsmuster:– Konstruktor-Methode -> Name identisch mit Klassenname– Überdecken des Namens kontostand (als Attributname und Variablenname)

public class Girokonto {...

public Girokonto( int kontostand) {this .kontostand = kontostand;

}...

}

Aufruf von Objekten

147

Zusammenspiel zwischen Objekten

• In einem OO-System kooperieren Objekte, umgemeinsam eine Aufgabe zu lösen

• Jede Klasse kann etwas besonders gut (Spezialist)– z.B. Klasse "Girokonto" für Umgang mit Girokonten

• Beim Erstellen eines OO-Systems müssen Spezialistenausgemacht werden– z.B. Erweiterung um Währungsrechnen

Aufruf von Objekten

148

Übung: Zusammenspiel von Objekten

Motivation:• Zusammenspiel mehrerer Objekte, Überladen von Namen

• Weg von Anforderungstext zu einer neuen Klasse• Ändern einer bestehenden Klasse

Aufgabe:• Entwerfen und implementieren Sie eine neue Klasse „Waehrungsrechner“ für das

Umrechnen von EuroCent in Pfennige (100 EuroCent ≈ 200 Pfennige)– Überlegen Sie, ob diese Klasse Attribute besitzen muß? Welche könnte sie besitzen?– Ergänzen Sie eine Methode "int wandeleInPfennig (int eurocent)"

und eine Methode "int wandeleInEuroCent (int pfennige)“.

• Die Klasse "Girokonto" soll angepaßt werden:– Einem Girokonto-Objekt soll beim Erzeugen stets ein "individueller" Währungsrechner

übergeben werden können, der für Konvertierungen benutzt wird.– Verstecken Sie nach außen, daß der Kontostand intern stets in EuroCent gespeichert wird

und jede andere Währung konvertiert wird („Information-Hiding“).

Aufruf von Objekten

Page 37: Java

149

Übung: Zusammenspiel von Objekten

Lösung:

public class Waehrungsrechner {

private int euroFaktor;

public Waehrungsrechner(){

euroFaktor = 2;

}

public int wandeleInEuroCent ( int pfennige){

int euroCent = pfennige / euroFaktor;

return (euroCent);

}

public int wandeleInPfennig ( int euroCent){

int pfennige = euroCent * euroFaktor;

return (pfennige);

}

} →

Aufruf von Objekten

150

Übung: Änderungen in „Girokonto“public class Girokonto {

private int kontostand = 0;

private Waehrungsrechner wr;

public Girokonto(Waehrungsrechner wr) {

this .wr = wr;

}

public Girokonto(Waehrungsrechner wr, int kontostand){

this .wr = wr;

// 1. Umrechnen des Betrags in EuroCent

int euroCent = wr.wandeleInEuroCent(kontostand);

// 2. Konstand aktualisieren

this .kontostand = euroCent;

}

Aufruf von Objekten

151

Übung: Änderungen in „Girokonto“public void zahle ( int pfennige){

// 1. Umrechnen des zahlbetrags in EuroCent

int euroCent = wr.wandeleInEuroCent(pfennige);

// 2. Konto aktualisieren

kontostand = kontostand + euroCent;

}

public int holeKontostand(){

// 1. Umrechnen des aktuellen Kontostandes in Pfennige

int pfennige = wr.wandeleInPfennig(kontostand);

// 2. Kontostand in Pfennigen zurückgeben

return (pfennige);

}

Aufruf von Objekten

152

Zusammenfassung

• Konstruktoren• Referenzen• Garbage Collection• Übergabe von Parametern an Methoden• Klassenattribute / Klassenmethoden• Namensraum

– Überladen von Methoden– Überdecken von Attributen

• Vertiefung OO-Programm=Mehrere Objekte + Nachrichtenaustausch– Aufgaben verteilen („Spezialisten“)– Klasse „Waehrungsrechner“

Aufruf von Objekten

Page 38: Java

Kapitel 7.3

Operatoren, Ausdrücke, Zuweisungen

154

Operatoren, Ausdrücke und Zuweisungen

• Ausdrücke sind mehrere durch Operatoren und Klammernverknüpfte Variablen oder Literale

Beispiel:5*a + 7*(3 - b)

ist ein (in diesem Fall arithmetischer) Ausdruck

• Ausdrücke haben Ergebnisse eines bestimmten Typs, diesesErgebnis kann einer Variablen zugewiesen werden.

Beispiel:c = 5*a + 7*(3-b);

155

Arithmetische Operatoren

• Arithmetische Operatoren: Bildung arithmetischer Ausdrücke

• Arithmetische Operatoren in Java:– Addition (+) und Subtraktion (- )– Multiplikation (* ) und Division (/ ) und– Restbildung („modulo“) (%)

• Zusätzlich:– einstellige Operatoren– Inkrement- und Dekrement-Operatoren mit Nebeneffekten

Programmkonstrukte

156

Arithmetische Operatoren Programmkonstrukte

Operator Bezeichnung Bedeutung+ Positives Vorzeichen +a ist synonym mit a- Negatives Vorzeichen -a kehrt das Vorzeichen um+ Summe a + b ergibt die Summe von a und b- Differenz a – b ergibt die Differenz von a und b* Produkt a * b ergibt das Produkt aus a und b/ Quotient a / b ergibt den Quotienten von a und b% Restwert a % bergibt den Restwert der Division von a durch b

++ Präinkrement ++a ergibt a+1 und erhöht a um 1++ Postinkrement a++ ergibt a und erhöht a um 1-- Prädekrement --a ergibt a–1 und verringert a um 1-- Postdekrement a-- ergibt a und verringert a um 1

In Java läßt sich dieser Operator sowohl auf ganze Zahlen als auch auf Fließkommazahlen anwenden!!

Page 39: Java

157

Postfix- und Präfix Increment und Decrement

• Inkrement- und Dekrementoperatoren erhöhen, bzw.erniedrigen eine Variable um 1, der Inhalt der Variable wirdzurückgegeben

• ++ ist der Inkrement- und -- der Dekrementoperator

• Steht der Operator vor der Variablen (Präfix), so wird dieVariable zuerst erhöht (bzw. erniedrigt) und dann das Ergebniszurückgegeben

• Steht der Operator hinter der Variablen (Postfix), so wird zuerstdas Ergebnis der Variablen zurückgegeben, bevor sie erhöht(bzw. erniedrigt) wird

158

Arithmetische Operatoren

• Präinkrement

int a = 5;int b = ++a; gleichbedeutend mit a = a + 1;

b = a;Ergebnis: a = 6

b = 6

• Postinkrement

int a = 5;int b = a++; gleichbedeutend mit b = a;

a = a + 1;Ergebnis: a = 6

b = 5

Programmkonstrukte

159

Arithmetische Operatoren ( +, - , * , / , %)

• Arithmetische Operatoren sind Infix-Operatoren• Es gibt Addition (+), Subtraktion (- ), Multiplikation (* ),

Division (/ ) und Modulo-Division (%)

• Modulo-Division bedeutet Divisionsrest, also11 / 3 = 3, Rest 2, damit ist 11 % 3gleich 2

• Arithmetische Operatoren lassen sich (auch in gemischterForm) auf Variablen und Ausdrücke der Typen char , byte ,int , long , float und double anwenden

• Divisionen durch Null sind nur für die Typen float unddouble direkt erlaubt, bei char , byte , int und long wirdeine Exception geworfen (später ausführlicher)

160

Ergebnistypen bei arithmetischen Operatoren

+ - */ %

char byte short int long float double

char int int int int long float double

byte int int int int long float double

short int int int int long float double

int int int int int long float double

long long long long long long float double

float float float float float float float double

double double double double double double double double

Page 40: Java

161

Ergebnistypen bei arithmetischen Operatoren

Beispiel:short a,b,c; // Deklaration

int d;

a=7; // Initialisierung

b=8;

c = a + b; // Zuweisung unzulässig

d = a + b; // Zuweisung zulässig

Fehlermeldung zur Compilezeit:Incompatible type for =. Explicit cast needed to convert

int to short.

c = a + b;

^

162

Implizite Typwandlungen

• Bei einer Zuweisung muß der Ergebnistyp des Ausdrucks mitdem der Variablen übereinstimmen, es sei denn, impliziteTypwandlungen sind erlaubt

• Implizite Typwandlungen sind in der Regel in Richtunggrößerer Typen erlaubt:

byte shortint long float double

char

• Achtung: Wandlung von long nach float eventuellverlustbehaftet

Hinweis: char nach short wäre prinzipiell verlustfrei möglich, ist aber dennoch unzulässig!

163

Implizite Typwandlungen

Beispiel:double a; // Deklarationen und Initialisierungen

double b=10.0;

int c=10;

a = c; // Zuweisung erlaubt, da Typwandlung

// implizit möglich

c = b; // Zuweisung nicht erlaubt

164

Explizite Typwandlungen (Cast)

• Explizite Typwandlungen sind durch Cast "( typ) " möglich.

Beispiel:double b=10.0;

int c;

c = (int)b; // Zuweisung erlaubt, da Typ gewandelt

• Typwandlungen sind in der Regel verlustbehaftet• Bei Verlusten weder Fehlermeldungen noch Warnungen zur

Laufzeit

Page 41: Java

165

Explizite Typwandlungen (Cast)

Beispiel: Typwandlung von short nach byte(hier ohne Verlust)

0000000000110001 (16 Bit, Wert entspricht 49)

...

00110001 ( 8 Bit, Wert entspricht 49)

1111111111110001 (16 Bit, Wert entspricht -15)

...

11110001 ( 8 Bit, Wert entspricht -15)

166

Explizite Typwandlungen (Cast)

Beispiel: Typwandlung von short nach byte(hier mit Verlust)

0000001000000010 (16 Bit, Wert entspricht 514)

...

00000010 ( 8 Bit, Wert entspricht 2)

Programm:shor t a = 514;

byte b = (byte)a; // Typwandlung von short nach byte

System.out.println(b);

Programmausgabe:

2

167

Vergleichsoperatoren

• Vergleichen von Ausdrücken

• Ergebnistyp stets boolean

• In Java:– Gleichheitstest (==), Ungleichheitstest (!= )– Größer (>), Kleiner (<)– Größer gleich (>=) und Kleiner gleich (<=)

Programmkonstrukte

168

Vergleichsoperatoren

• Achtung: Gleichheitstest (==) darf nicht mit Zuweisung (=)verwechselt werden

• Vergleich nicht für String geeignet

Programmkonstrukte

Operator Bezeichnung Bedeutung== Gleich a==b ergibt true , wenn a gleich b ist. Im Falle von

Referenztypen ist der Rückgabewert true , wennbeide Werte auf dasselbe Objekt zeigen.

!= Ungleich a!=b ergibt true , wenn a ungleich b ist. Im Falle vonReferenztypen ist der Rückgabewert true , wennbeide Werte auf unterschiedliche Objekte zeigen.

> Größer a > b ergibt true , wenn a größer b ist< Kleiner a < b ergibt true , wenn a kleiner b ist

>= Größer gleich a >= b ergibt true , wenn a größer oder gleich b ist<= Kleiner gleich a <= b ergibt true , wenn a kleiner oder gleich b ist

Page 42: Java

169

Vergleichsoperatoren Programmkonstrukte

• Veranschaulichung des Operators ==

– Beispiel:int a = 3;int b = 4;int c = 7;

a + b == c ergibt true

170

Zuweisungsoperatoren

• Setzen des Wertes einer Variablen

• = ist der Operator für die Standardzuweisung

• Es gibt viele Zuweisungen mit Nebeneffekten:+=, -= , *= , /= , %=, ^= , &=, |= , <<=, >>= und >>>

a += b bedeutet a = a + b;

a -= b bedeutet a = a - b;

a *= b bedeutet a = a * b;

Programmkonstrukte

171

Zuweisungsoperatoren Programmkonstrukte

Operator Bezeichnung Bedeutung= Einfache Zuweisung a = b weist a den Wert von b zu und liefert b als

Rückgabewert+= Additionszuweisung a += b weist a den Wert von a + b zu und liefert

a + b als Rückgabewert-= Subtraktionszuweisung a -= b weist a den Wert von a – b zu und liefert

a – b als Rückgabewert*= Multiplikationszuweisung a *= b weist a den Wert von a * b zu und liefert

a * b als Rückgabewert/= Divisionszuweisung a /= b weist a den Wert von a / b zu und liefert

a / b als Rückgabewert%= Modulozuweisung a %= bweist a den Wert von a % bzu und liefert

a % bals Rückgabewert&= UND-Zuweisung a &= b weist a den Wert von a & b zu und liefert

a & b als Rückgabewert|= ODER-Zuweisung a |= b weist a den Wert von a | b zu und liefert a

| b als Rückgabewert^= EXKLUSIV-ODER-Zu-

weisunga ^= b weist a den Wert von a ^ b zu und lieferta ^ b als Rückgabewert

172

Zuweisungsoperatoren Programmkonstrukte

• Veranschaulichung der Additionszuweisung

– Beispiel:int a = 3, b = 5;a += b; gleichbedeutend mit a = a + b;

ergibt: a = 8

Page 43: Java

173

Logische Operatoren

• Vergleichen boolescher Werte

• In Java:– mit Short-Circuit-Evaluation (SCE)

• UND (&&)

• ODER (|| )

– ohne Short-Circuit-Evalutation (Kurzschluß-Auswertung)• UND (&)

• ODER (| )

• Zusätzlich:– logisches NICHT (! )– EXKLUSIV-ODER (^ )

Programmkonstrukte

174

Logische Operatoren Programmkonstrukte

Operator Bezeichnung Bedeutung! Logisches NICHT !a ergibt false , wenn a wahr ist und true , wenn a

false ist&& UND mit SCE a && b ergibt true , wenn sowohl a als auch b wahr

sind. Ist a bereits falsch, so wird false zurückge-geben und b nicht mehr ausgewertet.

& UND ohne SCE a & b ergibt true , wenn sowohl a als auch b wahrsind. Beide Teilausdrücke werden ausgewertet.

|| ODER mit SCE a || b ergibt true , wenn mindestens einer derbeiden Ausdrücke a oder b wahr ist. Ist bereits a

wahr, so wird true zurückgegeben und b nicht mehrausgewertet.

| ODER ohne SCE a | b ergibt true , wenn mindestens einer derbeiden Ausdrücke a oder b wahr ist. Beide Teilaus-drücke werden ausgewertet.

^ EXKLUSIV-ODER a ^ b ergibt true , wenn beide Ausdrücke einenunterschiedlichen Wahrheitswert haben.

175

Logische Operatoren Programmkonstrukte

• Veranschaulichung der Operatoren || und &&

– Beispiel:int a = 3, b = 5, c = 5;

(a == b) || (b == c) ergibt true(a == b) && (b == c) ergibt false

&& false true

false false false

true false true

|| false true

false false true

true true true

176

Bitweise AND, OR, XOR

• Vergleich der einzelnen Bits zweier ganzer Zahlen

• Für alle ganzzahligen primitiven Datentypen

• Es gibt "bitweise und" bzw. AND (&), "bitweise inklusiv oder"bzw. OR (| ) und "bitweise exclusiv oder" bzw. XOR (^ )

• Für jede Position der Bitdarstellung der beiden Eingabezahlenwird ein Bit berechnet und in der Bitdarstellung derErgebniszahl an derselben Position abgelegt (siehe Beispiel)

Page 44: Java

177

Bitweise AND, OR, XOR

Beispiel:00000011 entspr. 3

00001001 entspr. 9

========

AND: 00000001 entspr. 1

OR: 00001011 entspr. 11

XOR: 00001010 entspr. 10

& 0 1

0 0 0

1 0 1

| 0 1

0 0 1

1 1 1

^ 0 1

0 0 1

1 1 0

Programm:byte a=3, b=9;

System.out.println(a & b);

System.out.println(a | b);

System.out.println(a ^ b);

178

Verschiebeoperatoren

• Durch Verschiebeoperatoren können Bitdarstellungen vonGanzzahldatentypen nach links, bzw. rechts verschobenwerden.

• Links vom Operator steht der zu verschiebende Wert undrechts die Anzahl der Bits, um die verschoben werden soll

• "<<" ist der Links-Shift-Operator und ">>" und ">>>" sindRechts-Shift-Operatoren

• Bei "<<" und ">>>" wird jeweils die Null nachgeschoben, bei">>" das Vorzeichenbit

• a << n entspricht einer Multiplikation mit 2n und a >>> nentspricht einer Division durch 2n.=> Geschwindigkeitsvorteile

179

String-Konkatenation

• Der +-Operator kann verwendet werden, um zwei Objekte derKlasse String zu verknüpfen

• Ist nur einer der Operanden ein Objekt der Klasse String, undein anderer ein primitiver Datentyp, wird letzterer nach Stringgewandelt

Beispiel:int alter = 27;

System.out.println("Alter : " + alte r + " Jahre");

Ausgabe:Alter: 27 Jahre

180

Unäre Operatoren

• Unäre Operatoren werden immer vor einen Ausdruck gestellt• Es gibt Plus- und Minusvorzeichen (+) und (- ), sowie

logische (! ) und bitweise (~) Verneinung.

• Vorzeichen und bitweise Verneinung werden fürGanzzahldatentypen verwendet, die logische Verneinung fürden Datentyp boolean

Page 45: Java

181

Bedingte Ausdrücke

• Mit bedingten Ausdrücken lassen sich Alternativen inAusdrücken beschreiben

• Sie werden in folgender Form benutzt:Ausdruck1 ? Ausdruck2 : Ausdruck3

• Ausdruck1 muß einen Wert vom Typ boolean haben

• Ausdruck2 und Ausdruck3 sind zwei Ausdrücke mit Wert vomgleichen Typ

• Ist Ausdruck1 gleich true , so wird Ausdruck2 ausgewertet,sonst Ausdruck3

182

Bedingte Ausdrücke

Beispiel 1:int alter = 17;

System.out.println(alter >= 18 ? "volljährig" :"nicht volljährig");

Ausgabe:nicht volljährig

Beispiel 2:int alter = 18;

double Mitgliedsbeitrag = alter >= 18 ? 200 : 100;

System.out.println("Mitgliedsbeitr.:" + Mitgliedsbeitrag);

Ausgabe:Mitgliedsbeitr.:200

183

Operator-Prioritäten

• Die Standard-Richtung für die Auswertung von Operatoren istvon links nach rechts

• Zuweisungsoperatoren werden von rechts nach linksausgewertet

• Operatoren unterliegen einer Prioritätenhierarchie, analog derPunkt- vor Strich-Regel, also der Ausdruck 5 + 3 * 3 + 1repräsentiert den Wert 15 , da die Multiplikation höhere Prioritäthat.

• Operatoren mit höchster Priorität werden zuerst ausgewertet• Durch Klammerung mit runden Klammern ( und ) kann die

vorgegebene Hierarchie überwunden werden

184

Operator-Prioritäten

Kategorie Operatoren

0 Zuweisung = += -= *= /= %= ^=&= |= <<= >>= >>>=

1 Bedingungsoperator ? :

2 logisches Oder ||

3 logisches Und &&

4 bitweise ink. Oder |

5 bitweise exkl. Oder ^

6 bitweise Und &

Niedrigste Priorität

Page 46: Java

185

Operator-Prioritäten

Kategorie Operatoren

7 Vergleichsop. == !=

8 Vergleichsop. < > <= >= instanceof

9 Verschiebeop. << >> >>>

10 additive Operatoren + -

11 multiplikative Op. * / %

12 Erzeugungs- oderTypumwandlungsop.

new (type) expr

186

Operator-Prioritäten

Kategorie Operatoren

13 unäre Operatoren ++expr -- expr +expr- expr ~ !

14 Postfix-Operatoren [] . expr++ expr--

Höchste Priorität

187

Operator-Prioritäten: Beispiele

int a, b=2;

a = b << 1 + 2;

• Addition hat höhere Priorität als Verschiebeoperatoren• Es wird daher zunächst 1+2 ausgewertet und der Wert von

b (2) dann um das Ergebnis (3) nach links verschoben, manerhält also 16 . Dieser Wert wird dann der Variablen azugewiesen, denn der Zuweisungsoperator hat die niedrigstePriorität

188

Operator-Prioritäten: Beispiele

int a, b=2;

a = (b << 1) + 2;

• Durch die Klammerung wird die Verschiebung zuerstdurchgeführt

• b um eins nach links verschoben ergibt 4. Dann wird 2aufaddiert und das Ergebnis (6) der Variablen a zugewiesen

Page 47: Java

189

Operator-Prioritäten: Beispiele

int a = 5, b;

a += b = 8;

• Auswertreihenfolge von links rechts nach links• Zunächst wird b die Zahl 8 zugewiesen, dann wird der neue

Wert von b auf a aufaddiert, a erhält also den Wert 13

(a += b) = 8;

• Fehler: Auswertreihenfolge läßt sich nicht verändern, dennAusdrücke dürfen nie links auf einer Zuweisung stehen

190

Zusammenfassung

• Operatoren– arithmetische Operatoren– Vergleichsoperatoren– Zuweisungsoperatoren

– logische Operatoren– bitweise Operatoren– Verschiebeoperatoren

– unäre Operatoren– bedingte Ausdrücke

• Prioritäten

• Typumwandlungen (Type Casting)– implizit / explizit

Programmkonstrukte

Kapitel 7.4

Anweisungen

192

Zur Einordnung

• Programme bestehen aus Klassen.• Eine der Klassen eines Programms hat eine Methode namens

„main“. Mit der wird die Ausführung begonnen.• Danach werden in der Regel Objekte erzeugt, die dann für

bestimmte Aufgaben zuständig sind.• Die Kommunikation zwischen den Objekten erfolgt über den

Aufruf von Methoden / das Versenden von Nachrichten.• Was innerhalb einer Methode passiert, wird durch

Anweisungen festgelegt. Grundbausteine der Anweisungenhaben wir bereits kennengelernt:– Literale und Variable– Operatoren

Page 48: Java

193

Zur Einordnung

• Der Algorithmus (also die Verarbeitungsvorschrift), der durcheine Methode realisiert wird, wird durch eine Menge vonAnweisungen beschrieben.

• Die Arten von Anweisungen, die hierfür verwendet werden,diskutieren wir im folgenden.

• Danach kennen wir dann alle Grundbestandteile von Java-Programmen.

194

Anweisungen

• Anweisungen (außer Blöcken) werden durch Semikolonvoneinander getrennt.

• Blöcke sind Sequenzen von Anweisungen, in der Regelgeklammert mit {}, sie werden nicht durch Semikolonvoneinander getrennt.

{

konto.zahle(+100);

konto.zahle(+30);

konto.zahle(-20);}

• Deklarationen bzw. Initialisierungen innerhalb von Blöcken sindnur innerhalb dieser gültig.

{Anweisung1;Anweisung2;...

}

195

Anweisungen

• Auch die bereits bekannten– Zuweisungen– Deklarationen und Initialisierungen

sind Anweisungen.

• “Einfache" Anweisungen werden der Reihenfolge nachabgearbeitet.

• Blöcke, Bedingungen, Schleifen und Sprünge sindAnweisungen, sie beeinflussen den Kontrollfluß. Siebeschreiben größere Strukturen als Ausdrücke, jedoch nicht sogroße wie Klassen.

196

Sichtbarkeit in Blöcken

• Da Deklarationen jenseits der äußeren Grenze eines Blocksnicht bekannt sind, stellt sich bei Attributen und Variablen, diein mehreren Blöcken namensgleich deklariert werden, dieFrage, auf welches Attribut durch einen Attributnamen Bezuggenommen wird.

• Der Zugriff auf die „falschen“ Attribute ist eine häufigeFehlerursache.

Page 49: Java

197

Sichtbarkeit in Blöcken

• Als generelle Regel der Sichtbarkeit läßt sich formulieren:– es wird zunächst im aktuellen (also inneren) Block nach dem Attribut

gesucht,– wird es dort nicht gefunden, wird schrittweise nach außen vorgedrungen

bis ein entsprechend benanntes Attribut gefunden wird.

• Besonders verwirrend kann dabei sein, daß Attribute undVariable erst ab der Deklarationsanweisung bekannt sind.

198

Variablen in Blöcken

• Im Block deklarierte Variablen sind nur im Block sichtbarpublic void zahle ( int betrag) {

int alterKontostand=kontostand;

{ // hier ist der alterKontostand sichtbar

int neuerKontostand = kontostand + 50000;...

// ab hier ist auch neuerKontostand sichtbar

Bildschirm.gibAus(neuerKontostand);

}

// neuerKontostand unsichtbar, alterKontostand sichtbar

int neuerKontostand = 1;

// ab hier dann die neue Variable neuerKontostand sichtbar

kontostand=kontostand + betrag;

}

Programmkonstrukte

199

Bedingtes Verzweigen (if-Anweisung)

• Bedingte Verzweigungen dienen zur Auswahl aus zweiAlternativen (siehe bedingte Ausdrücke)

if ( Ausdruck )

Anweisung1;else

Anweisung2;

• Ausdruck muß ein Wert vom Typ boolean haben• Anweisung1 wird ausgeführt, falls Ausdruck den Wert true

hat, sonst wird Anweisung2 ausgeführt.• Es wird zunächst Ausdruck ausgewertet. In Abhängigkeit vom

Ergebnis dann Anweisung1 oder Anweisung2.

200

Bedingtes Verzweigen (if-Anweisung)

• Der Teil else Anweisung2 ist optional. Liefert Ausdruck false,dann wird die if-Anweisung ohne weitere Ausführungverlassen.

• Unterscheidung zu Ausdruck1 ? Ausdruck2 : Ausdruck3:– bei der bedingten Verzweigung müssen Ausdruck2 und Ausdruck3 nicht

notwendigerweise ein Ergebnis des gleichen Typs liefern.

Page 50: Java

201

• Die if -Anweisung

if (kontostand < 0)Bildschirm.gibAus("Konto überzogen");

else

Bildschirm.gibAus("Geld vorhanden");

– else -Zweig ist optional

– ausdruck ist true → Ausführen von anweisungAfalse → Ausführen von anweisungB

Bedingtes Verzweigen Programmkonstrukte

if (ausdruck)anweisungA;

elseanweisungB;

ausdruck: boolean

202

Bedingtes Verzweigen

• Blöcke sind Anweisungen=> Mehrere Anweisungen lassen sich innerhalb der

if - oder else -Anweisung gruppieren

if (landeswährung == DM) {

neuerBetrag = betrag * 1.96;

System.out.println("Guthaben:" + neuerBetra g + " DM");

} else

System.out.println("Guthaben:" + betra g + " Euro");

203

Bedingtes Verzweigen

• Bedingte Verzweigungen sind selbst auch Anweisungen=> Schachtelung von if-Abfragen möglich

if (beruf == schüler)

System.out.println("Schülertarif");

else

if (beruf == rentner)

System.out.println("Rentnertarif");

else

System.out.println("Normaltarif");

Der zweite else -Zweig bezieht sich auf die zweite if -Abfrage

204

Bewachte Anweisungenswitch ( Ausdruck ) {

case Konstante1: Anweisungsfolge1;

case Konstante2: Anweisungsfolge2;

...

default: Anweisungefolge_n;

}

• Ausdruck ist vom Typ byte , short , int oder char

• Konstante_i sind Konstanten vom gleichen Typ wie Ausdruck• Anweisungsfolge_i sind Folgen von Anweisungen, die durch

Semikolon voneinander getrennt sind.

Page 51: Java

205

Bewachte Anweisungen

switch ( Ausdruck ) {

case Konstante1: Anweisungsfolge1;

case Konstante2: Anweisungsfolge2;

...

default: Anweisungefolge_n;

}

• Es wird zunächst Ausdruck ausgewertet.• Alle Anweisungen ab der ersten Konstante, welche gleich dem

Wert des Ausdrucks ist, werden abgearbeitet.

206

Bewachte Anweisungenswitch ( Ausdruck ) {

case Konstante1: Anweisungsfolge1;

case Konstante2: Anweisungsfolge2;

...

default: Anweisungefolge_n;

}

• Die Anweisungsfolge hinter default: wird auch abgearbeitet,falls keine Konstante gleich dem Wert von Ausdruck ist. Diedefault- Zeile ist optional.

• Beispiel 33

207

Bewachte Anweisungenswitch ( Ausdruck ) {

case Konstante1: Anweisungsfolge1;

case Konstante2: Anweisungsfolge2;

...

default: Anweisungefolge_n;

}

• Kommt die Anweisung break; in einer abzuarbeitendenAnweisungsfolge vor, so wird der gesamte von switchgefolgte Block verlassen.

208

Bewachte Anweisungen

• Die switch -Anweisung– default -Teil ist optional

int zensur = 2;switch (zensur) {

case 1:Bildschirm.gibAus("sehr gut");break ;

case 2:Bildschirm.gibAus("gut");break ;

...

default :Bildschirm.gibAus("das ist keine Zensur!");

}

Programmkonstrukte

switch (ausdruck){ case constant1:

anweisung1;

case constant2:

anweisung2;...default :

anweisung;}

ausdruck:byte , short , int , long , char

Page 52: Java

209

Schleifen

• Schleifen dienen dazu, die gleiche Anweisung mehrfachdurchlaufen zu können

• Diese Anweisung kann auch ein Block sein, also mehrereAnweisungen gruppieren.

• Es gibt Abbruch- bzw. Laufbedingungen für Schleifen• Es gibt 3 Schleifentypen:

while -Schleifen,do-while -Schleifen undfor -Schleifen

210

Schleifen

• Die while -Schleife– Die Laufbedingung Ausdruck ist vom Typ boolean

– Zunächst wird Ausdruck ausgewertet. Falls Ausdruck den Wert trueliefert, wird Anweisung abgearbeitet. Dies wiederholt sich solange, bisAusdruck den Wert false liefert

– Test vor Ausführung der Anweisungsfolge

int a=0;while (a < 100) {

Bildschirm.gibAus(a);a = a + 10;

};

Ausgabe: 0, 10, 20, ..., 90 (nicht mehr: 100)

BEISPIEL 34

Programmkonstrukte

while (ausdruck)anweisung;

ausdruck: boolean

211

Schleifen

• Die do-while -Schleife– Test nach Ausführung der Anweisungsfolge– also mindestens ein Durchlauf

int a=0;do {

Bildschirm.gibAus(a);a = a + 10;

} while (a < 100);

Ausgabe: 0, 10, 20, ..., 90, 100

Programmkonstrukte

doanweisung

while (ausdruck)

ausdruck: boolean

212

for -Schleifen (Zählschleifen)

for ( Initialisierungsliste; Ausdruck; Anweisungsliste)

Anweisung

• Initialisierungsliste ist eine Liste von Ausdrücken, die durchKommata getrennt sind. Sie wird als Initialisierung vor Eintrittin die Schleife abgearbeitet (nur einmal!). Typischerweiseweden hier Zählervariablen vereinbart.

• Ausdruck ist die Laufbedingung und muß daher einen Wertvom Typ boolean liefern. Ist das Ergebnis false , wirdabgebrochen, ansonsten wird als nächstes mit Anweisung derSchleifenrumpf abgearbeitet

Page 53: Java

213

for -Schleifen (Zählschleifen)

for ( Initialisierungsliste; Ausdruck; Anweisungsliste)

Anweisung

• Anweisungsliste ist eine Liste von Anweisungen, die durchKommata getrennt sind. Sie wird immer nach Anweisungausgeführt

• Nach der Auswertung von Ausdruck wird die Schleife dannfortgesetzt, wenn Ausdruck true liefert.

• Alle Anweisungen können optional weggelassen werden

214

Schleifen

• Die for -Schleife

int i;for (i=0; i<3; i++)

System .out.println(i);

– Ausgabe012

– Endlosschleifefor ( ; ; );

• BEISPIEL 36

Programmkonstrukte

for (init; test; update)anweisung;

test: boolean

215

Markierte Anweisungen

• Eine Anweisung läßt sich durch einen Namen markieren:

Markierung : Anweisung

• Markierung ist ein Bezeichner

Ist Anweisung aus mehreren Anweisungen zusammengesetzt,es ist also zum Beispiel ein Block oder eine Schleife, so gilt:

• Mit "break Markierung" wird Anweisung abgebrochen und mitdem unmittelbar auf Anweisung folgenden fortgefahren

• Mit "continue Markierung" wird Anweisung abgebrochen undvon Beginn an neu gestartet

216

Markierte Anweisungen

Markierung : Anweisung

• Markierung ist nur innerhalb der markierten Anweisung (Block,Schleife o. ä.) sichtbar

• Innerhalb von Bedingungs- und Zählschleifen kann break undcontinue ohne Markierung verwendet werden. Hier wird dieinnerste umgebene Schleife als markiert betrachtet.

• Sprunganweisungen sind in der Regel ein Anzeichenschlechter Strukturierung, sie sollten vermieden werden.

• Immerhin gibt es keine allgemeine Sprunganweisung (goto)!• BEISPIEL 38

Page 54: Java

217

Markierte AnweisungenBeispiel:

marke1: for (i=1; i<6; i++) {

marke2: for (j=1; j<4; j++) {

System.out.println( i + " / " + j);

if (i == 2)

break marke2; // Äquiv zu

if (i == 4) // break;

continue marke1;

}

System.out.println("=====");

}

Ausgabe:1 / 11 / 21 / 3=====2 / 1=====3 / 13 / 23 / 3=====4 / 15 / 15 / 25 / 3=====

218

Sichtbarkeit

Hier ist a sichtbar

Hier ist test sichtbar

Hier ist b sichtbar

Hier ist c sichtbar

Hier ist d sichtbar

{...

int a;

test : for (a=0; a<100; a++) {

int b;

for (int c=0; c<a; c++) {

System.out.println(a*c);

}

}

int d=7;

System.out.println(a*d);

}

219

Zusammenfassung

• Anweisungen– elementare Anweisungen– Blöcke

– if

– switch

• Schleifen– while

– do-while

– for

• Markierte Anweisungen• Sichtbarkeit

Programmkonstrukte

Programmierkonventionen und Dokumentation

Kapitel 8

Page 55: Java

221

Programmierkonventionen

• Warum Programmierkonventionen (Code Conventions)?– Nur wenig Software wird ausschließlich vom originalen Autor gewartet– Programmierkonventionen erleichtern Lesbarkeit und Verständlichkeit– selbst geringe Verbesserungen der Wartbarkeit rechtfertigen

Anstrengungen in der Entwicklung

222

Ausblick in die Wartung

Folgende Gegenstände der Wartung können unterschiedenwerden:Beseitigung von Fehlern, die den Software-Einsatz behindern:– echte Entwicklungsfehler– in der Wartung eingefügte Fehler– Sicherstellung der nicht-funktionalen Anforderungen nach

AuslieferungÄnderungen der Umweltbedingungen (Hardware, Fremdsoftware,

Organisation)– Jahr 2000 / EURO– gesetzliche Änderungen– neue Basissystemeneue Anforderungen (die Kenntnis einer Version weckt neue

Anforderungen!)

223

Ein Ausblick in die Wartung

Lehman‘s Law of Uncertainty and Lehman‘s Law of IncreasingSoftware Entropy bedeuten, daß Änderungen während undnach der Entwicklung unvermeidlich sind.

Law of Uncertainty: Software ändert sich während ihresganzen Lebenszyklus. Genauere Angaben zumGegenstand der Änderungen sind nicht vorhersehbar.

Law of Increasing Software Entropy: Änderungen einerSoftware machen ihre Struktur in der Regelunverständlicher. Die innere Struktur einer Software gehtmit fortschreitender Software-Lebenszeit verloren

224

Ausblick in die Wartung

Das Verhältnis von Entwicklungsaufwänden zuWartungsaufwänden wird in der Literatur in einem Bereichzwischen 1:4 und 1:2 angegeben. Das bedeutet, daßzwischen 20% und 33% der gesamten Kosten auf dieEntwicklung entfallen und daß zwischen 80% und 67% aufdie Wartung entfallen!

Deshalb: Programmierkonventionen als eine Maßnahme derVerbesserung der Wartbarkeit!Andere Maßnahmen: Dokumentierte Ergebnisse von OOAund OOD, Verzicht auch Trick-Programmierung

Page 56: Java

225

Programmierkonventionen

• Wie sollen sie eingesetzt werden?– Die offizielle Konventionen sollten als Basis dienen– Sie funktionieren nur, wenn sie von jedem eingehalten werden– Es kann projektspezifische Erweiterungen geben

226

Datei-Organisation

• Keine Dateien mit mehr als 2000 Zeilen• Abschnitte sollten durch Leerzeilen getrennt werden• Jede Datei sollte nur eine öffentliche Klasse bzw. ein

öffentliches Interface besitzen• Öffentliche Klasse / Interface ist am Dateianfang zu finden• Datei hat vorgegebene Aufteilung:

– Anfangskommentare– Package und Import-Statements– Klassen- und Interface-Deklarationen

227

Ordnung innerhalb einer Datei

Reihenfolge in einer Datei:• Anfangskommentare in C-Format:

/** Klassenname** Versionsinformation** Copyright-Vermerk*/

• Package- und Import-Statementspackage java.awt;

import java.awt.peer.CanvasPeer;

228

Ordnung innerhalb einer Datei

• Klassen- und Interfacedeklarationen in vorgegebenerReihenfolge:– Klassen / Interface - Kommentar (/** ... */ )– class oder interface Definition– Klassen / Interface - Implementierungskommentar, falls nötig (/* ... */ )– Klassenvariablendeklarationen (static )

– Instanzvariablendeklarationen– Konstruktoren– Methoden

(geordnet, also z.B. sollten öffentliche Klassen nicht zwischen privatenstehen)

Page 57: Java

229

Einrückungen

• Es werden 4 Zeichen eingerückt• Eine Zeile ist maximal 80 Zeichen breit• Regeln für Zeilenumbrüche:

– Umbruch auf höchstmöglicher Ebene– Umbruch vor Operatoren und nach Kommata– Gleiche Hierarchieebenen sollen möglichst in folgender Zeile

untereinanderstehen, falls nicht möglich, ist 8 Zeichen einzurückenz.B.:

var = funktion1(Ausdruck1,funktion2(Ausdruck2,

Ausdruck3));

230

Kommentare

• Block-Kommentare sollen mit führendem * in folgender Formgeschehen:/*

* Dies ist ein Kommentar.*/

• Einzeilenkommentare kommen vor dem entsprechendenProgrammcode mit zugehöriger Einrückung.Vor dem Kommentar steht eine Leerzeileif (Bedingung) {

/* Bedingung wird ausgewertet */...

}

231

Kommentare

• Zeilenendekommentare (// ) am Ende der Zeile solltengenügend eingerückt sein. Sie werden nicht für mehrzeiligeKommentare benutzt, es sei denn, Programmtext wirdauskommentiert

if (personImHaus == TRUE) {

return Zimmernummer; // Raum im Haus

} else {

return Adresse; // Privatadresse

}

232

Deklarationen

• Es sollte möglichst nur eine Deklaration pro Zeile erfolgenString name; // Vor- und Nachname

String straße; // Straße mit Hausnummer

und nichtString name, straße; // Möglichst vermeiden

• Auf keinen Fall dürfen Deklarationen unterschiedlichen Typs,oder Methoden- und Attributdeklarationen in einer Zeile stehenlong kundennummer, getKundennummer(); // Vermeiden

String name, namensliste[]; // Vermeiden

Page 58: Java

233

Deklarationen

• Deklarationen sollten immer am Anfang eines Blocks stehen• Mit Variablendeklarationen sollte nicht bis zur ersten

Benutzung gewartet werden• Lokale Variablen sollten, sofern möglich bei Deklaration auch

initialisiert werden• Überdeckungen von Variablen einer höheren Ebene sollten

vermieden werden:int zähler;...void funktion() {

if (Bedingung) {int zähler; // Vermeiden!

}}

234

Anweisungen

• Eine Zeile sollte nur einen Ausdruck enthalten:argv++; argc++; // Vermeiden!

• In Blöcken sollten öffnende Klammern am Zeilenende stehen• Struktur von if - und if-else -Anweisungen:

if (Bedingung) {Anweisungen;

}

if (Bedingung) {Anweisungen;

} else {Anweisungen;

}

if (Bedingung) {Anweisungen;

} else if (Bedingung) {Anweisungen;

} else if (Bedingung) {Anweisungen;

}

235

Namenskonventionen

• Klassennamen– Substantive, große Anfangsbuchstaben, ganze Worte, innere Worte

beginnen mit Großbuchstabenclass Datum;

class KundenListe;

• Interfacenamen– Analog zu Klassennamen

• Methodennamen– Verben, klein geschrieben, innere Worte beginnen mit Großbuchstabenint gibKundenListe();

236

Namenskonventionen

• Variablen / Attribute– am Wortanfang klein geschrieben, innere Worte beginnen mit

Großbuchstaben– Namen sollen selbsterklärend seinDatum meinGeburtsDatum = new Datum("1.1.1904");

– Temporäre Variablen dürfen mit einem Buchstaben benannt werdenhierbei gilt:

– i , j , k , mund n werden für Integerzahlen benutzt– c , d und e werden für Zeichen benutzt

• Konstanten– Konstanten werden komplett groß geschrieben, Worte durch "_"

voneinander getrenntint MINIMALE_BREITE = 10;

Page 59: Java

237

Sonstige Konventionen

• Klassen und Methoden sollten so privat wie möglich deklariertwerden

• Konstanten sollten über Namen in Programmcode eingebautwerden (bis auf bedeutungslose, wie -1 , 0, 1)

• Mehrfachzuweisungen sollten vermieden werdena = b = c; // Vermeiden!

• Klammerungen können selten benutzte Operatorprioritätenverdeutlichen

238

Dokumentation

• Es gibt 3 Sorten von Kommentaren:– // Rest der Zeile wird auskommentiert (C++-Methode)

– /** Ein gesamter Abschnitt wird kommentiert,* Achtung: Schachtelung von Kommentaren ist* nicht möglich (C-Methode)*/

– /*** Eine Klasse oder Methode wird kommentiert,* aus diesem Kommentar lassen sich automatisch* HTML-Dokumentationen erstellen*/

• Automatische Dokumentation geschieht mit Hilfe des Tools"javadoc " von JDK.

239

javadoc - Dokumentation

• /** */ - wird vor Klassen- und Interface-Deklarationen sowievor Methoden, Konstruktoren und Attributdeklarationenberücksichtigt

• Kommentar wird in HTML-Dokumentation von "javadoc "aufgenommen=> HTML-Tags im Kommentar sind erlaubt

• /** ist Kommentaranfang und */ ist Kommentarende• Innerhalb des Kommentars wird ein * am Zeilenanfang

ignoriert• Erster Satz des Kommentars ist gesonderter

Zusammenfassungssatz. (Punkt als Endmarkierung)

240

javadoc - Dokumentation

• Durch @-Zeichen innerhalb des Kommentars werden Tagseingefügt, um automatische Querreferenzen zu erzeugen:

• @see-Tag erzeugt allgemeine Querreferenz– Referenz zu anderer Klasse:

@see java.io.InputStream@see String

– Referenz zu einer Methode einer Klasse:@see String#equals

– Referenz zu anderer HTML-Datei:@see <a href="spec.html">Java Spec</a>

• @author -Tag um Autor zu kennzeichnen– @author Albert Einstein

– @author Albert Einstein, Max Born, Werner Heisenberg

Page 60: Java

241

javadoc - Dokumentation

• @version -Tag kennzeichnet Version– @version 1.01beta

• @param-Tag– Erklärung für Parameter in Methoden und Konstruktorendeklarationen:– @param Name Name der Person muß übergeben werden

• @return -Tag– Bedeutung des Rückgabeparameters

• @exception -Tag– Erklärung von Ausnahmen in Methoden und Konstruktordeklarationen:– @exception IndexOutOfBoundsException

Die Feldgrenze wird überschritten

• @deprecated -Tag (ab JDK 1.1)– Kennzeichnung veralteter Methoden

242

javadoc-Beispiel/* Copyright (c) 1999 by

* adesso-GmbH.* Dieser Kommentar soll nicht* mit aufgenommen werden*/

/*** Klasse, um Datum zu* erfassen.* @see java.util.Date* @version 0.9*/

public class Datum {private int jahr;private int monat;private int zag;

/*** Datum wird gesetzt.* Es wird deutsche Notation* erwartet.*/

void setzeDatum(String arg){...

}

/*** Wochentag wird berechnet.* Datum wird in deutscher* Notation zurückgegeben.*/

String Wochentag() {...

}}

Kapitel 9

Rekursive Methodennach Doberkat/Dißmann Kapitel 3

244

Struktur dieses Kapitels

Ein paar rekursive Methoden

Rekursives Sortieren am Beispiel Heapsort

Ein paar Überlegungen zur Überführung rekursiver in iterativeMethoden

Page 61: Java

245

Fakultäts-Methode

Die Fakultätsfunktion wird für positive ganzzahlige nfolgendermaßen definiert:

n! = 1, falls n = 1n * (n-1)!, sonst

Das läßt sich unmittelbar in einen Algorithmus umsetzen.

public double Fakultät (int n) { // Methodendeklaration

return ( n = 1 ? 1 : n*Fakultät(n-1));

}

{

246

Rekursive Fakultäts-Methode

Überlegung: Was passiert hier bei der Ausführung?

Beispiel: Fakultät(4)

Es wird der Namensraum für einen Methodenaufrufaufgebaut. Hierin ist der Parameter n = 4 bekannt.Beim Aufruf wird die Operation 4 * Fakultät(3) ausgewertet.

Hierzu wird der Namensraum für einen Methodenaufrufaufgebaut. Hierin ist der Parameter n = 3 bekannt.Beim Aufruf wird die Operation 3 * Fakultät(2) ausgewertet.

247

Rekursive Fakultäts-Methode

Beispiel: Fakultät(4) (Fortsetzung)Es wird der Namensraum für einen Methodenaufrufaufgebaut. Hierin ist der Parameter n = 2 bekannt.Beim Aufruf wird die Operation 2 * Fakultät(1) ausgewertet.

Hierzu wird der Namensraum für einen Methodenaufrufaufgebaut. Hierin ist der Parameter n = 1bekannt.Es wird das Ergebnis 1 zurückgeliefert.

2 * Fakultät(1) wird damit zu 2 * 1, das Ergebnis 2 wirdzurückgeliefert.

248

Rekursive Fakultäts-Methode

Beispiel: Fakultät(4) (Fortsetzung)

3 * Fakultät(2) wird damit zu 3 * 2, das Ergebnis 6 wirdzurückgeliefert.

4 * Fakultät(3) wird damit zu 4 * 6, das Ergebnis 24 wirdzurückgeliefert.

Dieses Beispiel zeigt, daß bei rekursiven Methode der Stapelzur Verwaltung der aktuellen Methodenaufrufe (kurz: Aufruf-

Stack) stark wachsen kann.

Page 62: Java

249

Rekursive Fakultäts-Methode

n=1 1

n=2 2

n=3 6

n=4 24

250

Iterative Fakultäts-Methode

Beispiel: Ausgabe der Fakultäten von 0! bis 10!

class Fakultaetsberechnung {

public static void main(String[] args) {

for (int i=0; i<=20; i++)

System.out.println(rechneFak(i));

}

static double rechneFak(int n) { // Methodendeklaration

double ergebnis = 1;

for (int i=1; i<=n; i++)

ergebnis *= i;

return ergebnis; // Rückgabe

}

}

251

Iterative Fakultäts-Methode

Bei der iterativen Version der Fakultäts-Methode wird nur eineMethode aufgerufen.

Die liefert als Ergebnis den Fakultätswert, ohne daß weitereMethodenaufrufe abgearbeitet werden müssen.

252

Rekursive Fibonacci-Methode

Beispiel: Fibonacci-Zahlen, positive, ganzzahlige Eingabe

public int fib(int n) {

if (n < 3)

return (1);

else

return (fib(n-1) + fib (n-2));

}

Ein Aufruf von fib führt zu zwei weiteren Aufrufen, dabeiwird der Parameter kontinuierlich kleiner.

Wie verhält sich hier der Aufruf-Stack?

Page 63: Java

253

Rekursion

• Ruft eine Anweisung innerhalb einer Methode die eigeneMethode auf, bezeichnet man dies als rekursiven Aufruf .

• Die Methode wird rekursive Methode genannt.• Bei einem rekursiven Aufruf einer Methode erhalten alle lokal

definierten Variablen einen neuen, unabhängigenNamensraum. Für die ausführende Maschine istbedeutungslos, ob es sich um einen rekursiven Aufruf handelt!

• Rekursive Implementierungen sind oft einfacher zu verstehen,als iterative Implementierungen (vgl. Fakultät, Fibonacci).

• Iterative sind hingegen in der Regel performanter.

254

Rekursion

Für die Definition einer rekursiven Methode werden benötigt:• Eine Beschreibung, wie sich der Wert eines »größeren«

Objekts aus den Werten für »kleinere« Objekte ergibt.• Eine Terminierungsbedingung : Ist diese Bedingung erfüllt, so

muß angegeben werden, wie sich der Wert berechnen läßt,ohne noch einmal auf die rekursive Methode zuzugreifen.

• Jeder Aufruf einer rekursiven Methode muß im Verlauf derAuswertung direkt (also im Aufruf selbst) oder indirekt (also imRahmen weiterer rekursiver Aufrufe) dieTerminierungsbedingung erreichen.

255

Rekursive Datenstrukturen

Rekursion ist nicht nur ein wichtiges Hilfsmittel für dieFormulierung von Algorithmen, sondern auch für dieFormulierung von Datenstrukturen.

Beispiele:Eine Liste ist ein Einzelelement gefolgt von einer Liste oder dieleere Liste.Eine Menge ist leer oder eine einelementige Menge vereinigtmit einer Menge.Oder Bäume (dazu im folgenden mehr).

256

Rekursion - Bäume

Nicht-rekursive Definition von Bäumen:

Ein Baum B besteht aus Knoten V und Kanten E, also B = (V,E).Knoten tragen Information, sie sind über Kanten miteinanderverbunden, also E = V x V.

Kanten eines Baumes sind gerichtet, sie sind also ein Paar vonKnoten (v1,v2). In einer Kante e = (v1,v2) wird v1 derVaterknoten und v2 der Sohnknoten von e genannt.

Page 64: Java

257

Rekursion - Bäume

Im Unterschied zu den allgemeineren Graphen sind Bäumehierarchisch, das heißt, es gibt keine zyklischen Verbindungenzwischen Knotenmengen.

∀∀∀∀ e = (v1,v2) ∈∈∈∈ E :¬ ( ∃∃∃∃ i ∈∈∈∈ ΝΝΝΝ, i ≥≥≥≥ 2 ∧∧∧∧ v21, ..., v2i ∈∈∈∈ V | v21 = v2, v2i = v1,

(v21,v22), ..., (v2i,v1) ∈∈∈∈ E)

Ein Binärbaum (auch binärer Baum) ist dann ein Baum, in demjeder Knoten maximal zwei Sohnknoten hat, d.h.

∀∀∀∀ v ∈∈∈∈ V : | { v i ∈∈∈∈ V | (v,v i) ∈∈∈∈ E } | ≤≤≤≤ 2

258

Rekursion - Bäume

Rekursive Definition von binären Bäumen:Die Grundstruktur eines Baumes läßt sich leicht rekursiv

definieren:Ein binärer Baum ist entweder leer oder er hat die folgendeForm:

w

B1 B2wobei w ein Knoten und B1, B2 binäre Bäume sind. Zusätzlichgilt, daß ein binärer Baum nur endlich viele Knoten hat(Terminierungsbedingung!).

259

Rekursion - Bäume

Der Knoten w, mit dem B1 und B2 oben verbunden sind, heißt dieWurzel von B.

B1 und B2 heißen linker bzw. rechter Unterbaum der Wurzel w.

Falls vorhanden, heißen die Wurzeln von B1 und B2 linker bzw.rechter Sohn der Wurzel von B.

Besitzt ein Knoten weder einen linken noch einen rechten Sohn,so wird er als Blatt bezeichnet.

260

Rekursion - Bäume

Blätter auf einer Ebene

Blätter auf mehreren Ebenen

Wurzel

Innere Knoten

Blätter

Page 65: Java

261

Rekursion - Bäume

Ein Blatt ist dadurch ausgezeichnet, daß der linke und der rechteUnterbaum leer sind.

Ein innerer Knoten hat die Eigenschaft, daß der rechte oder derlinke Unterbaum nicht leer ist und daß es sich nicht um die Wurzelhandelt.

Die Wurzel ist dadurch charakterisiert, daß sie kein Sohn einesanderen Knotens ist.

262

Bäume - Formalisierung der rekursiven Def.Der leere Baum wird durch die leere Menge Ø dargestellt, seineKnotenmenge ist leer, also

Knoten(Ø) := Ø .Seien B1 und B2 binäre Bäume, so daß ihre Knotenmengendisjunkt sind, es gilt also

Knoten( B1) ∩∩∩∩ Knoten( B2) = Ø .Sei weiterhin w ein Knoten mit w ∉ Knoten( B1) ∪ Knoten( B2) ,dann heißt

B := ( w, B1, B2)ein binärer Baum mit der Knotenmenge

Knoten( B) := { w} ∪∪∪∪ Knoten( B1) ∪∪∪∪ Knoten( B2) ,der Wurzel w, linkem Unterbaum B1 und rechtem Unterbaum B2.Innere Knoten und Blätter lassen sich in dieser Formulierungebenfalls mathematisch präzise beschreiben.

263

Rekursion - Auf dem Weg zu Heapsort

Problem: Gegeben sei ein Feld a mit n Werten, die sortiertwerden müssen.

Ausgangssituation: Werte im Feld sind unsortiert

Ziel: sortiertes Feld

Idee 1: kleinsten Wert suchen, diesen mit dem ersten Werttauschen, fast immer sehr langsam

Idee 2: benachbarte Werte tauschen, wenn der zweite Wertgrößer ist. Solange bis alles sortiert ist. Langsam, wenn von vornenach hinten durchgetauscht werden muß.

Idee 3: Verwendung eines Binärbaums (Heapsort)264

Rekursion - Auf dem Weg zu Heapsort

Wir verwenden die Zahlen 1 … n zur Numerierung der Knoteneines binären Baums: 1 bildet die Wurzel, und derKnoten i > 1 hat i/2 als Vater, so daß der linke Sohn einesKnotens gerade und der rechte Sohn eines Knotens ungerade ist,sofern der Knoten diese Söhne hat.

Damit können wir ein Feld ebenfalls als Baum darstellen: Ist dasFeld a mit n Komponenten gegeben, so beschriften wir denKnoten i mit dem Feldelement a[i] . Im folgenden Beispielhaben wir das Feld mit denElementen 7, 12 , 0, 5, 9, 1, 3, 8, 13 , 10 , 15 als binärenBaum dargestellt. Die Knoten i werden mit ihrerBeschriftung a[i] angegeben.

Page 66: Java

265

Rekursion - Auf dem Weg zu HeapSort

Knoten 2

Knoten 11Knoten 10Knoten 9Knoten 8

Knoten 7Knoten 6

Knoten 5Knoten 4

Knoten 1

Knoten 3

7

12

5

8 13 10 15

9

0

1 3

266

Rekursion - Auf dem Weg zu Heapsort

Ein Feld genügt der Heap-Bedingungim Knoten i , falls imUnterbaum mit Wurzel i jeder Knoten eine kleinere Beschriftungals seine Söhne trägt.

Die Heap-Bedingung ist in den Knoten 3, 4, 5, 6, 7, 8, 9, 10, 11erfüllt, nicht jedoch im Knoten 2, da

a[2] = 12 , a[4] = 5 und a[5] = 9

aber 12 > 5 und 12 > 9 ,

und auch nicht im Knoten 1, da

a[3] = 0 und 7 > 0 .

267

Lokale Gültigkeit der Heap-Bedingung

Knoten 2

Knoten 11Knoten 10Knoten 9Knoten 8

Knoten 7Knoten 6

Knoten 5Knoten 4

Knoten 1

Knoten 3

7

12

5

8 13 10 15

9

0

1 3

Heap-Bedingung im Teilbaum erfüllt268

Rekursion - Auf dem Weg zu Heapsort

Die Heap-Bedingung kann jedoch im Knoten 2 wie folgthergestellt werden:

Wir vertauschen die Beschriftung im Knoten 2 mit derBeschriftung desjenigen Sohnes, der die kleinereBeschriftung trägt. In diesem Fall handelt es sich um denKnoten 4. Wir nehmen hierzu die kleinere derBeschriftungen der Söhne, damit im Knoten 2 die Heap-Bedingung lokal erfüllt ist: Die Beschriftung des Knotens 2ist kleiner als die Beschriftungen seiner Söhne (Ergebnisvgl. folgende Folie).

Page 67: Java

269

Rekursion - Auf dem Weg zu Heapsort

Knoten 2

Knoten 11Knoten 10Knoten 9Knoten 8

Knoten 7Knoten 6

Knoten 5Knoten 4

Knoten 1

Knoten 3

7

5

12

8 13 10 15

9

0

1 3

270

Herstellung der lokalen Heap-Bedingung im Knoten 2

Knoten 2

Knoten 11Knoten 10Knoten 9Knoten 8

Knoten 7Knoten 6

Knoten 5Knoten 4

Knoten 1

Knoten 3

7

5

12

8 13 10 15

9

0

1 3

271

Rekursion - Auf dem Weg zu Heapsort

Nun ist zwar die Heap-Bedingung im Knoten 2 lokal hergestellthaben. Als Folge ist sie aber im Knoten 4 verletzt ist!

Die Vertauschung der Beschriftung eines Knotens mit derkleineren Beschriftung eines seiner Söhne, läßt sich an dieserStelle wiederholen, so daß die Beschriftung 12 in ein Blatt, denKnoten 8, wandert.

Trivialerweise ist die Heap-Bedingung in einem Blatt erfüllt, sodaß wir durch das beschriebene Vorgehen schrittweise dafürgesorgt haben, daß die Heap-Bedingung im Knoten 2 hergestelltwurde.

272

Rekursion - Auf dem Weg zu Heapsort

Knoten 2

Knoten 11Knoten 10Knoten 9Knoten 8

Knoten 7Knoten 6

Knoten 5Knoten 4

Knoten 1

Knoten 3

7

5

8

12 13 10 15

9

0

1 3

Page 68: Java

273

Herstellung der Heap-Bedingung im Knoten 2

Knoten 2

Knoten 11Knoten 10Knoten 9Knoten 8

Knoten 7Knoten 6

Knoten 5Knoten 4

Knoten 1

Knoten 3

7

5

8

12 13 10 15

9

0

1 3

274

Rekursion - Auf dem Weg zu Heapsort

Die Heap-Bedingung gilt aber immer noch nicht für denKnoten 1, da die Beschriftungen beider Söhne, der Knoten 2 und3 kleiner sind als die Beschriftung der Wurzel des Baumes.

275

Rekursion - HeapsortDefinition: Das Feld a[1] , …, a[n] heißt ein Heap, falls dieHeap-Bedingung im Knoten 1 erfüllt ist. Hieraus ergibt sichunmittelbar als Konsequenz, daß das kleinste Element in einemHeap immer in der Wurzel, d.h. in a[1] , steht.

Der populäre Sortieralgorithmus Heapsort arbeitet in zweiPhasen:

Es ist ein Feld a mit n Elementen gegeben.

In der ersten Phase wird dieses Feld in einen Heapumgestaltet, d.h. es wird dafür gesorgt, daß derentsprechende binäre Baum die Heap-Bedingung imKnoten 1 erfüllt.

In der zweiten Phase wird aus dem zuvor aufgebautenHeap systematisch ein geordnetes Feld erzeugt.

276

Rekursion - Heapsort1. Heap-Aufbau: Idee: Sei in i die Heap-Bedingung nicht erfüllt (iist also kein Blatt), wohl aber in allen Söhnen. Dann werdenfolgende Vertauschungen vorgenommen:

2*i < n, 2*i + 1 > n :vertausche a[i] mit a[2*i] . Da i nur einen Sohn hat,ist die Heap-Bedingung in diesem Knoten erfüllt.

2*i < n, 2*i + 1 < n : suche den Sohn k ,

k ∈∈∈∈ {2i, 2i+1} , so daß gilt:a[k] = min {a[2*i], a[2*i + 1]} ,vertausche a[i] mit a[k] und wende rekursiv dieseIdee auf k an.

Page 69: Java

277

Rekursion - HeapsortDies führt zum Algorithmus Heapify , der rückwärtsgehend fürjeden Knoten k = n/2 , …, 1 die Heap-Bedingung erfüllt.

Rückwärtslaufen ist nötig, denn der Algorithmus sorgt dafür, daßaus kleineren Heaps größere aufgebaut werden.

Wenn wir in einem Knoten sind, dessen Unterbäume beide dieHeapbedingung erfüllen, so wird durch die Bewegung desKnotenelements ja lediglich einer der Unterbäume modifiziert, derandere Unterbaum bleibt in diesem Durchlauf unverändert.

278

Rekursion - HeapsortDie Methode Heapify bekommt als Eingabe denKnoten dieserKnoten und die aktuelle heapGröße desFeldes.

Im ersten Schritt werden zunächst der linke und der rechte Sohnbestimmt. Danach findet eine Fallunterscheidung statt. Dabei wirduntersucht, ob der linke Knoten noch im Feld und der rechteKnoten nicht mehr im Feld liegt: In diesem Fall muß lediglichgetestet werden, ob die Beschriftung des Knotens größer ist alsdie Beschriftung seines einzigen Sohnes.

279

Rekursion - HeapsortDer zweite Fall besteht darin, daß auch der rechte Knoten nochim Feld liegt: In diesem Fall muß der Knoten mit der kleinerenBeschriftung herausgesucht werden und die Beschriftung diesesKnotens mit der Beschriftung des eingegebenen Knotensverglichen werden. Falls es sich hierbei herausstellt, daß dieHeap-Bedingung verletzt ist, wird mit Hilfe der elementarenMethode Tausche der Inhalt dieses Knotens mit dem seinesSohnes vertauscht und Heapify mit dem Sohn und derHeapgröße erneut aufgerufen.

280

Rekursion - Heapsortvoid Heapify(int dieserKnoten, int heapGröße) {

int links = 2 * dieserKnoten,rechts = links + 1,derSohn;

if (links <= heapGröße && rechts > heapGröße) {if (a[dieserKnoten] > a[links])

Tausche(dieserKnoten, links);} else if (rechts <= heapGröße) {

derSohn = (a[links] < a[rechts] ? links :rechts);

if (a[derSohn] < a[dieserKnoten]) {Tausche(dieserKnoten, derSohn);Heapify(derSohn, heapGröße);

}}}

Page 70: Java

281

Rekursion - HeapSortNachdem Heapify in der beschriebenen Art aufgerufen wordenist, stellt das Feld a einen Heap dar, der jetzt dazu herangezogenwerden kann, das Feld zu sortieren.

Wir hatten gerade festgestellt, daß das kleinste Element in derWurzel liegt. Also vertauschen wir zunächst a[1] mit a[n] .

Damit haben wir bereits ein Element des Feldes, das kleinste,sortiert. Um das zweitkleinste Element zu bestimmen, sorgen wirnun dafür, daß die restlichen n-1 Elemente wieder einen Heapbilden.

Anschließend können wir dessen Wurzel und a[n-1] miteinander vertauschen und haben bereits zwei Elementedes Feldes sortiert, und so geht es weiter, bis alle Elementesortiert sind. 282

Rekursion - HeapSort

Auf der folgenden Folie wird dieser erste Sortierschritt an einemBeispiel gezeigt.

Die übernächste Folie demonstriert dann die nächsten beidenSortierschritte, nach deren Ausführung bereits die drei letztenElemente des Feldes sortiert sind, so daß nun nur noch n-3 Elemente betrachtet werden müssen.

Das Feld ist vollständig sortiert, wenn der im nächstenSortierschritt noch zu betrachtende Heap nur noch aus der Wurzelbesteht.

283

Sortieren mit einem Heap - erster Sortierschritt

4

9 12 8

Aufgebauter Heap 1

6

74

9 12 1

erster Sortierschritt 8

6

7

bereits sortiert

Austausch

bereits sortiert

8

9 12 1

Reorganisation desHeaps

4

6

7284

Sortieren mit einem Heap - 2. / 3. Sortierschritt

8

9 12 1

Zweiter Sortierschritt 7

6

4 8

9 12 1

Reorganisation desHeaps

6

7

4

8

9 6 1

Dritter Sortierschritt 12

7

4

bereits sortiert

Page 71: Java

285

Rekursion - HeapsortDer Konstruktor für die Klasse Heap allokiert das Feld a.Da a[0] nicht benutzt wird, benötigen wir ein Feld mitk+1 Elementen, um k Zahlen zu speichern.

Die Initialisierung von a passiert über die Methode Setze .

Neben der bereits bekannten, privaten Methode Heapify werdendie parameterlosen Methoden BaueHeap und Sortiereimplementiert. Zusammen realisieren sie den AlgorithmusHeapsort.

286

Rekursion - HeapSortDer Aufbau eines ersten Heaps aus einem gegebenen Felderfolgt durch den Aufruf der Methode BaueHeap.

Da jedes Blatt des Baumes für sich bereits einen Heap bildet,beginnen wir in der Mitte des Feldes mit dem Aufrufvon Heapify und bauen so immer größere Heaps auf.

Anschließend führt die Methode Sortiere das bereitsvorgestellte Vorgehen mit Vertauschen und Reorganisieren durch.

Das Auslesen eines sortierten Feldes kann durch die mehrfacheAusführung der Methode Gib erfolgen

287

Rekursion - Klasse Heapclass Heap {

private int[] a;

Heap(int k) {a = new int[k+1];

}

void Setze(int i, int x) { a[i] = x; }

int Gib(int i) { return a[i]; }

private void Tausche(int eins, int zwei) {int t = a[eins];a[eins] = a[zwei];a[zwei] = t;

} 288

Rekursion - Auf dem Weg zu Heapsortprivate void Heapify(int dieserKnoten, int heapGröße)

{ wie vorne definiert }

void BaueHeap() {for (int i = (a.length-1)/2; i >= 1; i--)

Heapify(i, a.length-1);}

void Sortiere() {BaueHeap();for (int i = a.length-1; i > 1; i--) {

Tausche(1, i);Heapify(1, i-1);

}}

Page 72: Java

289

Klassifikation rekursiver Methoden

Definition:

Eine rekursive Methode heißt linear , wenn in den einzelnen

Zweigen der bedingten Anweisung, die die rekursiven Aufrufesteuert, jeweils höchstens ein Aufruf der Methode vorkommt.

Beispiele:

Die Methode Fakultät ist linear.

Die Methode Heapify ist linear.

Die Methode Fibonacci ist nicht linear.

290

Klassifikation rekursiver Methoden

Definition:

Eine lineare rekursive Methode heißt schlicht, wenn lediglich

der Wert eines früheren Aufrufs übertragen eingeht.

Beispiele:int F(int x, int y)) {

int t = 0;if (y == 0)

t = x;else if (y > 0)

t = F(x * y, y - 1);return t;

Fakultät ist nicht schlicht, denn es wird nachdem Aufruf noch multipliziert.

291

Klassifikation rekursiver Methoden

Eine systematische Transformation schlichter rekursiverMethoden in nicht-rekursive Methoden ist auf einfache Weisemöglich. Wir erläutern dies zunächst an einem Beispiel.

Beispiel:Sei F gegeben wie oben definiert. Wir berechnen F(a, 3)schrittweise:

F (a, 3) = F (a*3, 2)= F (a*3*2, 1)= F (a*3*2*1, 0)= a*3*2*1

292

Klassifikation rekursiver Methoden

Behauptung:∀∀∀∀ n ≥≥≥≥ 0 gilt F (x, n) = x * n! .

Beweis (durch vollständige Induktion):

Induktionsverankerung n = 0:F (x, 0) = x = x * 0!

Induktionsschritt: Induktionsvoraussetzung ist:

F (x, n) = x * n! ∀∀∀∀ x ∈∈∈∈ N0

Wir wollen zeigen: ∀∀∀∀ x ∈∈∈∈ N0 : F (x, n+1) = x*(n+1)!

F(x, n+1) = F (x*(n+1), n) = x*(n+1)* n! = x*(n+1)!

Induktionsvoraussetzung

Page 73: Java

293

Klassifikation rekursiver MethodenDies führt zu einer nicht-rekursiven Lösung. Das erste Argumentwird als eine Art Akkumulator eingesetzt wird: Die Resultatewerden im ersten Argument so lange angesammelt, bis y denWert 0 erreicht hat. Dann werden sie ausgegeben.

int Iterativf (int x, int y) {int x1 = x, y1 = y, tx, ty;while (y1 > 0) {

tx = x1 * y1;ty = y1 - 1;x1 = tx;y1 = ty;

}return x1;

294

Klassifikation rekursiver Methoden

Beh.: F(x,y) = Iterativf(x, y)

Beweis (durch vollständige Induktion nach y):

Induktionsverankerung: Für y=0 : Iteratif (x,y) = x = x * 0! = F(x, y).

Induktionsschritt: Die Behauptung gelte für ein y ∈ N0. Wir müssenihre Gültigkeit für y+1 nachweisen. Es muß also gezeigt werden,daß nach x1 = x;

y1 = y+1;while(y1 > 0) { …}

von Iterativf der Wert F(x, y+1) geliefert wird.

295

Klassifikation rekursiver MethodenDie Schleife kann, da y+1 > 0, umformuliert werden zu:

tx = x1 * y1;ty = y1 - 1 ; // 1x1 = tx;y1 = ty; // 2while(y1 > 0) {…}

296

Klassifikation rekursiver MethodenIn // 1 gilt: x1 = x; y1 = y + 1;

also: tx = x * (y + 1); ty = y;

Daraus erhält man in // 2 (durch Einsetzen):

x1 = x * (y + 1); y1 = y;

Mit diesen Anfangswerten wird die Bedingungsschleife betreten,nach Induktionsvoraussetzung liefert Iterativf dann den Wert

F(x * (y+1), y)= x * (y+1) * y! = x*(y+1)! = F(x , y + 1)

was zu zeigen war.

Page 74: Java

297

Klassifikation rekursiver MethodenVerallgemeinerung der Umformulierung der Schleife:

Ist P(x) eine Aussage über x und sind I 1(x), I 2(x)Anweisungen, so daß I 2(x) den Wert von x ändert, so sind diebeiden folgenden Code-Fragmente gleichwertig.

if(P(x)){I 2(x);

}while(P(x)){

I 2(x);}I 1(x);

while(P(x)){I 2(x);

}I 1(x);

298

Verallgemeinerung dieses VorgehensGegeben sei die schlicht rekursive Methode:

int F(int x, int y) {

… // Deklarationen ausgelassen

return (y > 0 ? F( µµµµ(x, y), y-1) : νννν(x));}

299

Verallgemeinerung dieses VorgehensHier hängen die Funktionen νννν und µµµµ weder direkt noch indirektvon F ab. Die Methode F wird analog zum vorhergehendenBeispiel transformiert in:

int Iterativf (int x, int y) {// ohne Deklarationenx1 = x; y1 = y;while (y1 > 0) {

tx = µµµµ(x1, y1); ty = y1 -1;x1 = tx; y1 = ty;

}return νννν(x1);

}

300

Verallgemeinerung dieses Vorgehens

Derselbe Beweis, den wir gerade für die Fakultätsfunktiondurchgeführt haben, zeigt, daß die rekursive Methode F und dieiterative Methode Iterativf äquivalent in dem obenbesprochenen Sinne sind.

Wir merken abschließend an, daß die Verallgemeinerung auf mehrals zwei Argumente leicht möglich ist.

Page 75: Java

Kapitel 10

Verschachtelte Klassen (nested classes) /Innere Klassen (inner classes)

302

Verschachtelte Klassen

Definition: Eine verschachtelte Klasse (nested class) ist eineKlasse, die Mitglied einer anderen Klasse ist. Wenn sie staticist, dann spricht man von einer static verschachtelten Klasse.Non-static verschachtelte Klassen heißen auch innere Klassen(inner class).

Man verwendet verschachtelte Klassen, um die Beziehungenzwischen Klassen zu veranschaulichen. Man sollte eine Klasseals verschachtelte Klasse einer umgebenden Klassedefinieren, wenn sie nur in dieser Umgebung Sinn macht odersogar auf die Funktionalität der umgebenden Klasseangewiesen ist.

Beispiel: Textcursor-Klasse in Textverarbeitungsklasse

303

Verschachtelte Klassen

„As a member of its enclosing class, a nested class has a specialprivilege: It has unlimited access to itsenclosing class's members, even if they are declared private.

However, this special privilege isn't reallyspecial at all. It is fully consistent with the meaning of private

and the other access specifiers. The accessspecifiers restrict access to members for classes outside of the

enclosing class. The nested class is insideof its enclosing class so that it has access to its enclosing

class's members.“

(aus dem Java Tutorial)

304

Verschachtelte Klassen

Verschachtelte Klassen können als static definiert werden, dannheißen sie static nested classes . Eine non-staticverschachtelte Klassen heißt inner class.

class EnclosingClass{

. . .

static class AStaticNestedClass {...}

class InnerClass {...}

}

Page 76: Java

305

Verschachtelte Klassen

Wie für static Methoden und Variablen üblich gilt:„... a static nested class is associated with its enclosing class.And like class methods, a static nested class cannot referdirectly to instance variables or methods defined in itsenclosing class-it can use them only through an objectreference.“ (Java Tutorial)

„As with instance methods and variables, an inner class isassociated with an instance of its enclosing classand has direct access to that object's instance variables and

methods. Also, because an inner class isassociated with an instance, it cannot define any static

members itself.“ (Java Tutorial) 306

Verschachtelte Klassen

Zur Unterscheidung:„nested class“ reflektiert die syntaktische Beziehung zwischenKlassen (der Code einer Klasse erscheint im Code eineranderen).

„inner class“ reflektiert die Beziehungen zwischen Objekten derKlassen.

307

Verschachtelte Klassen

• Verschachtelte Klassen dienen dazu, Klassen die nur lokalbenötigt werden, im lokalen Rahmen zu definieren.

• Zweck der Verwendung verschachtelter Klassen ist es,größtmögliche Übersicht zu gewährleisten.

• Es gibt insgesamt 4 Arten von verschachtelten Klassen:• static verschachtelte Klassen• innere Klassen• lokale Klassen (local classes)• anonyme Klassen (anonymous classes)

308

Innere Klassen

class EnclosingClass {

. . .

class InnerClass { . . . }

}

Ein Objekt der Klasse InnerClass kann nur im Rahmen einesObjektes der Klasse EnclosingClass existieren. Es hatdirekten Zugriff auf Instanzvariablen und Methoden desumgebenden Objekts.

Page 77: Java

309

Innere Klassen

Innere Klassen sind die wichtigste Anwendung verschachtelterKlassen!

Innere Klassen werden oft im Sinne von Adaptern verwendet.Soll beispielsweise eine beliebige Struktur von Elementen in der

Lage sein, einem Aufrufer bestimmte Information über dieWerte der Struktur zu übermitteln, so kann eine innere Klassein der Rolle des Adapters dazu dienen, sich auf den Aufrufereinzustellen.

Eine solche Klasse ist außerhalb der Struktur (für dieInformationen über die Werte geliefert werden) bedeutungslosund deshalb eine innere Klasse zu der eigentlichen die Strukturrealisierenden Klasse.

310

Innere Klassen

Beispiel Stapel:Die Elemente eines Stapels sollen für externe Anfrageraufgezählt werden. Diese Anforderung soll nicht mit dereigentlichen Stapelfunktionalität vermischt werden.

Als zusätzliche Methoden werden identifiziert:public boolean hasMoreElements();

public Object nextElement();

Eine Bereitstellung in Form einer inneren Klasse ist nötig, wenndie Aufzählung mehrfach simultan aufgerufen werden soll oderwenn in verschiedenen Aufzählungen unterschiedlich reagiertwerden soll.

311

Innere Klassen

Diese innere Klasse muß Zugriff auf die Stapelelemente habenund das unabhängig von den Stapelzugriffsmethoden.

public class Stack {

private Vector items;

//code for Stack-Methoden ausgelassen

class StackEnum { ...

public boolean hasMoreElements()

{ ... }

public Object nextElement() { ... }

}

} Hinweis: Die StackEnum Klasse benutzt direkt dieInstanzvariablen von Stack-Objekten.

312

Lokale Klassen

• Sie befinden sich innerhalb eines Code-Blocks und verhaltensich wie verschachtelte Klassen.

• Sie sind nur sichtbar innerhalb des Blocks, in dem sie definiertsind.

• Sie werden benutzt, wenn die Klasse nur innerhalb einesCode-Blocks gebraucht wird.

• Für einmalige Anwendung, die keine Konstruktoren erfordert,sind anonyme Klassen geeigneter.

Page 78: Java

313

Anonyme Klassen

Anonyme Klassen

Im vorherigen Beispiel hat der Klassenname StackEnum nichtszum Verständnis des Programms beigetragen. Es gibt dieMöglichkeit, innere Klassen ohne Namen zu definieren. Wirsprechen dann von anonymen Klassen.

Hinweis: Anonyme Klassen sollten nur verwendet werden, wennes um Klassen geht, die ganz sicher nur einen Zweck habenund die maximal zwei Methoden haben. Alles andere gefährdetdie Lesbarkeit des Codes.

314

Anonyme Klassen

• Anonyme Klassen sind lokale Klassen ohne Namen• Das bedeutet: man kann sie in einem Schritt definieren und

benutzen• Syntax: new NameOberklasse() {

// zusätzliche Attribute und Methoden}

• Sie haben keinen Konstruktor• Sie sind praktisch, wenn eine Klasse nur ein einziges Mal

gebraucht wird

Kapitel 11

Elementare Java-Klassen11.1 String11.2 Felder11.3 Object

Kapitel 11.1

String

Page 79: Java

317

Klasse String

• Zeichenketten werden durch Objekte der Klasse Stringdargestellt. Wir hatten schon gesehen, daß String keinprimitiver Typ, sondern eine vordefinierte Klasse ist!

• String ist eine besondere Klasse, da Literale (konstanteZeichenketten) und Operatoren (+ zur Konkatenation) definiertsind.

• In enger Verbindung mit der Klasse String steht die KlasseStringBuffer.

318

Klasse String

Warum zwei String Klassen?„The Java development environment provides two classes thatstore and manipulate character data:String, for constant strings, and StringBuffer, for strings thatcan change.

You use Strings when you don't want the value of the string tochange. For example, if you write a method that requires stringdata and the method is not going to modify the string in anyway, use a String object. Typically, you'll want to use Strings topass character data into methods and return characterdata from methods.

319

Klasse String

Because they are constants, Strings are typically cheaper thanStringBuffers and they can be shared.

So it's important to use Strings when they're appropriate.“

(aus dem Java Tutorial)

320

Methoden der Klasse String (Ausschnitt)

Konstruktoren:• public String(char chars[])

– Konvertiert Array von Zeichen in einen String

• public String(byte bytes[])

– Konvertiert Array von Bytes in einen String– Plattformspezifische Zeicheninterpretation wird benutzt

• public String(StringBuffer buffer)

– Konvertiert StringBuffer nach String

Beispiel:char[ ] c = {'S', 'c', 'h', 'u', 'l', 'z', 'e'};

Strin g s = new String(c);

System.out.println(s);

Page 80: Java

321

String-Objekte Elementare Java-Klassen

• Objekte für den Umgang mit Zeichenketten

→ Aufruf von Methoden für Erzeugen, Aneinanderhängen, Längenmessung,Vergleich, ...

• Erzeugen

String vorname= new String ("Max")

String nachname= "Mustermann" (Kurz-Form mit Literal)

• Messen der Länge

int laenge= name.length() →→→→ 14

• Aneinanderhängen (Konkatenation)

String name = vorname + nachname (neues String-Objekt)

322

String-Konkatenation

• Der +-Operator kann verwendet werden, um zwei Objekte derKlasse String zu verknüpfen

• Ist nur einer der Operanden ein Objekt der Klasse String, undein anderer ein primitiver Datentyp, wird letzterer nach Stringgewandelt

Beispiel:int alter = 27;

System.out.println("Alter : " + alte r + " Jahre");

Ausgabe:Alter: 27 Jahre

323

String-Objekte Elementare Java-Klassen

Vergleichen (mit anderem Objekt):

public boolean equals(Object anObject)– Vergleicht String mit einem anderen Object auf Gleichheit– Typ Object heißt, daß Objekte aller Klassen als Argument übergeben

werden dürfen (später mehr)– Operator "==" vergleicht nur, ob die Referenz identisch ist, also ob es

sich um dasselbe Objekt handelt, und nicht, ob es inhaltlich identisch ist•

String vorname2= "Max"

boolean istGleich = vorname.equals(vorname2) →→→→ true

– Achtung: == vergleicht Referenzen beider Seiten miteinander!boolean istGleicheReferenz = (vorname == vorname2) →→→→

false324

Methoden der Klasse String (Ausschnitt)

Beispiel :String s1 = "Test", s2=s1;

String s3="Te", s4="st", s5;

s5 = s3 + s4;

System.out.println((s1 == s2 ) + " / " + s1.equals(s2));

System.out.println((s1 == s3 ) + " / " + s1.equals(s3));

System.out.println((s1 == s5 ) + " / " + s1.equals(s5));

Ausgabe:true / true

false / false

false / true

Page 81: Java

325

Methoden der Klasse String (Ausschnitt)

• public int length()– Gibt Länge des Strings zurück

• public byte[] getBytes()

– Konvertiert String in Array von Bytes– Plattformspezifische Zeicheninterpretation wird benutzt

• public int compareTo(String anotherString)– vergleicht zwei Zeichenketten lexikographisch basierend auf Unicode-

Nummern (Telefonbuchordnung)– Ergebnis ist gleich 0, falls Strings identisch sind,– kleiner 0, falls der String lexikographisch kleiner ist, als das Argument,– größer 0, falls der String lexikographisch größer ist, als das Argument

326

Methoden der Klasse String (Ausschnitt)

• public String toLowerCase()

• public String toUpperCase()

– Wandelt String in Kleinbuchstaben bzw. Großbuchstaben– Funktioniert auch mit deutschen Umlauten– "ß" wird bei toUpperCase nach "SS" gewandelt, Rückwandlung

funktioniert hier natürlich nicht

Beispiel: Ausgabe:Strin g a = "Schoßhündchen"

System.out.println(a.toLowerCase()); schoßhündchen

System.out.println(a.toUpperCase()); SCHOSSHÜNDCHEN

System.out.println(a.toUpperCase() schosshündchen

.toLowerCase());

327

String und StringBuffer

• String ist nur geeignet, um nicht änderbare Zeichenketten zuverarbeiten, denn z.B. bei Stringkonkatenation durch "+" wirdein neues Objekt erzeugt und die kompletten alten Inhaltekopiert.

• Müssen in eine Zeichenkette laufend kleine Teilzeichenkettenangefügt werden, so ist StringBuffer besser geeignet

328

Methoden der Klasse StringBuffer (Ausschnitt)

• StringBuffer hat ein initiales Fassungsvermögen

• Wird mehr benötigt, wird es automatisch erweitert• Bei anfänglicher realistischer Voreinschätzung der benötigten

Länge läßt sich die Effizienz steigern

Konstruktoren:• public StringBuffer()

– Erzeugt Leerstring mit initialem Fassungsvermögen von 16 Zeichen

• public StringBuffer(int length)

– Erzeugt Leerstring mit spezifiziertem initialen Fassungsvermögen

• public StringBuffer(String str)– Initialisiert StringBuffer mit vorgegebenem String .

Page 82: Java

329

Methoden der Klasse StringBuffer (Ausschnitt)

• public StringBuffer append(String str)

– Hängt eine Zeichenkette an den String an– Fassungsvermögen wird dynamisch an die benötigten Gegebenheiten

angepaßt

• public int length()– Gibt die Länge der aktuellen Zeichenkette zurück (nicht des aktuellen

Fassungsvermögens)

• public String toString()– Wandlung in eine Zeichenkette vom Typ String

330

Methoden der Klasse StringBuffer (Ausschnitt)

Einfügen von Zeichen in StringBuffer-Objekte:StringBuffer sb = new StringBuffer("Drink Java!");

sb.insert(6, "Hot ");

System.out.println(sb.toString());

Ergebnis: Drink Hot Java!

Ersetzen von Zeichen an bestimmten Positionen:setCharAt ersetzt ein Zeichen an einer bestimmten Positioninnerhalb des StringBuffer-Objektes.

331

Methoden der Klasse StringBuffer (Ausschnitt)

Anhängen am Ende eines StringBuffer-Objekts:

StringBuffer sb = new StringBuffer("Drink Hot");

sb.append("!");

System.out.println(sb.toString());

Ergebnis: Drink Hot!

332

Methoden der Klasse StringBuffer (Ausschnitt)

Reversieren eines StringBuffer-Objektes:class ReverseString {

public static String reverseIt(Stringsource) {

int i, len = source.length();

StringBuffer dest = new StringBuffer(len);

for (i = (len - 1); i >= 0; i--) {

dest.append(source.charAt(i));

}

return dest.toString();

}

}

Page 83: Java

333

Methoden der Klasse StringBuffer (Ausschnitt)

Erläuterung zum Reversieren:Die Anweisung StringBuffer dest legt fest, daß ein

StringBuffer-Objekt verwendet werden soll.

Hierfür wird Speicherplatz allokiert.

StringBuffer(len) initialisiert das Objekt.

Durch das Anhängen eines Zeichens an ein StrinBuffer-Objektkann prinzipiell neue Speicherallokation nötig sein. Dies istteuer. Deshalb wird im Reversieren ein passend langesStringBuffer-Objekt auf einmal allokiert.

334

Übung: String, Referenzen

Motivation• Benutzen von Zeichenketten• Übergabe von Referenzen statt kompletter Parameter-Objekte

Aufgabe• Jedes Girokonto soll einen eigenen Konten-Inhaber bekommen. Entwerfen

und implementieren Sie eine neue Klasse "Person“:– Attribute: Vorname, Nachname, Strasse, Postleitzahl (plz) und Ort vom Typ String– Methoden:

void setzeName : Setzen von Vorname und Nachnamevoid setzeAdresse : Setzen von Strasse, PLZ, OrtString holeInhaber : Rückgabe aller aneinanderfügten Attribute

• ...

Elementare Java-Klassen

335

Übung: String, Referenzen

Aufgabe (Forts.)

• Testen Sie nun die Klasse "Person" (vgl. Klasse "TestGirokonto").– Was kann/sollte man testen?

– Testen Sie auch folgendes: Erzeugen Sie zwei Konten und eine Person, setzendiese für beide Konten als Inhaber. Ändern Sie ein Attribut dieser Person undgeben Sie danach für beide Konten den Inhaber aus. Was fällt Ihnen auf?

Elementare Java-Klassen

336

Übung: String, Referenzen

Lösung 1:

public class Person {

private String vorname, nachname, strasse, plz, ort;

public Person(String vorname, String nachname, String strasse,String plz, String ort) {

setzeName(vorname, nachname);

setzeAdresse(strasse, plz, ort);

}

public void setzeName (String vorname, String nachname){

this.vorname=vorname;

this.nachname=nachname;

}

Elementare Java-Klassen

Page 84: Java

337

Übung: String, Referenzen

...

public void setzeAdresse(String strasse, String plz, Stringort){

this.strasse=strasse;

this.plz=plz;

this.ort=ort;

}

public String holeInhaber(){

return (this.vorname+" "+this.nachname+", "+this.strasse+", "+this.plz+" "+this.ort);

}

}

Elementare Java-Klassen

338

Übung: String, ReferenzenLösung:

public class Test2 {

public static void main(String[] args) {

Waehrungsrechner wr = new Waehrungsrechner();

Person herrMeyer = new Person ("Martin", "Meyer",

"Saarstrasse 11", "D-44227", "Dortmund");

Girokonto konto1 = new Girokonto (herrMeyer, wr, 100);

Girokonto konto2 = new Girokonto (herrMeyer, wr, 200);

Bildschirm.gibAus(konto1.holeInhaber() );

Bildschirm.gibAus(konto2.holeInhaber() );herrMeyer.setzeAdresse("Moselgasse 5", "D-44223",

“Dortmund");

Bildschirm.gibAus(konto1.holeInhaber() );

Bildschirm. gibAus ( konto2.holeInhaber () );

Elementare Java-Klassen

Kapitel 11.2

Felder

340

Felder

arrayA collection of data items, all of the same type, inwhich each item's position is uniquely designated by aninteger.

Elementare Java-Klassen

Page 85: Java

341

Felder

• Objekte für den Umgang mit Folgen von Objekten

Girokonto[] Konten;...Konten = new Girokonto[100];...

• belegen der Feldplätze– Index beginnt bei 0

konten[0]=... ;konten[1]=... ;

• zugreifen auf ein einzelnes Feld-Objekt (mittels Index)

konten[2] ergibt das Girokonto-Objekt auf dem 3. Platz des Felds

Elementare Java-Klassen

Typ feldname[]oder: Typ[] feldname

Beim Erzeugen wird dieFeldgröße mitgegeben

342

Eindimensionale Felder

• Deklaration:Typ [] Feldname ;

(alternativ: Typ Feldname []; )

• Initialisierung:Feldname = new Typ [ Feldgröße ];

• Initialisierung mit Werten:Feldname = new Typ []{Konst1, Konst2, ...,Konstn};

• Deklaration und Initialisierung:Typ [] Feldname = new Typ [ Feldgröße ];

Typ [] Feldname = { Konst1 , Konst2 ... };

343

Eindimensionale Felder

• Zugriff auf Feldelemente:Feldname [ Nummer];Nummer ist eine Zahl vom Typ int zwischen 0 und Feldgröße-1

• Zugriff auf Feldlänge:Feldname .length

• Typ kann ein primitiver Datentyp oder auch eine Klasse sein

• Es können mehrere Referenzen auf ein Array zeigen

344

Anwendung: Sortieren durch EinfügenProblem: Eine unsortierte Folge von Zahlen soll geordnet werden.Dazu sollen die Zahlen zunächst in einemFeld int[] zahlen abgelegt werden, das anschließend aufsteigendsortiert werden soll.

Idee: Sind für einen Indexwert i bereits dieElemente zahlen[0], …, zahlen[i-1] aufsteigend sortiert, so sucheman im bereits sortierten Bereich die Position k, ander zahlen[i] eingefügt werden kann, verschiebe zahlen[k], …,zahlen[i-1] um genau eine Position weiter auf die Elementezahlen[k+1], …, zahlen[i] und setze zahlen[k] = zahlen[i].

Page 86: Java

345

Anwendung: SortierenBei der Bestimmung von k sind die folgenden Fälle zuberücksichtigen:

• Alle Werte im sortierten Bereich sind kleiner als dereinzusortierende Wert, d.h. zahlen[i-1] ≤ zahlen[i]: dannist k = i.

• In allen anderen Fällen: k sei der kleinsteIndex t, t ∈ {1, …, i-1}, für den gilt:

zahlen[i] ≤ zahlen[t](Dann gilt also: zahlen[i] ≤ zahlen[k] und zahlen[i] > zahlen[k-1], denn k ist minimal; für zahlen[i] < zahlen[0] gilt: k = 0)

Code für die Bestimmung von k:k = 0;while ((k < i) & (zahlen[i] >= zahlen[k]))

k++; 346

Anwendung: Sortieren

Die Verschiebung erfolgt in folgender Weise:

merker = zahlen[i];zahlen[i] = zahlen[i-1];zahlen[i-1] = zahlen[i-2];

…zahlen[k+1] = zahlen[k];zahlen[k] = merker ;

Code für die Verschiebung:

for (int j = i; j > k; j--)zahlen[j] = zahlen[j-1];

347

Anwendung: Sortieren

Die Analyse dieses Algorithmus zeigt, daß für dasElement zahlen[i] der Test zur Bestimmung der Position desEinfügens, (k<i) & (zahlen[i]>=zahlen[k]), im ungünstigsten Falli–1-mal durchgeführt wird. Dieser Fall liegt dann vor, wenn daseinzufügende Element an das Ende des sortierten Bereichsplaziert wird. Für die gesamte Zahlenfolge ist der ungünstigsteFall daher dann gegeben, wenn eine bereits sortierte Folgevorliegt. Für n Elemente werden dann insgesamt

1 + 2 + … + (n – 1) = n*(n–1)/2

Tests durchgeführt. Für eine lange Zahlenfolge vonbeispielsweise 10 000 Elementen könnte daher der Falleintreten, daß bis zu annähernd 50 Millionen Vergleicheausgewertet werden müssen.

348

int[] zahlen;int merker=0, k=0;

// Einlesen der Elemente …

for (int i = 0; i < zahlen.length; i++) {k = 0;while ((k < i) & (zahlen[i] >= zahlen[k]))

k++;if (k != i) {

merker = zahlen[i];for (int j = i; j > k; j--)

zahlen[j] = zahlen[j-1];zahlen[k] = merker;

}}

// Ausgeben der Elemente …

Page 87: Java

349

public class Sort {public static void main(String[] args) {int[] arrayOfInts = { 32, 87, 3, 589, 12, 1076,

2000, 8, 622, 127 };for (int i = arrayOfInts.length; --i >= 0; ) {

for (int j = 0; j < i; j++) {if (arrayOfInts[j] > arrayOfInts[j+1]) {

int temp = arrayOfInts[j];arrayOfInts[j] = arrayOfInts[j+1];arrayOfInts[j+1] = temp;

} }}for (int i = 0; i < arrayOfInts.length; i++) {

System.out.print(arrayOfInts[i] + " ");}System.out.println();

}}350

Mehrdimensionale Felder• mehrdimensionale Felder möglich

int[][] dreieck;dreieck = {{1}, {2,3}, {4,5,6}};

dreieck[1][0] ergibt 2

• dreieck[1].length liefert die Ausdehnung der zweiten Dimension in derAbhängigkeit von der ersten Dimension, hier also 2, die Anzahl der Spalten derzweiten Zeile (denn die wird durch den Index [1] referenziert.

• Initialisierung eines Feldes möglich (schon bei Deklaration)– muß alle Elemente belegen

int[][] dreieck = {{1}, {2,3}, {4,5,6}}

Elementare Java-Klassen

Typ Feldname = { Konst1, Konst2 ...}

351

Mehrdimensionale Felder

• Deklaration:Typ [][] Feldname ; // zweidimensional

Typ [][][] Feldname ; // dreidimensional

(alternativ: Typ Feldname [][]; )

• Initialisierung:Feldname = new Typ [ Feldgröße1 ][ Feldgröße2 ];

– oder (für nicht notwendigerweise rechteckige Arrays):

Bezeichner = new Typ [ Feldgröße1 ][];

for (int i=0; i< Feldgröße1 ; i++)

Bezeichner [i] = new Typ [ Feldgröße_i ];

352

Mehrdimensionale Felder

• Deklaration mit Initialisierung:Grundtyp [][] Feldname = new Typ [ Feldgr1 ][ Feldgr2 ];

Grundtyp [][] Bezeichner ={{ Konst1 , Konst2 ... },{ ... }, ... };

• Zugriff auf Feldelemente:Bezeichner [ Nummer1][ Nummer2]

• Feldname ist Referenz auf das n-dimensionale Array• Feldname[Nummer] ist Referenz auf ein

(n-1)-dimensionales Teil-Feld• Feldname.length ist die äußere Feldlänge• Feldname[Nummer].length ist die Feldlänge eine Ebene tiefer

Page 88: Java

353

Mehrdimensionale Felder

Beispiel:int abteilungsAnzahl = 4;

int[] abteilungsGröße = {6, 17, 13, 14};

String[][] mitarbeiter = new String[abteilungsAnzahl][];

for (int i=0; i<abteilungsAnzahl; i++)

mitarbeiter[i] = new String[abteilungsGröße[i]];

mitarbeiter[0][0] = "Max Born"; // Abteilung 1

mitarbeiter[0][1] = "Werner Heisenberg";

... (6 Leute)mitarbeiter[1][0] = "Albert Einstein"; // Abteilung 2

mitarbeiter[1][1] = "Nils Bohr";

...

354

Mehrdimensionale Felder

Beispiel: Ausgabe zweidimensionaler Felder

float[][] matrix = new float[4][4];

setupMatrix(mat); // Eingabe der Werte

for (int y=0 ; y < mat.length; y++){

for (int x=0 ; x < mat[y].length; x++)

System.out.print(mat[y][x ] + “ “);

System.out.println();

}

355

Übung: Kartenverwaltung

Motivation• Vertiefen von FOR, IF-ELSE, Array und String

• Aus Anforderungstext zu Programmcode kommen• Motivation für Ausnahmebehandlung erkennenAufgabe

• Entwerfen und implementieren Sie eine Klasse „Kartenverwaltung“, die folgendeTabelle verwaltet:

Elementare Java-Klassen

i kartennr(Array mit 100 String-Obj.)

pins(Array mit 100 String-Obj.)

konten(Array mit 100 Girokonto-Obj.)

0 ´´000´´ ´´A´´ (Zeiger auf ein Konto)

1 ´´111´´ ´´B´´ ´´´´

2 ´´222´´ ´´C´´ ´´´´

...

34 ´´343434´´ ´´Y´´ ´´´´

...

99 ´´9999999´´ ´´YYYY´´ ´´´´

356

Übung: Kartenverwaltung

Vorgehen• Überlegen Sie sich, wie Sie die Tabelle in Java realisieren möchten

(z.B. mehrere Arrays, parallel durchlaufen)• Welche Attribute und Methoden soll die neue Klasse „Kartenverwaltung“

haben?• Wie kann man in der Tabelle eine Zeile lokalisieren zu einem

vorgegebenen Eintrag (z.B. Kartennummer)?• Schreiben Sie den Quellcode der Klasse „Kartenverwaltung“ auf und

beheben Sie ggf. auftauchende Fehler!• Überlegen Sie, auf welche Weise Sie diese neue Klasse testen können und

schreiben Sie den Quellcode für diese Testklasse!

Elementare Java-Klassen

Page 89: Java

357

Übung: Kartenverwaltung

Methoden:• ´´erfasseWeiteresKonto´´ : Eintragen von Konto, Kartennummer und

Pin in eine Tabellenzeile

• ´´holeKonto´´ : Rückgabe des Kontos zu einer übergebenenKartennummer

• ´´pinIstGültig´´ : Rückgabe true falls Kartennummer undPIN zusammengehören

false sonst

Elementare Java-Klassen

358

Übung: Kartenverwaltung (1/4)

public class Kartenverwaltung {

private String[] pins =new String[100];

private String[] kartennr =new String[100];

private Girokonto[] konten=new Girokonto[100];

private int freiIndex; //Feldindex des//frühesten

//unbesetzten Eintrags

public Kartenverwaltung(){

freiIndex=0;

}

// weiter auf nächster Folie

Elementare Java-Klassen

359

Übung: Kartenverwaltung (2/4)

public void erfasseWeiteresKonto (String kartennummer,String pin, Girokonto konto){

kartennr[freiIndex]=kartennummer;

pins[freiIndex]=pin;

konten[freiIndex]=konto;

freiIndex++;

}

Elementare Java-Klassen

360

Übung: Kartenverwaltung (3/4)...

public Girokonto holeKonto (String kartennummer){

Girokonto dasKonto=null;

for (int i=0; i<freiIndex; i++){

if (kartennummer.equals(kartennr[i])){

dasKonto=konten[i];

}

}

return (dasKonto);

}

Elementare Java-Klassen

Page 90: Java

361

Übung: Kartenverwaltung (4/4)

public boolean pinIstGültig (String kartennummer, Stringpin){

int i;

for (i=0; (! kartennummer.equals(kartennr[i])); i++){}

return (pin.equals(pins[i]));

}

}

Elementare Java-Klassen

362

Übung: Test_Kartenverwaltung

public class Test_Kartenverwaltung {

public static void main(String[] args) {

// 1. Erzeuge Waehrunsgrechner, Person und drei Konten

// mit initialen Konständen von 100,200, 300 Pfennigen

Waehrungsrechner wr=new Waehrungsrechner();

Girokonto konto1=new Girokonto(wr, 100);

Girokonto konto2=new Girokonto(wr, 200);

Girokonto konto3=new Girokonto(wr, 300);

// 2. Erzeuge eine Kartenverwaltung und füge dort// die 3 Konten mit PIN ein

Kartenverwaltung kv=new Kartenverwaltung();

kv.erfasseWeiteresKonto("111", "A", konto1);

kv.erfasseWeiteresKonto("222", "B", konto2);

kv.erfasseWeiteresKonto("333", "C", konto3);

Elementare Java-Klassen

363

Übung: Test_Kartenverwaltung

// 3. hole von Kartenverwaltung (OHNE PIN-Prüfung!) die Konten// und gib ihre Kontostande aus

Bildschirm.gibAus("Der Kontostand fuer Kartennummer 1 ist "+kv.holeKonto("111").holeKontostand());

Bildschirm.gibAus("Der Kontostand fuer Kartennummer 2 ist"+kv.holeKonto("222").holeKontostand());

Bildschirm.gibAus("Der Kontostand fuer Kartennummer 3 ist"+kv.holeKonto("333").holeKontostand());

Elementare Java-Klassen

364

Übung: Test_Kartenverwaltung// 4. hole MIT PIN-Prüfung das Konto2, gib Kontostand aus

boolean istAkzeptiert=false;

do {

String eingabePIN=Bildschirm.gibEin("Bitte PIN für fuer Konto 2");

if (kv.pinIstGültig("222", eingabePIN)) {

istAkzeptiert=true;

Bildschirm.gibAus("Die eingegebene PIN ist gueltig.");

Girokonto dasKonto2=kv.holeKonto("222");

Bildschirm.gibAus("Kontostand: "+dasKonto2.holeKontostand());

} else{

Bildschirm.gibAus("Die eingegebene PIN ist nicht gueltig.");

}

} while (!istAkzeptiert);

Bildschirm.warteAufTastendruck();

}

}

Elementare Java-Klassen

Page 91: Java

Kapitel 11.3

Object

366

Die Klasse Object

• Die Klasse Object ist die Oberklasse aller Klassen, und stellteinige Methoden zur Verfügung:

• public String toString()

– Die toString() -Methode gibt eine (etwas kryptische) Wandlung einesObjektes in einen Stringsie sollte von Klassen überdeckt werden

– Die System.out.println -Methode akzeptiert beliebige Objekte alsargument, sie benutzt die (eventuell selbst überschriebene)toString() -Methode

– Strings können mit beliebigen Objekten durch den +-Operator verknüpftwerden. Dazu wird implizit von den Objekten die toString() -Methodeaufgerufen, um die String-Darstellung zu erhalten

367

Die Klasse Object

• public boolean equals(Object obj)

– Das Objekt wird mit dem Argument auf Gleichheit überprüft– In der Standardimplementierung wird nur die Referenz verglichen (also,

ob es sich im dasselbe Objekt handelt)– Eine neue Methode sollte die equals -Methode überdecken, um einen

Inhaltlichen Vergleich zu ermöglichenBeispiel:Für einen Kunden soll abgefragt werden, ob er bereits Kunde ist. Fürden Vergleich spielt der Name, der Geburtsort und das Geburtsdatumeine Rolle, nicht jedoch die Adresse

368

Die Klasse Object

• public Object clone()

– returniert eine wertegleiche Kopie des Objektes.– Hinweis: Wenn in dem zu klonenden Objekt Referenzen auf andere

Objekte (z.B. Arrays) vorkommen, so werden die Referenzen geklont,nicht aber die referenzierten Objekte. Auf diese Weise kommt es zu“shared data”. Ob das beabsichtigt ist, muss sorgfältig geprüft werden.

– Diskussion des Stack-Beispiels

• public final Class getclass()

– returniert das Objekt, das die Klasse des Objektes repräsentiert, dessenMethode aufgerufen wird.

Page 92: Java

Kapitel 12

Ähnliche Objekte (Vererbung)

370

Vererbung

• Klassen können zueinander in einer "ist ein"-Beziehung stehen

• Beispiel: Jeder PKW ist ein Kraftfahrzeug,jedes Kraftfahrzeug ist ein Transportmittel

aber: auch jeder LKW ist ein Kraftfahrzeug und jeder Zug,jedes Schiff und jedes Flugzeug ist ein Transport-mittel

Transportmittel

Kraftfahrzeug Zug Boot Flugzeug

PKW LKW Segelbooot MotorbootVW Golf Opel Astra

371

Vererbung (anschaulich)

• Sowohl PKWs, als auch LKWs besitzen Fahrersitze undFahrertüren, es handelt sich also um Attribute der OberklasseKraftfahrzeug

• Sowohl PKWs als auch LKWs haben die Methoden Sitzverstellen, Tür schließen und fahren, es sind Methoden derOberklasse Kraftfahrzeug

• PKWs haben jedoch mit der Rückbank und dem Kofferraumeigene Attribute und mit "hinten einsteigen" eigene Methoden

• LKWs haben mit der Ladefläche und dem Anhänger aucheigene Attribute und "beladen" ist eine eigene Methode=> Unterklassen PKWs und LKWs besitzen alle Attribute und

Methoden der Oberklasse, haben jedoch noch zusätzliche

372

Ähnlichkeiten bei Objekten

Und bei Konten tritt so was ähnliches natürlich auch auf :-)• Zusammenfassen von gleichen Attributen und Methoden

Vererbung

Girokonto

kontostand : intinhaber : Personhabenzinsen : intsollzinsen : intdispo : int

holeKontostand()zahle()

Sparkonto

kontostand : intinhaber : Personhabenzinsen : int

holeKontostand()zahle()kuendigen()

Festgeld

kontostand : intinhaber : Personhabenzinsen : intmindBetrag : intlaufzeit : int

holeKontostand()zahle()kuendigen()

Page 93: Java

373

Erweiterung des Klassenmodells Vererbung

Konto

kontostand : intinhaber : Personhabenzinsen : int

holeKontostand()zahle()

Girokontosollzinsen : intdispo : int

Festgeldkonto

mindBetrag : intlaufzeit : int

kuendigen()

Sparkonto

kuendigen()

374

Verhältnis zwischen Objekten erbender Klassen

• Die vererbende Klasse heißt Superklasse.• Die erbenden Klassen sind Unter- oder Subklassen.• Konto ist also die Superklasse der Klassen Girokonto,

Festgeldkonto, Sparkonto. Diese sind die Subklassen derKlasse Konto.

375

Verhältnis zwischen Objekten erbender Klassen

Konto

Girokonto

Sparkonto

Festgeldkonto

• Alle Objekte sind Konten!• Einige sind besondere

Arten von Konten.• Die Menge der

Sparkonten, Girokonen,Festgeldkonten istjeweils eine Teilmengeder Menge der Konten

• Die Teilmengen sinddisjunkt.

376

• Wir nehmen folgende Deklarationen an:

Girokonto einGirokonto;

Sparkonto einSparkonto;

Konto einKonto, einAnderesKonto;

• Legale Zuweisungen:

einGirokonto = new Girokonto();

einSparkonto = new Sparkonto();

einGirokonto.sollzinsen = 12;

einKonto = einGirokonto;

einAnderesKonto = new Sparkonto();

Verhältnis zwischen Objekten erbender Klassen

Konto

GirokontoSparkonto

Festgeldkonto

Page 94: Java

377

• Wir nehmen folgende Deklarationen an:

Girokonto einGirokonto;

Sparkonto einSparkonto;

Konto einKonto, einAnderesKonto;

• Nicht legale Zuweisungen:

einSparkonto = einGirokonto;

einGirokonto = new Sparkonto();

Verhältnis zwischen Objekten erbender Klassen

Konto

GirokontoSparkonto

Festgeldkonto

378

Erläuterungen :

Jedes Sparkonto / Girokonto ist auch ein Konto, deshalb isteinKonto = einSparkonto legal.

Ein Objekt der einer Klasse kann also mehrereErscheinungsformen haben, es kann ein Objekt der Klasseselbst sein oder es kann ein Objekt einer der Unterklassendieser Klasse sein. Es ist also polymorph .

Verhältnis zwischen Objekten erbender Klassen

379

Erläuterungen :

Nicht jedes Konto ist ein Sparkonto.Ist dann einSparkonto = einKonto legal?

Ja, denn Objekte der Klasse Sparkonto sind wandelbar zuObjekten der Klasse Konto. Allerdings ist der Zugriff auf alleAttribute nicht möglich, denn einKonto hat ja nicht dieSparkonto-Attribute.

Verhältnis zwischen Objekten erbender Klassen

380

Erläuterungen :Was passiert bei folgender Anweisung?

if (x%2 == 0)

einKonto = einSparkonto;

else

einKonto = einGirokonto;

Der Compiler ist nicht in der Lage, die Klasse von einKonto zuermitteln. Die Klasse von einKonto nach dieser Zuweisung istnicht vorhersehbar. einKonto kann also nach der Anweisungeine von mehreren Klassen haben, es ist halt polymorph.

Verhältnis zwischen Objekten erbender Klassen

Page 95: Java

381

Erläuterungen :

IsteinKonto = (x%2==0 ? einGirokonto : einSparkonto)

erlaubt?

Verhältnis zwischen Objekten erbender Klassen

382

Die Klasse Konto

public class Konto {

private int kontostand = 0;

private Waehrungsrechner wr;

private Person inhaber;

private int habenzinsen;

public Konto (Person inhaber, Waehrungsrechner wr) {

this.inhaber = inhaber;

this.wr = wr;

}

Vererbung

383

Die Klasse Konto

public void zahle (int pfennige) {

int euroCent = wr.wandeleInEuroCent(pfennige);

kontostand += euroCent;

}

public int holeKontostand() {

int pfennige = wr.wandeleInPfennige(kontostand);

return (pfennige);

}

} // Ende der Klasse Konto

Vererbung

384

Die Klasse Girokonto

public class Girokonto extends Konto {

private int sollzinsen;

private int dispo;

} // Ende der Klasse Girokonto

Vererbung

Schlüsselwort: extends

Page 96: Java

385

Vererbung (technisch)

• Vererbung wird über Schüsselwort extends realisiert:

class Unterklasse extends Oberklasse {

... // Hier zusätzliche Attribute und Methoden}

• Die neu definierte Unterklasse erweitert also die anderswodefinierte Oberklasse um neue Attribute und Methoden.

• Alle Methoden und Attribute der Oberklasse werdenübernommen.

386

Vererbung (technisch)

• Jede Klasse hat genau eine Oberklasse (Java kennt keineMehrfachvererbung)

• Ist keine Oberklasse definiert (kein extends ), so ist dieSystemklasse Object die Oberklasse=> Object ist eine Oberklasse für alle Klassen

(bis auf Object selbst)

387

Vererbung (technisch)

• Konstruktoren werden nicht vererbt, Konstruktoren derabgeleiteten Klasse müssen neu definiert werden!

• Über Schlüsselwort super kann am Anfang eines Konstruktorsder abgeleiteten Klasse ein Konstruktor der Oberklasseaufgerufen werden.Beispiel: class A {

A(String name) { ...}

}class B extends A {

B(String name, int a) {super(name); // Aufruf des Oberkl.-... // Konstruktors

}}

388

Vererbung (technisch)

• Wenn in der ersten Anweisung des Subklassen-Konstruktorsnicht einer der Konstruktoren der Superklasse aufgerufen wird,dann wird der parameterlose Superklassen-Konstruktor(Standard-Konstruktor) automatisch aufgerufen, bevorirgendeine andere Anweisung des Subklassen-Konstruktorsaufgerufen wird.

• Die Verwendung von super ist die einzige Situation, in der dieQuelle einer Referenz für die Wahl der auszuführendenMethode / den Zugriff auf ein Attribut verantwortlich ist.

Page 97: Java

389

Zugriffsrecht: protected

• private Methoden und Attribute sind nur in der Klassezugreifbar, in der sie definiert sind. Sie sind nicht in denerbenden Klassen zugreifbar.

• Oft ist es so, daß Methoden und Attribute nicht von außenzugreifbar sein sollen, daß sie aber schon vererbt werdensollen. Genau dies wird durch das Schlüsselwort protectedvereinbart.

Vererbung

390

Zugriffsrecht: protected

• protected Methoden und Attribute sind in der Klasse selbstund in allen Subklassen sichtbar.

Vererbung

Konto

private kontostandprotected habenzinsen

Girokonto

Bankautomat

„habenzinsen“ ist hier unbekannt

„habenzinsen“ ist hier bekannt

erweitert

benutzt

391

Zugriffsrecht: protected

• protected Methoden und Attribute einer Oberklasse Akönnen auch in einer Unterklasse B zur Oberklasse Azugreifbar, d.h. genau:

– sie können benutzt werden über eine Referenz auf ein Objekt derKlasse A oder auf ein Objekt einer Unterklasse der Klasse A.

Vererbung

392

Überschreiben von Methoden in Vererbungshierarchien

• Methode: berechneZinsen (int tage)

• gleiche Implementierung in Sparkonto und Festgeld

• aber: in Girokonto Berechnung aus Sollzinsen und Habenzinsen

• Lösung: Standard-Implementierung in Konto undÜberschreiben in Girokonto

Page 98: Java

393

Überschreiben von Methoden

public class Konto {

...

/**

berechnet für die Anzahl Tage die angefallenen Zinsen

*/

protected int berechneZinsen(int tage) {

Float zinsen =

new Float(kontostand*(habenzinsen/100)*(tage/360));

return (zinsen.intValue());

}

...

}

Vererbung

Wrapper-Klasse: Float

394

Überschreiben von Methoden

public class Girokonto extends Konto {

...

protected int berechneZinsen(int tage) {

int guthaben = holeKontostand();

if (guthaben > 0) {

Float zinsen =new Float(guthaben*(habenzinsen/100)*(tage/360));

return (zinsen.intValue());

} else {

Float zinsen =

new Float(guthaben*(sollzinsen/100)*(tage/360));

return (zinsen.intValue());

}

}

}

Vererbung

395

Zugriff auf überschriebene Attribute / Methoden• In einem Objekt einer abgeleiteten Klasse ist super eine

Referenz auf das Teilobjekt der Oberklasse• Attribute und Methoden der Oberklasse lassen sich so

ansprechen (auch überschriebene Attribute und Methoden)Beispiel:class A { class B extends A {

int variable; int variable; // Überschreibendes Attr.void methode() { void methode() { // Überschreibende Meth.

... ...} }

} void methode2() { // Zugriff aufsuper.variable = 3; // überschriebenesuper.methode(); // Attribute und

} // Methoden der} // Oberklasse

396

Schlüsselwort: final

• Verhindert, daß eine Methode überschrieben wirdpublic final int holeKontostand() {

...

}

• Erben von einer Klasse verbietenpublic final class Girokonto extends Konto {

...

}

Alle Methoden und Attribute einer finalen Klasse sind implizitauch final.

Vererbung

Page 99: Java

397

Schlüsselwort: final

• Finale Klassen und Methoden sind aus Sicherheitsgründenzuweilen erforderlich. Sie tun das, was sie tun sollen undkönnen nicht manipuliert werden. Typische Anweisung: eineMethode zur Passwort-Prüfung.

• final - Attribute sind Konstanten, sie dürfen nicht verändertwerden

public final int mwst;

Vererbung

398

Einschub: Klasse Datum (wird gleich benötigt)

public class Datum {

public Datum(int tag, int monat, int jahr) { ...}

public void setzeDatum(int tag, int monat, int jahr) { ... }

public static Datum aktuellesDatum() { ... }

public boolean istSpaeterAls(Datum dat) { ...}

public boolean istAbgelaufen() { ...}

public boolean istGleich (Datum dat) { ...}

public int gibDifferenz(Datum dat) { ...}

}

399

Abstrakte Methoden/Klassen

• Situation: Jede Subklasse hat die gleiche Methode aberunterschiedliche Implementierung

• Beispiel: auszahlen(int betrag)– Girokonto: beliebige Auszahlung bis Limit– Sparkonto: Restguthaben von DM 5,- nötig (außer nach Kündigung)– Festgeld: Auszahlung erst nach Ende der Laufzeit

• Lösung: abstrakte Methode in der Superklasse. Eineabstrakte Methode ist eine Methode, die nicht realisiert ist.

• Die abstrakte Methode der Superklasse gibt dann nur dieSignatur der Methode an, nicht aber ihre Realisierung.

Vererbung

400

Abstrakte Methoden/Klassen

public abstract class Konto {

protected Datum letzteTransaktion;

...

public void einzahlen(int betrag) {

Datum heute = Datum.aktuellesDatum();

int zinstage = heute.gibDifferenz(letzteTransaktion);int zinsen = berechneZinsen(zinstage);

zahle(betrag+zinsen);

}

public abstract int auszahlen(int betrag);

}

Vererbung

Schlüsselwort: abstractvor Methode und Klasse

Page 100: Java

401

Beispiel: Klasse Girokonto

class Girokonto extends Konto {

...

public int auszahlen(int betrag) {

Datum heute = Datum.aktuellesDatum();

int zinstage = heute.gibDifferenz(letzteTransaktion);

int zinsen = berechneZinsen(zinstage);

zahle(zinsen);

if (kontostand-betrag > dispo) {

zahle(-betrag);

return (betrag);

} else Bildschirm.gibAus(“Kein Auszahlen möglich“);

return (0);

}

}

Vererbung

402

Abstrakte Methoden/Klassen

• Enthält eine Klasse eine abstrakte Methode, so ist die ganzeKlasse abstract

• Eine abstrakte Klasse kann nicht instanziiert werden. D.h., eskönnen keine Objekte zu dieser Klasse erzeugt werden. Eskann nur Objekte zu den nicht abstrakten Unterklassen geben.

• Abstrakte Methoden müssen in den Subklassen implementiertwerden (oder die Subklassen sind wieder abstract)

Vererbung

403

Polymorphie

• Wunsch:Alle Objekte aus der Oberklasse “Konto” sollen in der gleichenWeise behandelt werden können.

• Lösung: PolymorphieEine Oberklassen-Referenz kann auch auf Objekte derSubklassen verweisen.

• Methoden der Oberklasse können so aufgerufen werden.Wurde eine Methode von einer Subklasse überschrieben , sowird nicht die Methodenimplementierung der Oberklasseaufgerufen, sondern die Implementierung der Subklasse.

404

Polymorphie

• Methoden können so mit allen möglichen Konten arbeiten

public int berechneVermoegen(Konto[] konten) {

int vermoegen = 0;

for (int i=0; i<konten.length; i++) {

Kont o k = konten[i];

vermoegen += k.holeKontostand();

}

return (vermoegen);

}

• Methodenaufruf wird an die entsprechende Subklasseweitergeleitet

Vererbung

Page 101: Java

405

Polymorphie (technisch)

• Polymorphie wird bei Vererbung durch Überschreiben derMethoden der Oberklasse erreicht, dabei muß die Signatur(also Parameterliste und Rückgabetyp) mit der Methode derOberklasse übereinstimmen.

• Beim Überschreiben werden die allgemeineren Methoden (derOberklasse) durch die konkreteren der Unterklasseüberschrieben.

406

Polymorphie (technisch)

• Auch wenn ein Objekt durch eine Variable eines allgemeinerenTyps referenziert wird, so werden immer die zum Objektgehörenden Methoden aufgerufen.

• Überschreiben darf nicht mit Überladen verwechselt werden,bei überladenen Methoden hat man unterschiedlicheSignaturen und nur der Methodenname ist der gleiche.

407

Instanceof

• Da jedes Objekt auch über Referenzen der Oberklasseangesprochen werden kann, ist nicht immer klar, zu welcherKlasse ein Objekt gehört. Daher gibt es das Schlüsselwortinstanceof , um die Klassenzugehörigkeit zu bestimmen:

if( Objektname instanceof Klassenname)Anweisung

• Die Abfrage liefert auch dann true , wenn durch Klassennameeine Oberklasse für das zu Objektname zugehörige Objektangegeben wird

408

Übung: Vererbung

Motivation• Vererben von Attributen und Methoden• Überschreiben von Methoden

Aufgabe• Nutzen Sie die Gemeinsamkeiten von Girokonto, Sparkonto und Festgeldkonto in der

gemeinsamen Oberklasse Konto. Implementieren Sie die Klasse Festgeldkonto alsErweiterung der Klasse Konto

– neue Attribute: laufzeit und mindBetrag– neue Methoden:

erweiterter Konstruktor : Übergeben der Laufzeitauszahlen(int betrag) : Auszahlung der Summe nach Ende der Laufzeitkuendigen() : identisch mit auszahlen

• Schreiben Sie eine Testklasse– benutzen Sie die Methode setzeDatum der Klasse Datum, um die letzteTransaktion

zurückzusetzen

Vererbung

Page 102: Java

409

Übung: Vererbung

public class Festgeld extends Konto {

private int laufzeit = 1080; // Laufzeit: 3 Jahre

public static int mindBetrag = 250000;

public Festgeld (Person inhaber, Waehrungsrechner wr,

int initialkontostand) {

super(inhaber, wr, initialkontostand);

if (initialkontostand < mindBetrag) {

Bildschirm.gibAus("Mindest-Betrag wird nichterreicht");

}

}

Vererbung

410

Übung: Vererbung

public Festgeld (Person inhaber, Waehrungsrechner wr) {

super(inhaber, wr);

}

public Festgeld (Person inhaber, Waehrungsrechner wr,

int initialkontostand, int laufzeit) {

super(inhaber, wr, initialkontostand);

this.laufzeit = laufzeit;

if (initialkontostand < mindBetrag) {

Bildschirm.gibAus("Mindest-Betrag wird nichterreicht");

}

}

Vererbung

411

Übung: Vererbung

public void setzeLaufzeit (int neueLaufzeit) {

this.laufzeit = neueLaufzeit;

}

public int kuendigen () {

return (auszahlen(holeKontostand()));

}

Vererbung

412

public int auszahlen (int betrag) {

if (betrag == holeKontostand()) {

Datum heute = Datum.aktuellesDatum();

int abgelaufeneZeit =heute.gibDifferenz(letzteTransaktion);

if (abgelaufeneZeit >= this.laufzeit) {

int zinsen =holeWaehrungsrechner().wandeleInPfennig

(berechneZinsen(laufzeit));

int pfennige = holeKontostand()+zinsen;

zahle(-betrag);

return (pfennige);

} else {

Bildschirm.gibAus("Laufzeit noch nicht errreicht");

}

} else {

Bildschirm.gibAus(“Auszahlung der ges. Summe nötig");

}

}

Page 103: Java

413

Zusammenfassung

• Finden ähnlicher Objekte– Vererbungsbeziehung

• Zugriffsrecht: protected

• Überschreiben von Methoden– Schlüsselwort: final

• Abstrakte Methoden

• Polymorphie

Vererbung

Kapitel 13

Schnittstellen (Interfaces)vgl. Kapitel zu Interfaces aus Ken Arnold, James

Gosling, The Java Programming Language,Second Edition, Addison-Wesley

415

Motivation

• Interfaces sind “Klassen ohne Methodenimplementierungen”.

• Interfaces werden auch Schnittstellen genannt. ImDoberkat/Dißmann-Buch werden sie Abstraktionen genannt.

• Grundlegende Motivation:– Trennung Spezifikation / Realisierung– Ermöglichung von Mehrfacherbung

416

Motivation: Trennung Spezifikation / Realisierung

• Realisierung ist noch nicht bekannt, aber man weiß schon, wasrealisiert werden soll.

• Man will mehrere auch konkurrierende Realisierungenzulassen und dabei sicherstellen, daß gewisse Eigenschaftengewährleistet werden.

• Die grundlegenden Eigenschaften werden durch Signaturenfestgelegt.

• Die Signatur einer Methode legt ihr Eingabe-/Ausgabeverhalten fest, also die Typen der Eingabeparameterund den Rückgabewert.

Page 104: Java

417

Erläuterung SignaturNatSig = (S, F) mit Signatur der Algebra der

natürlichen Zahlen

S={Nat, Bool}F={0Nat, succNat, +Nat, =Nat}

type: F → S* x S0Nat → () x Nat oder 0Nat:() → NatsuccNat → Nat x Nat oder succNat : Nat → Nat

+Nat → Nat x Nat x Nat oder +Nat : Nat x Nat → Nat=Nat → Nat x Nat x Bool oder =Nat : Nat x Nat → Bool

true Bool → () x Bool oder true Bool :() → Bool

false Bool → () x Bool oder false Bool :() → Bool=bool → Bool x Bool x Bool oder =bool : Bool x Bool → Bool1Nat → () x Nat oder 1Nat:() → Nat

418

Motivation: Mehrfacherbung

Mehrfacherbung (multiple inheritance) =eine Klasse besitzt mehrere Oberklassen

Problem: Welche Methode wird bei Namenskonflikten gewählt?

Lösung: In Java nicht möglich!aber: hilfreiches Ersatzkonstrukt verfügbar: Interface

Inventar

Leihwagen

KFZ

419

Interfaces

• Bsp: Lookup und Verwendung der Lookup-Typen

• extends ist das Schlüsselwort für Interfacevererbung:interface Unterinterface extends Oberinterface {

Interfacebody}

• Klassen erben von Interfaces über das Schlüsselwortimplements

• Bsp: SimpleLookup

interface I {Methodendeklarationen;

}

420

Interfaces

• Klassen können von einem oder mehreren Interfaces und auchzusätzlich von einer Oberklasse erben:

class NameUnterklasse extends NameOberklasseimplements Interface1, Interface2, ... {

...}

• Werden von einer Klasse nicht alle Methoden des Interfacesimplementiert, muß sie mit abstract gekennzeichnet werden

• Analog zum Erben von Oberklassen ist Polymorphie möglich

Page 105: Java

421

Interfaces

• Die Supertypen einer Klasse A sind– die Klasse B, von der A erbt,– die Interfaces, die A implementiert,– und die Supertypen, dieser Klasse und Interfaces.

• Alle Interface-Methoden sind implizit public und abstract.– Begründung: public weil alle realisierenden Klassen wissen müssen,

was sie realisieren sollen, abstract weil das das Merkmal vonInterfaces ist.

• Alle Attribute sind implizit public , static und final– Begründung: Es kann nur um Konstanten gehen, die immer gleich

verwendet werden (also final). Diese braucht man dann nicht pro Objekt,sondern nur pro Klasse (also static).

422

Abstrakte Klasse versus Interface

Eine Klasse ist abstrakt, wenn mindestens eine ihrer Methoden abstrakt ist.

Insofern ist ein Interface ein Spezialfall einer abstrakten Klasse. Ein Interfacehat halt ausschließlich abstrakte Methoden.

Der Vorteil im Hinblick auf Mehrfacherbung ist, daß es ohneImplementierungen bezüglich Methoden auch keine Konflikte geben kann.

public interface Konto {public void einzahlen();public void auszahlen();...

}

423

Interface wird durch Klasse implementiert

public class Privatkontoimplements Konto {

public void einzahlen() {...

}public void auszahlen() {

...}

}

modifier class cNameimplements iName {

...}

Interfaces

424

• Interfaces können eigene Vererbungshierarchie bilden• für Interfaces ist Mehrfacherbung erlaubt:

public interface Kontoextends Vertrag, Historisierbar {

public void einzahlen() {...

}public void auszahlen() {

...}

}

interface I extends I1,I2 {Methodendeklarationen;

}

Interfaces

Page 106: Java

425

eine Klasse kann mehrere Interfaces implementieren– alle vorgegebenen Methoden müssen realisiert werden

public class Privatkontoimplements Konto, Zähler {

public void einzahlen() {...

}public void auszahlen() {

...}

public int inkrementiere() {...

}

}

class Cimplements I1,I2 {

...}

Interfaces

426

Mehrfacherbung• Mit Interfaces läßt sich Mehrfacherbung erreichen

– Lösung: Implementierung eines Interfaces

Interface

Klasse B

Klasse C

Klasse A

Klasse A

Klasse C

Interface I

public class SubNameextends SuperNameimplements InterfaceName, ...,InterfaceName {

...

}

427

Interface kann als Typ für eine Referenz dienen, d.h.Interfaces unterstützen polymorphes Verhalten wie Oberklassen.

Girokonto dasGiro = new Girokonto();

Konto kto = dasGiro;

kto.einzahlen(500);

Das durch kto referenzierte Objekt bestimmt die Methode, die ausgeführt wird!

Interfaces

428

interface W {}

interface X extends W {}

class Y implements W {}

class Z extends Y implements X {}

Interfaces

W

X

Z

Y

Page 107: Java

429

interface W {}

interface X extends W {}

interface Y extends W {}

class Z implements X, Y {}

Interfaces

W

X

Z

Y

430

Namenskonflikte beim Realisieren mehrerer Interfaces:

Was passiert, wenn eine Methode mit dem gleichen Namen in zwei zurealisierenden Interfaces vorkommt?

1. Fall: Überladen2. Fall: eine Realisierung3. Fall: unlösbarer Konflikt (gleiche Parameter, unterschiedlicheRückgabetypen)

Was passiert bei gleichnamigen Attributen?

Referenzierung über InterfaceName.Attribute

Interfaces

431

Interfaces haben keine ausgezeichnete Wurzel, von der alle Interfaces erben(anders als Klassen, die alle von Object erben). Dennoch könnenAusdrücke eines beliebigen Interface-Typen an eine Referenz auf einObjekt der Klasse Object zugewiesen werden, denn ein Objekt, das einInterface implementiert ist halt irgendein Objekt und damit auch vom TypObject .

Interfaces

432

Garantieren von Methoden

• Trennung von Deklaration und Implementierung– Deklaration

public interface Konto {public void einZahlen();public void ausZahlen();...

}

Interface

public interface iName {Methodendeklarationen;

}

Interfaces können von anderenInterfaces erben (extends )

Page 108: Java

433

Garantieren von Methoden

• Trennung von Deklaration und Implementierung– Implementierung

public class Girokontoimplements Konto {

public void einZahlen() {...

}public void ausZahlen() {

...}

}

Interface

public class cNameimplements iName {

}

Klassen können mehrereInterfaces implementieren(implements i1, i2, ... )

434

Interfaces versus abstrakte Klassen

Interfaces erlauben eine Art Mehrfacherbung. Eine Klasse kann nur von eineranderen Klasse erben, selbst dann wenn die vererbende Klasse nurabstrakte Methoden hat.

Eine abstrakte Klasse kann teilweise implementiert sein, sie kann überprotected Attribute, static Methoden usw. verfügen. Interfaces könnennur public Konstanten und Methoden ohne Realisierungen beinhalten.

Tipp: Jede grundlegende Klasse, von der geerbt wird, sollte dieImplementierung eines Interface sein! Nur dann können andere Klassen(die schon erben) von der allgemeinen Festlegung profitieren.

Kapitel 14

Ausnahmen (Exceptions)

436

Ausnahmen - Wieso eigentlich?

(Etwas naive) Annahme:

– Algorithmen sind so entworfen, daß alle denkbarenZustände behandelt werden. Ungewollte Terminierungen(Abstürze) können deshalb gar nicht vorkommen.

• Beispiel: beim Einfügen eines Elementes in eine Liste werden alledenkbaren Fälle (Einfügen in leere Liste, Einfügen vor erstemListenelement, Einfügen zwischen Listenelemente, Einfügen hinterdem letzten Listenelement) unterschieden und korrekt behandelt.

– Wozu also Ausnahmen?

Page 109: Java

437

Ausnahmen - Wieso eigentlich?

Das Ende der Naivität:

– Algorithmen werden durch das Zusammenwirken vonObjekten realisiert. Objekte entscheiden autonom über dieAusführung von Methoden, können dabei aber nicht denGesamtzustand des Systems berücksichtigen. Wenn eineAusführung nicht erfolgen kann, dann erfolgt eineAusnahme, die entsprechend behandelt werden kann (undmuß).

– Viele Objekte mit internen Zuständen führen zu einerZustandsexplosion, so daß es nicht mehr handhabbar ist,alle Zustände explizit zu unterscheiden.

438

Ausnahmen - Wieso eigentlich?

Und noch ein pragmatischer Grund:

– Selbst wenn es in kleineren Programmen möglich ist, alleAusführungen abzufragen und deshalb auch ohneAusnahmen auszukommen, so wird durch die ganzeFallunterscheiderei der eigentlich Algorithmus verschleiert.Das Konzept der Ausnahmebehandlung wirkt dementgegen, indem der eigentliche Algorithmus von derAusnahmebehandlung getrennt wird.

439

Übersicht über dieses Kapitel

• Was sind Ausnahmen? / Grundidee der Ausnahmebehandlung– Die Klasse java.lang.Exception

• „Werfen“ von Exceptions

• Weiterleiten von Exceptions

• „Fangen“ von Exceptions

• Die Klassen Exception, Error, RuntimeException

440

Was sind Ausnahmen?

• Ausnahmen können im Programmablauf auftreten– Division durch Null– Datei nicht vorhanden– ...

• Ziel ist aber: Erstellen eines stabilen Programms• Ausnahme: Zustand, der das Programm daran hindert, im

normalen Ablauf fortzufahren

• Trennung von Fehlerbehandlungscode und regulärem Code• Es kann leichter sein, Ausnahmen eintreten zu lassen und sie

ordentlich zu behandeln als sie unbedingt zu vermeiden.

Page 110: Java

441

• Es gibt vordefinierte Ausnahmen, diese können erweitertwerden.

• In der Definition von Methoden wird definiert, welcheAusnahmen auftreten können.

• Beim Aufruf von Methoden wird definiert, wie diemöglicherweise auftretenden Methoden behandelt werden.Hierzu wird der potentiell Ausnahmen verursachende Code ineinen try{...}- Block eingebettet.

Grundidee der Ausnahmebehandlung

442

Grundidee der Ausnahmebehandlung

• Wenn im try{...}- Block Ausnahmen auftreten, werden siegefangen. Was dann passiert, wird im catch{...}- Blockfestgelegt.

• Nach dem Fangen und Verarbeiten wird im finally{...}-Block definiert, was zum Abschluß der Ausnahmebehandlungpassiert.

• Und nun erst mal ein Beispiel!

443

Die Klasse java.lang.Exception

public class Exception ... {

public Exception() {..};

public Exception(String s) {...};

// und von java.lang.Throwable geerbt:

// Kurzbeschreibung des Fehlers

public String toString() {...};

// Details des Fehlers

public String getMessage() {...};

// Details mit Aufrufstack

public String printStackTrace() {...};

...

} 444

„Werfen“ von Ausnahmen

...

if (kontostand-betrag > dispo) {

zahle(-betrag);

return (betrag);

} else throw new Exception();

...

throw new Exception ();throw new Exception(„Text“);

Page 111: Java

445

Definition des Werfens von Ausnahmen in Methoden

public int auszahlen(int betrag) throws Exception {

Datum heute = Datum.aktuellesDatum();

int zinstage = heute.gibDifferenz(letzteTransaktion);

int zinsen = berechneZinsen(zinstage);

zahle(zinsen);

if (kontostand-betrag > dispo) {

zahle(-betrag);

return (betrag);

} else throw new Exception(“Konto nicht gedeckt“);

}

Modifier Rückgabetyp Methodenname (...) throws Exception {

446

Definition des Werfens von Ausnahmen in Methoden

Die Ausnahmen, die geworfen werden können, müssen deklariertwerden, weil Programmierer, die Methonden aufrufen, dasAusnahmeverhalten genauso kennen müssen wie das normaleVerhalten (Signatur).

Die in der Methodendefinition deklarierten Ausnahmen werdenauch „checked“ Ausnahmen genannt (im Unterschied zu dennicht explizit deklarierten und vom Compiler nicht explizitgeprüften Laufzeitausnahmen).

447

Definition des Werfens von Ausnahmen in Methoden

Das heißt: RuntimeException (z.B. ClassCastException ,ArithmeticException ) werden nicht explizit deklariert. Siekönnen von jeder Methode geworfen werden und werdendeshalb auch nicht vom Compiler überprüft (sie bleiben„unchecked“), d.h. Exceptions der Klassen java.lang.Errorund java.lang.RuntimeException und deren Unterklassenmüssen nicht in der throws -Deklaration gekennzeichnetwerden.

448

Aufrufen von Methoden, die Ausnahmen werfen

Beim Aufruf einer Methode, die in ihrer throws-AnweisungAusnahmen auflistet, bleiben drei Möglichkeiten:– Fangen und Behandeln– Fangen, Abbilden auf eigene Ausnahme, Werfen der eigenen

Ausnahme– Deklarieren der Ausnahme in der aufrufenden Methode und dann

Fangen und Weiterleiten der Ausnahme

• Immer dabei: Fangen von Ausnahmen!

Page 112: Java

449

Fangen von Ausnahmen

• Mit try und catch werden Exceptions aufgefangen– try -Block: Bereich, in dem Ausnahmen auftreten können– catch -Block: Bereich, in dem die Fehlerbehandlung stattfindet– finally -Block: optional, wenn vorhanden, wird er auf jeden Fall ausgeführt

...

Kont o k = new Konto();

try {

k.auszahlen(10000);

} catch (Exception e) {

Bildschirm.gibAus(e.getMessage());

} finally {

Bildschirm.gibAus(k.holeKontostand());

}

Werfen

Fangen

Aufräumen

450

Fangen von Ausnahmen

try {

statements

} catch (exception_type1 identifier1) {

statements

} catch (exception_type2 identifier2) {

statements

....

} finally {

statements

}

Mehrerecatch-Blöcke!

451

Verarbeiten von Ausnahmen

Der Rumpf des try -Blockes wird ausgeführt bis eine Ausnahmeauftritt oder bis zum Ende (falls keine Ausnahme auftritt).

Wenn eine Ausnahme auftritt wird jeder catch -Block geprüft (vonoben nach unten), um diejenigen catch -Blöcke zu finden, diedie Ausnahme fangen können.

Es dürfen keine Ausnahmen gefangen werden, die im try -Blocknicht auftreten können.

Für einen passenden catch -Block wird der Identifier auf dasaufgetretene Exception-Objekt gesetzt. Kein weiterer catch-Block wird ausgeführt (also nur der erste passende!). Es mußalso darauf geachtet werden, daß die catch- Blöckeunterschiedliche Ausnahmen fangen.

452

Verarbeiten von Ausnahmen

Wenn kein passender catch -Block gefunden wird, sickert dieAusnahme in weiter außen liegende try -Blöcke durch.

Wenn ein finally -Block vorkommt, dann wird er ausgeführt,nachdem der try- Block abgearbeitet ist (entweder durchnormale Beendigung, Ausnahme oder return/break ).

Ein finally -Block ist sinnvoll, um notwendige Resourcenfreizugeben (z. B. Schließen einer Datei), denn derProgrammcode außerhalb des try -Blocks wird nicht mehrerreicht, falls innerhalb eines catch -Blocks wieder eineAusnahme geworfen wird.

Page 113: Java

453

• Ausnahmen können auftreten durch– explizite throw -Anweisung– Aufruf einer Methode mit throws - Deklaration

Ausnahmebehandlung

454

• Auffangen und Weiterwerfen (throw im catch -Block) istsinnvoll, um wichtige Zusatzinformationen anzuhängen

• Kann in einer Methode eine Ausnahme auftreten, muß sie– entweder durch try und catch aufgefangen werden– oder durch throws in der Methodendeklaration weitergeleitet werden

Ausnahmebehandlung

455

Exception, Error, RuntimeException

• Exception:– nicht für ernsthafte, kritische Fehler– Einsatz als Feature im Programmablauf

• Error:– Schwerwiegende Fehler der Virtual Machine– Sollten nicht selbst geworfen oder aufgefangen werden

• RuntimeException– Systemfehler, die nicht deklariert werden müssen– Beispiel: Teilung durch Null (0)

456

Schreiben eigener Ausnahmen

• Neue Klasse wird von java.lang.Exception abgeleitet :

public class KeineDeckungException extends Exception {

public KeineDeckungException() {

super();

}

public KeineDeckungException(String s) {

super(s);

}

}

Page 114: Java

457

Benutzen eigener Ausnahmenpublic class Girokonto extends Konto {

...

public int auszahlen( int betrag) throws KeineDeckungException {

...

if (kontostand-betrag > dispo) {

zahle(-betrag);

return (betrag);

} else throw new KeineDeckungException( “ Konto nicht gedeckt“);

}

}

• Auffangen der Exception:try {

k.auszahlen(1000);

} catch (KeineDeckungException e) {

Bildschirm.gibAus(e.getMessage());

}

458

Übung: Behandlung von Ausnahmen

Motivation• Schreiben eigener Ausnahmen• Benutzen von Ausnahmen

Aufgabe• Identifizieren Sie zwei weitere Ausnahmen und schreiben Sie jeweils eine

neue Klasse für diese Ausnahme• Erweitern Sie das Programm so, daß diese Exceptions geworfen,

weitergeleitet und gefangen werden• Testen Sie die geänderten Klassen mit der der Klasse

TestKartenverwaltung . Verursachen Sie dabei absichtlich Fehler.

459

Übung: Behandlung von Ausnahmenpublic class KontoNichtVorhandenException extends Exception {

public KontoNichtVorhandenException () {

super ();

}

public KontoNichtVorhandenException (String s) {

super (s);

}

}

public class LaufzeitNichtErreichtException extends Exception {

public LaufzeitNichtErreichtException () {

super ();

}

public LaufzeitNichtErreichtException (String s) {

super (s);

}

}

Exceptions

460

Übung: Behandlung von Ausnahmenpublic class Kartenverwaltung {

...

public Konto holeKonto (String kartennummer)

throws KontoNichtVorhandenException {

Konto dasKonto = null ;

for (int i=0; i<freiIndex; i++){

if (kartennummer.equals(kartennr[i])){

dasKonto = konten[i];

}

}

if (dasKonto == null ) throw new KontoNichtVorhandenException();

return (dasKonto);

}

...

}

Exceptions

Page 115: Java

461

Übung: Behandlung von Ausnahmenpublic class TestKartenverwaltung {

public static void main (String[] args) {

Waehrungsrechner rechner = new Waehrungsrechner();

Person inhaber = new Person( “ Urs“, “ Müller“, “ Hauptstr. 1“,

“ 12345“, “ Berlin“);

Girokonto k = new Girokonto(inhaber, rechner, 100);

Festgeld f = new Festgeld(inhaber, rechner, 100000);

Kartenverwaltung verwaltung = new Kartenverwaltung();

verwaltung.erfasseWeiteresKonto("1", “1234", k);

verwaltung.erfasseWeiteresKonto(“2", “5678", f);

try {

Festgeld geld = (Festgeld) verwaltung.holeKonto(“2“);

geld.kuendigen();

} catch (LaufzeitNichtErreichtException e) {

Bildschirm.gibAus(e.getMessage());

}

Exceptions

462

Übung: Behandlung von Ausnahmen

try {

Girokonto gKonto = (Girokonto) verwaltung.holeKonto("1“);

gKonto.auszahlen(1000);

} catch (KontoNichtVorhandenException e1) {

Bildschirm.gibAus(e1.getMessage());

} catch (KeineDeckungException e2) {

Bildschirm.gibAus(“Konto ist nicht gedeckt“);

}

...

}

Exceptions

Kapitel 15

Pakete und Zugriffskontrolle

464

Pakete, Verkapselung, Zugriffskontrolle

• Pakete, Verkapselung und Zugriffskontrollmechanismen sindMöglichkeiten, Programme besser zu strukturieren=> Diese Mechanismen sind eine Grundvoraussetzung für

eine erfolgreiche Programmierung im Team

• Überlegungen der Grobstrukturierung sollten vor demProjektstart gemacht werden, und nicht nachher

• Modellierungssprachen wie UML können hier die Planungerheblich erleichtern, denn je größer das Software-Projekt istdesto wichtiger ist eine gründliche Planung

Page 116: Java

465

Pakete

• Durchpackage Packagename;wird ein neuer Namensraum als Paket zusammengefaßt

• Die package -Anweisung ist die erste Anweisung der Datei

• Zugehörige CLASS-Files stehen in einem Unterverzeichnesmit dem Namen Packagename, dessen Wurzel befindet sich ineinem Verzeichnis, welches im CLASSPATHaufgenommen ist.

• Packages können auch Unter-Packages haben, analog zuUnterverzeichnissen im Dateisystem

466

Pakete

• Pakete werden in der Regel durch eine Abbildung der Pakete-Struktur auf das Dateisystem realisiert

• Unter-Pakete werden mitpackage Hauptpackagename. Unterpackagename;definiert

• Klassen aus anderen Paketen werden durchPackagename.Klassenname angesprochen

467

Pakete

• Durchimport Packagename. Klassenname;wird eine Klasse aus einem anderen Pakete bekannt gemacht.Sie kann dann wie eine lokal definierte Klasse ohne Angabedes Paketnamens benutzt werden.

• Mitimport Packagename. *;werden alle Klassen im entsprechenden Paketbekanntgemacht

• import java.lang.*; wird immer ausgeführt und mußnicht explizit angegeben werden

468

Pakete

Beispiel:

• Anlegen eines Wurzelverzeichnisses für ein Projekt, hierC:\projekt (bzw. ~/projekt in UNIX). und Wechsel indieses Unterverzeichnis (cd projekt ).

• Für Pakete müssen Unterverzeichnisse angelegt werden. Hier:"md utils " und "md hauptpackage ".

• Java-Files für die einzelnen Pakete müssen in denentsprechenden Unterverzeichnissen editiert werden.Hier: Datum.java im Verzeichnis utils undStartklasse.java im Verzeichnis hauptpackage .

Page 117: Java

469

PaketeDatei Datum.java im Verzeichnisutils :

Datei Startklasse.java imVerzeichnis hauptpackage :

• Zum Compilieren Angabe derHauptdatei vom Wurzelverzeichnisaus.javac hauptpackage/Startklasse.java

•Abhängige Klassen werden (fallsnicht schon geschehen) mitcompiliert.• Zum Ausführen Angabe der zustartenden Klasse innerhalb derPaket-Hierarchie. Unterpaketewerden durch Punkt gekennzeichnet:java hauptpackage.Startklasse

• Ohne Angabe von import utils.*

müßte die Klasse Datum über dasPaket angesprochen werden:utils.Datum d = new utils.Datum();

package utils;class Datum() {

int tag, monat,jahr;

... // nun dieMethoden}

package hauptpackage;import utils.*;class Startklasse {

public static voidmain(String[] args) {

Datum d = new Datum();...

}}

470

Pakete

• Pakete sind Sammlungen von Klassen und Interfaces

package demo;

public class A {...

}

import demo.*;import demo.windows.*

Zusammenfassung von Klassen

Aufruf

import Package.Klasse;

import Package.*;

Definition

package PackageName; oder

package PackgaeName.SubPackageName;

471

Zugriffskontrolle für Klassen

• Klassen können standardmäßig nur auf andere Klassen ausdem gleichen Package zugreifen.

• Mit Hilfe der Zugriffsspezifikation public kann die Klasseauch nach außen sichtbar gemacht werden, also auch überPaketgrenzen hinaus!

public class Klassenname {

...

}

472

Zugriffskontrolle für KlassenBeispiel:

package A;public class Test1 {}

package A;class Test2 {}

package A;class Haupt1 {

void methode() {// beides erlaubt:

Test1 t1 = new Test1();Test2 t2 = new Test2();

}}

package B;

import A.*;

class Haupt2 {

void methode() {

// erlaubt:

Test1 t1 = new Test1();

// nicht erlaubt:

Test2 t2 = new Test2();

}

}

Page 118: Java

473

Übersicht Zugriffsrechte

• Alle Zugriffsrechte in Java im Überblick

Zusammenfassung von Klassen

Zugriff auf public protected package private

Gleiche Klasse Ja Ja Ja Ja

Klasse im gleichen Paket Ja Ja Ja Nein

Subklasse im fremden Paket Ja Ja / Nein Nein Nein

Keine Subklasse, fremdes Paket Ja Nein Nein nein

474

Zugriffskontrolle für Attribute / Methoden

• Methoden und Attribute einer Klasse können optional eineder Sichtbarkeitsmodifikationen public , protected oderprivate erhalten. Ist nichts spezifiziert, gilt das Zugriffsrechtpackage

• Attribute sollten immer als private definiert werden. DerZugriff auf die Attributwerte wird dann nur über set- und get-Methoden erlaubt.

475

Zugriffskontrolle für Attribute / Methoden

• public heißt, das Attribut bzw. die Methode ist für jedensichtbar.

• protected heißt, das Attribut bzw. die Methode ist innerhalbdes Packages und in abgeleiteten Klassen sichtbar. DieSichtbarkeit in abgeleiteten Klassen ist aber nur danngegeben, wenn die Referenz auf das abgeleitete Objekt, vondem aus das protected -Attribut angesprochen werden soll,nicht eine Referenz vom Typ der Oberklasse ist.

• private heißt, das Attribut bzw. die Methode ist nur innerhalbder Klasse sichtbar

476

Zugriffskontrolle für Attribute / Methoden

• Ohne Spezifikation kann man innerhalb des Packages aufAttribute bzw. Methoden zugreifen.

• Ist die Klasse nicht als public deklariert, kann außerhalb desPackages auch nicht auf Methoden oder Attribute zugegriffenwerden, die als public deklariert sind.

Page 119: Java

477

Zugriffskontrolle für Attribute / MethodenBeispiel:

package A;public class ZugriffsTest {

private int priv;protected int prot;public int pub;int pack;

private void privMethode() {}protected void protMethode() {}public void pubMethode() {}void packMethode() {}

public void test(ZugriffsTest z) {

// Alle Zugriffe erlaubtpriv = 1; z.priv = 1;prot = 1; z.prot = 1;pub = 1; z.pub = 1;pack = 1; z.pack = 1;privMethode();protMethode();pubMethode();packMethode();z.privMethode();z.protMethode();z.pubMethode();z.packMethode();

}}

478

Zugriffskontrolle für Attribute / MethodenBeispiel:ZugriffsTest2 im gleichen Packagewie Zugriffstest

package A;public class ZugriffsTest2 {

public static voidmain(String[] args) {

ZugriffsTest t =new ZugriffsTest();

t.priv = 1; // n. erlaubtt.prot = 1; // erlaubtt.pub = 1; // erlaubtt.pack = 1; // erlaubt

// nicht erlaubt:t.privMethode();

// erlaubt:t.protMethode();t.pubMethode();t.packMethode();

}}

479

Zugriffskontrolle für Attribute / MethodenBeispiel:ZugriffsTest3 abgeleitet vonZugriffsTest und im gleichenPackage wie ZugriffsTest

package A;public class ZugriffsTest3

extends ZugriffsTest {public static void

main(String[] args) {

ZugriffsTest3 t =new ZugriffsTest3();

t.priv = 1; // n. erlaubtt.prot = 1; // erlaubtt.pub = 1; // erlaubtt.pack = 1; // erlaubt

t.privMethode(); // n.e.t.protMethode(); // erl.t.pubMethode(); // erl.t.packMethode(); // erl.

}void test3 () {

priv = 1; // n. erlaubtprot = 1; // erlaubtpub = 1; // erlaubtpack = 1; // erlaubtprivMethode(); // n.e.protMethode(); // erl.pubMethode(); // erl.packMethode(); // erl.

}}

480

Zugriffskontrolle für Attribute / MethodenBeispiel:ZugriffsTest4 abgeleitet vonZugriffsTest und nicht im gleichenPackage wie ZugriffsTest

package B;import A.*;public class ZugriffsTest4

extends ZugriffsTest {public static void

main(String[] args) {

Zugriffstest4 t =new ZugriffsTest4();

t.priv = 1; // n. erlaubtt.prot = 1; // erlaubtt.pub = 1; // erlaubtt.pack = 1; // n.erlaubt

t.privMethode(); // n.e.t.protMethode(); // erl.t.pubMethode(); // erl.t.packMethode(); // n.e.

}void test4 () {

priv = 1; // n. erlaubtprot = 1; // erlaubtpub = 1; // erlaubtpack = 1; // n. erlaubtprivMethode(); // n.e.protMethode(); // erl.pubMethode(); // erl.packMethode(); // n.e.

}}

Page 120: Java

481

Zugriffskontrolle für Attribute / MethodenBeispiel:ZugriffsTest5 abgeleitet vonZugriffstest und nicht im gleichenPackage wie ZugriffsTest

package B;import A.*;public class ZugriffsTest5

extends ZugriffsTest {public static void

main(String[] args) {

Zugriffstest t =new ZugriffsTest5();

t.priv = 1; // n. erlaubtt.prot = 1; // n. erlaubtt.pub = 1; // erlaubtt.pack = 1; // n.erlaubt

t.privMethode(); // n.e.t.protMethode(); // n.e.t.pubMethode(); // erl.t.packMethode(); // n.e.

}}

• Im Unterschied zuZugriffsTest4 wird hier übereine Referenz auf Zugriffstestauf die Attribute bzw. Methodenzugegriffen.

• FürZugriffstest t = new

Zugriffstest();

erhalten wir die gleichen Zugriffs-einschränkungen (nur public -Zugriff)

482

Verkapselung

• Verkapselung ist ein Grundprinzip der Objektorientierung, undkann als Empfehlung verstanden werden, Zugriffskontrollenrichtig einzusetzen also:

• Jede Klasse legt mit Hilfe der Zugrifsrechte selbst fest, wer aufihre Attribute und Methoden zugreifen darf, hierbei gilt:– Methoden, die nicht dokumentiert sind, bzw. nur Hilfsfunktionen für

andere Methoden sind, sollten private oder zumindest protectedsein

– Attribute sollten nicht public sein, um Änderbarkeit undDatenkonsistenz sicherzustellen

– Für Zugriffe auf Attribute sollten get - und set -Methoden zur Verfügunggestellt werden, die zugehörigen Attribute sollten dann private sein

483

Verkapselung

• Verstecken von Implementierungsdetails ist wichtig, umÄnderbarkeit der Implementierung zu gewährleisten.Eine nicht sichtbare Methode kann auch nicht von anderenbenutzt worden sein.

• Verstecken von Implementierungsdetails kann das Verständniserleichtern, da nur die für den Endanwender wichtigeSchnittstellen zugreifbar sind.

484

Gesamtbeispiel Klasse Datum

Klasse Datum unter Berücksichtigung von:• Verkapselung / Zugriffskontrolle• Ausnahmebehandlung

Zeigt auch, was von Packages sichtbar gemacht werden muß!• D.h. vieles bleibt intern• nur das nötigste wird nach außen bekannt gemacht

Page 121: Java

485

Gesamtbeispiel Klasse Datum

Realisierung der folgenden Funktionalitäten:• Wochentagberechnung• Differenzbildung zwischen Daten (in Tagen)• Addition eines Datums mit einem Offset (in Tagen)• Feiertagsberechnungen

486

Klasse DatumException

• Klasse Datum bekommt eine eigene Exception-Klasse fürFehlerbehandlung

package utils;

/**

* Exception für Fehlerbehandlung der Klasse Datum.

*/

public class DatumException extends Exception {

public DatumException() {

super();

}

public DatumException(String s) {

super(s);

}

}

487

Klasse Datum - Attribute

• Attributdefinitionen der Klasse Datumpackage utils;import java.io.*;/**

* Klasse zur Verwaltung von Datumsobjekten*/

public class Datum implements Serializable {private int tagkonst; // Konstante mit Tagen seit Christi Geburt

// Konstanten für Tag, Monat und Jahr.// Daten lassen sich aus tagkonst berechnen, daher// als transient definiert.

private transient int tag, monat, jahr;

private final static String[] wt = {"Montag", "Dienstag", "Mittwoch","Donnerstag", "Freitag", "Samstag", "Sonntag"};

// Hier nun die Methoden, nächste Folien}

488

Klasse Datum - öffentl. Konstruktoren/**

* Konstruktor mit Tag, Monat und Jahr.* @exception utils.DatumException* Datum ist nicht gültig nach Gregorianischem Kalender* (Gregorianischer Kalender seit 15.10.1582)*/

public Datum (int tag, int monat, int jahr) throws DatumException {init(tag, monat, jahr); // Initialisierung der Attribute

}

Achtung: Für Kommentare sollten HTML-Umlaute verwendet werden, also"&uuml; " für "ü". Hier aber "ü" für die bessere Lesbarkeit.

/*** Konstruktor für 1. Januar eines Jahres.*/

public Datum(int jahr) throws DatumException {init(1,1,jahr);

}

Page 122: Java

489

Klasse Datum - priv. Initialisierungsmethoden

/**

* Berechnung der Tage, die seit eines Bezugsdatums vergangen sind.

* Dieser Tag liegt vor dem 15.10.1582, dem Start des Gregorianischen

* Kalenders.

* Wichtig für Differenzbildung von Daten und für Wochentags- bzw.

* Feiertagsberechnungen.

*/

private synchronized int getTageKonst(int tag, int monat, int jahr) {

boolean schalt = (jahr%4 == 0 && (jahr%100 != 0 || jahr%400 == 0));

return (jahr-1) * 365 + (jahr-1)/4 - (jahr-1)/100

+ (jahr-1)/400

+ (monat-1)*31 - (monat>2 ? 3 : 0) + (monat>2 && schalt ? 1: 0)

- (monat>4 ? 1 : 0) - (monat>6 ? 1 : 0) - (monat>9 ? 1 : 0)

- (monat>11 ? 1 : 0) + tag;

}

490

Klasse Datum - priv. Initialisierungsmethoden

/**

* Initialisiert das Attribut tagkonst.

* Der benötigte Wert kann mit getTageKonst(tag, monat, jahr)

* berechnet werden.

* @exception utils.DatumException

* Datum vor Einführung des Gregorianischen Kalenders

*/

private void init(int tagkonst) throws DatumException {

this.tagkonst = tagkonst;

if (tagkonst < 577736)

throw new DatumException("Nur Gregorianischer Kalender" +

" ab 15.10.1582 wird untertützt");

}

491

Klasse Datum - priv. Initialisierungsmethoden/**

* Initialisiert Attribute jahr, monat und tag bei bereits* initialisiertem Attribut tagkonst.*/

private synchronized void setTagMonatJahr() {jahr = 1500;monat = 1;tag = 1;while (getTageKonst(tag, monat, jahr+100) <= tagkonst)

jahr += 100;while (getTageKonst(tag, monat, jahr+10) <= tagkonst)

jahr += 10;while (getTageKonst(tag, monat, jahr+1) <= tagkonst)

jahr ++;while (getTageKonst(tag, monat+1, jahr) <= tagkonst)

monat++;tag += tagkonst - getTageKonst(tag, monat, jahr);

}

492

Klasse Datum - priv. Initialisierungsmethoden/**

* Initialisiert Attribute jahr, monat und tag und tagkonst.** @exception utils.DatumException* Datum ist nicht gültig nach Gregorianischem Kalender.* (Gregorianischer Kalender seit 15.10.1582).* Hierbei werden alle Regeln der Datumsbildung berücksichtigt.*/

private synchronized void init(int tag, int monat, int jahr)

throws DatumException {

init(getTageKonst(tag, monat, jahr));

setTagMonatJahr();

if (tag != this.tag || monat != this.monat || jahr != this.jahr)

throw new DatumException("Datum " + tag + "." + monat + "."

+ jahr + " existiert nicht");

}

Page 123: Java

493

Klasse Datum - privater Konstruktor

/*** Konstruktor, der aus der Tageskonstante ein Datumsobjekt* erzeugt.* Dummy-Parameter notwendig, um sich von Initialisierung über* Jahreszahl zu unterscheiden.*/

private Datum(int tagkonst, boolean dummy) throws DatumException {

init(tagkonst);

setTagMonatJahr();

}

494

Klasse Datum - Objektserialisierung

/*** Bei Objektserialisierung wird nur das Attribut tagkonst* berücksichtigt.* Diese Methode sorgt für eine Rekonstruktion der* Attribute tag, monat und Jahr bei Deserialisierung*/

private void readObject(ObjectInputStream stream)

throws IOException, ClassNotFoundException {

stream.defaultReadObject();

setTagMonatJahr();

}

495

Klasse Datum - öffentliche Methoden/**

* Berechnung des Wochentages.*/

public String wochentag() {

return wt[(tagkonst + 6) % 7];

}

/**

* Gibt die Differenz zu einem Referenzdatum d in Tagen zurück.

* Der Wert ist negativ, falls d in der Zukunft liegt, sonst positiv.

*/

public int diff(Datum d) {

return tagkonst - d.tagkonst;

}

496

Klasse Datum - öffentliche Methoden/**

* Gibt das Datum in i Tagen zurück. Auch negatives i möglich.* @exception utils.DatumException* Das Ergibnis liegt vor Einführung des Gregorianischen Kalenders.*/

public Datum plus(int i) throws DatumException {

return new Datum(tagkonst + i, true);

}

/**

* Gibt String-Repräsentation des Datums zurück.

*/

public String toString() {

return wochentag() + ", den " + tag + "." + monat + "." + jahr;

}

Page 124: Java

497

Klasse Datum - öffentliche Methoden/**

* Berechnet Ostersonntag des entsprechenden Jahres nach der Gaußschen* Osterformel (1800), welche für die Jahre 1583 bis 8202 gültig ist.* @exception utils.DatumException* Falls Osterformel nicht gültig.*/

public Datum OsterSonntag() throws DatumException {if (jahr < 1583 || jahr > 8202)

throw new DatumException("Osterformel gilt von 1583 bis 8202");int a = jahr % 19; int b = jahr % 4; int c = jahr % 7;int m = (8 * (jahr/100) + 13) / 25 - 2;int s = jahr/100 - jahr/400 - 2; int M = (15 + s - m) % 30;int N = (6 + s) % 7; int d = (M + 19*a) % 30;int D;if (d == 29) D = 28;else if (d == 28 && a >= 11) D = 27;else D = d;int e = (2*b + 4*c + 6*D + N) % 7;return new Datum(22,3,jahr).plus(D+e);

}

498

Klasse Datum - öffentliche Methoden// Auf Ostern basierende Feiertage:public Datum PfingstSonntag() throws DatumException {

return OsterSonntag().plus(49);}public Datum RosenMontag() throws DatumException {

return OsterSonntag().plus(-48);}public Datum Himmelfahrt() throws DatumException {

return OsterSonntag().plus(39);}

// Feste Feiertage:public Datum ErsterWeihnachtstag() throws DatumException {

return new Datum(25,12,jahr);}public Datum Maifeiertag() throws DatumException {

return new Datum(1,5,jahr);}

499

Klasse Datum - Anwendungpackage hauptpackage;

import utils.*;

public class Anwendung {

public static void main(String[] args) {

try {

Datum d = new Datum(1,1,2000).plus(10000);

System.out.println("Am " + d + " wird das 3. Jahrtausend"

+ " 10000 Tage alt.");

}

catch (DatumException e) {}

}

}

Ausgabe:Am Mittwoch, den 19.5.2027 wird das 3. Jahrtausend 10000 Tage alt.

500

Klasse Datum - Anwendungpackage hauptpackage;

import utils.*;

public class Anwendung {

public static void main(String[] args) {

try {

System.out.println("Ostersonntage:");

for (int i=1995; i<=2010; i++)

System.out.println(new Datum(i).OsterSonntag());

}

catch (DatumException e) {}

}

}

Ausgabe:Ostersonntage:Sonntag, den 16.4.1995Sonntag, den 7.4.1996Sonntag, den 30.3.1997Sonntag, den 12.4.1998Sonntag, den 4.4.1999Sonntag, den 23.4.2000Sonntag, den 15.4.2001Sonntag, den 31.3.2002Sonntag, den 20.4.2003Sonntag, den 11.4.2004Sonntag, den 27.3.2005Sonntag, den 16.4.2006Sonntag, den 8.4.2007Sonntag, den 23.3.2008Sonntag, den 12.4.2009Sonntag, den 4.4.2010

Page 125: Java

Kapitel 16

Überblick über Java-Klassenbibliotheken

502

Klassenbibliothek

• Umfangreiche Klassenbibliotheken machen die Mächtigkeitvon Java aus.

• Während sich der Sprachumfang kaum von dem andererSprachen unterscheidet, bedeutet die Verfügbarkeit einerumfangreichen Klassenbibliothek einen Vorteil.

• Von besonderer Bedeutung ist dabei, daß die Bibliothekplattformübergreifend eingesetzt werden kann.

• Die Bibliothek ist in Pakete gegliedert. Nur dadurch wird siehandhabbar.

• Diese Pakete können wie selbstdefinierte Pakete verwendetwerden.

503

Klassenbibliothek

• Klassenbibliotheken sehr umfangreich• Hier nur Einblick in grobe Einteilung und wichtige

Funktionalitäten• Vollständige Übersicht in• “JDK 1.2 Documentation“ bzw.

“Java SDK SE v1.3 Documentation”=> Nachschlagewerk

504

Übersicht Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

Page 126: Java

505

java.applet Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

506

java.awt Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

507

java.beans Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

508

java.io Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

Page 127: Java

509

java.lang Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

510

java.lang

• Basispaket der Sprache

• alle Systemklassen sind hier untergebracht

• Klassen dürfen ohne import -Deklaration direkt angesprochenwerden (vgl. System, String)

Die Java Klassenbibliotheken

511

java.lang: Object , String und StringBuffer

• Klasse Object– Die Mutter aller Klassen

• Klassen String und StringBuffer– Zeichenketten

512

Class

• Klasse Class– Klasse um Klassennamen und Instanzen zu verwalten– Die Klasse Object hat die Methode

public final Class getClass()um zugehöriges Class-Objekt zu erhalten

– Methode public String getName() gibt Namen der Klasse zurück

– Es lassen sich mit Hilfe des Class-Objektes verfügbare Konstruktorenund Methoden ermitteln (seit JDK 1.1)

– Neue Objekte der Klasse können so erzeugt werden, ohne daß manVorabinformationen hat (seit JDK 1.1)

Page 128: Java

513

System

• Klasse System– Sammlung von Klassenattributen und -methoden– Anbindung an Standard-In, Standard-Out und Standard-Error-Stream

(System.in , System.out und System.err )

– Systemnahe Methoden– public static long currentTimeMillis()

• gibt Millisekunden seit 1. Janur 1970 zurück

– public static void exit(int status)• Beendet das Programm (und die Virtuelle Maschine)

– public static void gc()• Empfehlung an den Garbage - Kollektor, Speicher freizugeben. In der Regel nicht

nötig.

514

java.lang

• java.lang.System– Anbindung an Standard-Err, Standard-In, Standard-Out-Stream

{...System.out.println(“Hallo”);...

}

– Systemnahe Methoden

Die Java Klassenbibliotheken

public static final PrintStream err

public static final PrintStream in

public static final PrintStream out

public static void exit(int status)

public static void gc()

515

Einhüllende Klassen

• Klassen Boolean, Byte, Character, Double,Float, Integer, Long, Short

• Nützlich, wenn primitive Datentypen als Objekt benötigtwerden, z.B. für objektbasierte Datenstrukturen

• Alle einhüllenden Klassen haben den entsprechendeneinfachen Datentypen als Konstruktor– Beispiel:

Float zahl=3.5;Float zahlHülle = new Float(zahl);

• Alle einhüllenden Klassen (bis auf Character) haben Stringals Konstruktorargument– Beispiel:

Long l = new Long("2.142352123");

516

Einhüllende Klassen

• Byte , Double , Float , Integer , Long und Short (sowiejava.math.BigDecimal und java.math.BigInteger )sind von abstrakter Klasse Number abgeleitet

• Für Objekte der Klasse Number sind Wandlungen zu primitivenDatentypen möglich mit byteValue() , doubleValue(),floatValue(), intValue(), longValue() undshortValue()

• Beispiel: Konvertierung von String nach doubleString s = "1.345";double d = new Double(s).doubleValue();

Page 129: Java

517

java.lang

• java.lang.Math– Konstanten E und Pi

– Methoden für Betrag, Rundung, Trigonometrische Funktionen,Exponent / Logarithmus, etc.

Die Java Klassenbibliotheken

public static int abs(int a)

public static native double sin(double a)

public static native double sqrt(double a)

518

java.math Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

519

java.rmi Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

520

java.security Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

Page 130: Java

521

java.util Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

Kapitel 17Dynamische

Datenstrukturen

17.1 Listen17.2 Bäume17.3 Graphen17.4 Schlangen17.5 Keller17.6 Mengen

524

Überblick

• Unter dynamischen Datenstrukturen verstehen wir Strukturen,die je nach Bedarf und damit dynamisch wachsen undschrumpfen können (Unterschied zu Arrays!).

• Die Idee ist, daß die einzelnen Elemente die zu speichernden /zu verarbeitenden Daten speichern und daß diese Elementemiteinander verknüpft werden.

• Die Art der Elemente ist dabei stark problemabhängig undvariiert von Anwendung zu Anwendung.

• Für die Verknüpfung gibt es einige typische Muster. Diesetypischen Muster sind in den klassischen dynamischenDatenstrukturen realisiert.

Dynamische Datenstrukturen

Page 131: Java

525

Überblick

• Neben der Verknüpfung werden diese Datenstrukturen auchnoch dadurch charakterisiert, daß es bestimmteZugriffsmethoden gibt.

• Wie in der Objektorientierung üblich, werden die dynamischenDatenstrukturen also durch die Art der Verknüpfung derElemente und die Zugriffsmethoden festgelegt.

• Weitere Methoden der Ausprägungen der dynamischenStrukturen hängen auch von der Struktur der Einzelelementeab.

Dynamische Datenstrukturen

526

Wichtige dynamische Datenstrukturen

• Listen, lineare Listen, doppelt verkettete• Bäume, binäre Bäume, binäre Suchbäume• Graphen, gerichtete Graphen, ungerichtete Graphen• Stack, Schlangen• Mengen

– Wie wird eine Instanz der Struktur intialisiert und Daten eingefügt bzw. entfernt ?

– Wie wird in den Strukturen navigiert ?– Wie werden einzelne Werte in einer Struktur wiedergefunden ?

– Wie werden alle in einer Struktur abgelegten Werte besucht ?

527

Eigenschaften von Referenzen:

Geld betrag;

if (betrag != null)

betrag.Drucke();

else

betrag = new Geld(10, 25);

Geld preis;

preis = new Geld(48, 98);

preis = null ;

Zugriff über Referenzen

Variable betrag: Referenz auf Objekt der Klasse Geld

Soll eine Referenz auf kein Objekt verweisen, wird der Wertnull zugewiesen

Überprüfung der Referenz mittels Vergleichsoperator

Der Wert null für Referenzen ermöglicht ein Objekt explizit voneiner Referenz zu lösen

Referenz preis verweist auf Objekt der Klasse Geld

Zuweisung auf null vernichtet Verweis auf Objekt mit Werten 48und 98

528

Dynamische Datenstrukturen

Grundlage für den Aufbau dynamischer Datenstrukturen

• Klassen enthalten Attribute, die Referenzen auf Objekte dereigenen Klasse darstellen.

• Diese Attribute schaffen die Möglichkeit, an eine Referenz einweiteres Objekt der Klasse zu binden.

• Die einzelnen Objekte sind in der Lage, gemeinsam einekomplexe Struktur durch aufeinander verweisende Referenzenzu bilden.

Page 132: Java

Kapitel 17.1

Listen

530

Allgemeines zu Listen• Listen definieren eine Reihenfolge von Elementen, die gemäß dieser

Reihenfolge miteinander verknüpft sind.• Typische Zugriffsmethoden:

– Einfügen am Anfang– Einfügen an bestimmter Stelle

– Anfügen (d.h. Einfügen am Ende)– Ermittlung der Länge– Prüfen auf Leere

– Prüfen, ob Element in Liste vorkommt– Ermittlung der Position eines Elements– Ermittlung des ersten Elements

– Liefern der Liste ohne erstes Element

• Die Verfügbarkeit aller dieser Methoden variiert mit demAnwendungszweck. Nicht immer sind alle Methoden realisiert, aberman redet dennoch von Listen

531

Bestandteile einer Listeclass Element {

Element(int i) { wert = i; weiter = null; }

private int wert;

private Element weiter;

}

• Deklaration einer Klasse Element mit zwei privaten Attributen undeinem Konstruktor

• Ein Objekt vom Typ Element enthält als Attribute eine ganze Zahlund einen Zeiger auf ein weiteres Objekt des Typs Element

• Jedes Objekt vom Typ Element besitzt eine Referenz auf einweiteres Element, man kann sie miteinander verketten

• Die daraus entstehende Datenstruktur ist eine Lineare Liste

532

class Liste {private Element kopf;

Liste() { kopf = null; }Liste(int w) { kopf = new Element(w); }

void FügeAn(int an) {

...

}void FügeEin(int ein) {

...

}

Schema der Klasse lineare Liste

Page 133: Java

533

Erweiterung einer Liste

Eine lineare Liste kann auf verschiedene Artenkonstruiert werden :

• neues Element an den Anfang, in die Mitte oder an das Endeeiner bereits bestehenden Liste anhängen

• Zugriff auf die Liste wird durch eine Referenz realisiert, die aufdas erste Element der Liste zeigt

• Enthält eine Liste keine Elemente, zeigt die Referenz auf null

• Besuchen eines Elements innerhalb der Liste erfordert eineReferenz von Element zu Element

534

void FügeAn(int neuerWert) {

Element lauf = this;

while (lauf.weiter != null)

lauf = lauf.weiter;

lauf.weiter = new Element(neuerWert);

}

• Die Klasse Element wird um die Methode FügeAn ergänzt, die ein neuesElement an das Ende einer Liste anhängt, die bereits aus wenigstens einemElement besteht.

• Die Liste wird durch die lokale Referenz lauf von Element zu Elementdurchlaufen, bis die Referenz weiter auf null verweist.

• Nun wird auf das neu erzeugte Objekt der Klasse Element verwiesen.• Die Referenz this verweist immer auf das Objekt, für welches die Methode

FügeEin aufgerufen wurde, daher verweist this nie auf den Wert null .

Programm: Einfügen am Ende einerlinearen Liste

Erweiterung einer Liste

535

Initiales Anlegen einer linearen Liste

Anlegen einer linearen Liste:• Mit dem Konstruktor von Element wird ein erstes Objekt geschaffen.• Alle weiteren Listenelemente werden durch FügeAn für das erste Element

angefügt.

Element kopf;

kopf = new Element(25);

kopf.FügeAn(22);

kopf.FügeAn(28);

• Die Methode FügeAn wird für das erste Element der Liste aufgerufen.• Jetzt wird mit lauf die gesamte Liste bearbeitet.

kopf null2825 22

536

Rekursives AnfügenRekursives Vorgehen:

void RekFügeAn(int neuerWert) {

if (weiter != null)

weiter.RekFügeAn(neuerWert);

else

weiter = new Element(neuerWert);

}

Beachte:Die Ausführung der Methode RekFügeAn ist aufwendiger, als die bishervorgestellten Methoden, da alle Aufrufe von RekFügeAn ineinandergeschaltet sind und erst dann beendet werden, wenn das neue Elementangefügt ist.

Programm: Einfügen auf der Basis einesrekursiven Vorgehens

Page 134: Java

537

Konstruktion einer Liste durch weiteres Anfügen

void FügeEin(int neuerWert) {

Element neuesElement = new Element(wert);

neuesElement.weiter = weiter;

weiter = neuesElement;

wert = neuerWert;

}

kopf.FügeEin(17) wird nun auf die Liste

angewendet

Programm: Methode FügeEin

kopf null2825 22

538

Konstruktion einer Liste durch Einfügen

kopf null2825 22

kopf null25 25 22 28

kopf null25 282217

17

zuweisen mit Konstruktor

zuweisen

Alles andere würde bedeuten, daß kopf umgesetzt wird.

Das aber würde bedeuten, daß ein Element den Zugriff auf sich abtritt.

Das geht nicht, also bleibt nur der Weg über das Einfügen an

der zunächst zweiten Stelle.

539

Klasse lineare ListeUmsetzen von linearen Listen mit der Klasse Element und den

Methoden FügeAn und FügeEin :

Aufbau einer Liste aus einer „leeren“ Liste:Da die Methoden FügeAn und FügeEin Bestandteile der Objekte derKlasse Element sind, können sie nur dann aufgerufen werden, wenn auchein solches Element besteht. Daher muß das erste Element einer Listeimmer über einen Konstruktor erzeugt werden, alle weiteren können dannüber die Methoden hinzugefügt werden. Innerhalb eines Programms mußdaher vor jedem Aufruf von FügeAn oder FügeEin überprüft werden, obdie Referenz auf die Liste auf null verweist. Übersichtlicher wäre eshingegen, in allen Situationen Elemente durch dieMethoden FügeAn und FügeEin hinzufügen zu können.

540

Änderung des ersten Elementes:Die Implementierung der Methode FügeEin hat gezeigt, daß dasHinzufügen eines neuen Objektes als erstes Element der Liste nichtmöglich ist; hierfür muß auf entsprechende Zuweisungen zurückgegriffenwerden. Ebenso problematisch ist das Löschen des ersten Elementes einerListe. Insbesondere das letzte Element einer Liste läßt sich nicht durch eineMethode der Klasse Element entfernen.

Klasse lineare Liste

Page 135: Java

541

Effizienz der Methode FügeAn:

Die Methode FügeAn erfordert bei jedem Aufruf ein vollständigesDurchlaufen der Liste. Eine sehr viel effizientere Realisierung dieserListenoperation wäre möglich, wenn neben dem ersten Element auch dasletzte Element der Liste unmittelbar erreichbar wäre.

Klasse lineare Liste

542

Verbesserungsmöglichkeiten

• Die Idee, eine Liste mit einer Referenz auf ihr erstes Elementgleichzusetzen, wird dem Umgang mit der entstehendenDatenstruktur nicht gerecht.

• Der Wertebereich einer Klasse, die lineare Listenimplementiert, sollte auch die leere Liste beinhalten und fürdiese eine korrekte Anwendung der Methoden garantieren.

• Die Ausführung von Methoden sollte durch zusätzlicheReferenzen auf ausgewählte Elemente der Liste unterstütztwerden.

• Als Ergebnis entstehen die folgenden, modifizierten KlassenElement und Liste

543

class Element {private int wert;private Element weiter;Element(int i) { wert = i; weiter = null; }Element(int i, Element e) { wert = i; weiter = e; }void SetzeWert(int i) {

wert = i;

}int GibWert() {

return wert;

}void SetzeWeiter(Element e) {

weiter = e;

}Element GibWeiter() {

return weiter;

}}

Klasse Element (verbessert)

544

class Liste {private Element kopf, fuß;Liste() { kopf = fuß = null; }Liste(int w) { kopf = fuß = new Element(w); }void FügeAn(int an) {

Element neu = new Element(an);

if (fuß != null) {

fuß.SetzeWeiter(neu);

fuß = neu;

}

else

kopf = fuß = neu;

}void FügeEin(int ein) {

kopf = new Element(ein, kopf);

if (fuß == null)

fuß = kopf;

}}

Klasse lineare Liste (verbessert)

Page 136: Java

545

Beispiel Anfügen und Einfügen

Liste eineListe = new Liste();

eineListe.FügeAn(15);

eineListe.FügeAn(52);

eineListe.FügeEin(34)

kopf null fuß

fußnull15kopf

15kopf fußnull52

546

Liste eineListe = new Liste();

eineListe.FügeAn(15);

eineListe.FügeAn(52);

eineListe.FügeEin(34) ein 34

15kopffußnull52

ein 34

15kopffußnull52

ein 34

15kopf fußnull52

Beispiel Anfügen und Einfügen

547

Anwendungsbeispiel

• Einordnen eines Werts in eine bereits aufsteigend geordnete Liste• Keine zwei Elemente haben die identische Belegung des Attributs wert

• Der Algorithmus ist auf natürliche Weise rekursiv

Die Idee:Ist eine ganze Zahl x gegeben, so daß x kleiner als das erste Element der Liste ist,so füge man x am Anfang der Liste ein. Muß x in der Mitte der Liste eingefügtwerden, so suche man die entsprechende Position, spalte dort die Liste in einenAnfangs- und einen Endteil auf und füge x am Anfang des Listenrestes ein.Schließlich verbinde man das Ende des Anfangsteils der Liste mit der soentstandenen neuen Liste. Ist x größer als das letzte Element der Liste, so bildetdas neue Element allein den neuen Rest: x wird angefügt.

548

Präzisierung des Algorithmus:Folgende Fälle sind zu unterscheiden:

• kopf == null:

Einen Sonderfall bildet die Situation, daß die Liste leer ist, also noch kein Elemententhält. Es muß ein erstes Element angelegt werden, das sicherlich eine geordnete,einelementige Liste bildet.

• kopf != null:

Wir definieren eine private Methode Positioniere , die als Parameter deneinzuordnenden Wert und eine Referenz auf den Anfang einer Teilliste übergebenbekommt. Als Ergebnis gibt Positioniere eine Referenz auf Element zurück, dieauf die Teilliste verweist, in die x einsortiert ist.

Anwendungsbeispiel

Page 137: Java

549

Sei anfang die an Positioniere übergebene Teilliste und gelte:

• x < anfang.wert:

Erzeuge ein neues Element und füge es am Anfang der bei anfang

beginnenden Teilliste ein.

• x > anfang.wert:

Füge x in die mit anfang.weiter beginnenden Restliste ein, indemhierfür Positioniere mit den entsprechenden Parametern erneut

aufgerufen wird.

Anwendungsbeispiel

550

Beachte:

• Keine doppelten Einträge werden zugelassen.• Die Referenz fuß verweist auch nach dem Einsortieren auf das

letzte Element.• Wenn Positioniere die leere Referenz null als Wert für den

Parameter anfang übergeben bekommt, muß fuß korrigiertwerden und auf das neu eingeordnete letzte Objekt gesetztwerden.

Anwendungsbeispiel

551

Einordnen mit Hilfe von Positioniere

class Liste {private Element kopf, fuß;Liste() { kopf = fuß = null; }Liste(int w) { kopf = fuß = new Element(w); }…void OrdneEin(int i) {

kopf = Positioniere(kopf, i);}

Programm: Einordnen in eine geordnete Liste

552

Einordnen mit Hilfe von Positioniere

private Element Positioniere(Element anfang, int i) {if (anfang == null)

fuß = anfang = new Element(i);else {

if (i < anfang.GibWert()) {anfang = new Element(i, anfang);

}if (i > anfang.GibWert())

anfang.SetzeWeiter(Positioniere(anfang.GibWeiter(), i));

}

return anfang;}…

}

Programm: Einordnen in eine geordnete Liste

Page 138: Java

553

Durchlaufen einer Struktur

Programm: Rekursive Methode zum Druckeneiner verketten Liste

• In vielen Anwendungen, die auf dynamischen Datenstrukturenbasieren, besteht die Notwendigkeit, alle Elemente der Strukturgenau einmal zu besuchen. Dies gilt für Listen wie für anderedynamische Strukturen.

• Dieses möglichst nur einmalige Besuchen aller Elemente nenntman Durchlaufen einer Struktur.

• Anwendungsbeispiele: Prüfen auf Vorhandensein, Einsortieren• Konkrete Ausprägungen dieses Problems spielen in der

theoretischen Informatik eine wichtige Rolle (TravellingSalesman Problem).

554

Durchlaufen einer Listeclass Liste {

void RekDrucke() {

RekDrucke(kopf);

}

private void RekDrucke(Element aktuell) {

if (aktuell != null) {

System.out.println(aktuell.GibWert());

RekDrucke(aktuell.GibWeiter());

}

}

} Programm: Rekursive Methode zum Druckeneiner linearen Liste

555

void IterDrucke() {

Element aktuell = kopf;

while (aktuell != null) {

System.out.println(aktuell.GibWert());

aktuell = aktuell.GibWeiter();

}

}

Programm: Iterative Methode zum Druckeneiner linearen Liste

Durchlaufen einer Liste

556

Durchlauf einer Liste in umgekehrter Reihenfolge:

• Referenz fuß verweist zwar auf das letzte Element einer Liste,kann jedoch nicht von dort zum vorletzten Element gelangen.

• Für eine umgekehrte Ausgabe müssen alle Listenelementegemerkt werden, während die Liste vom Anfang zum Endedurchläuft.

• Erst nach einmaligem Durchlaufen kann vom letzten bis zumersten Element gedruckt werden.

Durchlaufen einer Liste

Page 139: Java

557

void ReversivDrucke() {

ReversivDrucke(kopf);

}

private void ReversivDrucke(Element aktuell) {

if (aktuell != null) {

ReversivDrucke(aktuell.GibWeiter());

System.out.println(aktuell.GibWert());

}

}Programm: Ausgabe einer Liste in umgekehrter

Reihenfolge

Durchlaufen einer Liste

558

Doppelt verkettete Listen

• Ist der Durchlauf vom Ende einer Liste zu ihrem Anfang häufigbenötigt, dann ist die lineare Verkettung von vorne nach hintennicht der ideale Navigationspfad.

• Besser wäre es dann auch eine Rückwärtsverkettung zuhaben.

• Auf Grund dieser Überlegung kommt man zu doppeltverketteten Liste (einmal von vorne nach hinten, einmalumgekehrt).

559

Doppelt verkettete Listen

• Die lokale Klasse Element enthält eine zweite Referenz voran ,die genau entgegengesetzt zu weiter gerichtetist und somit für jedes Element innerhalb der Liste auf seinendirekten Vorgänger verweist.

• Mit doppelt verketteten Listen kann in beide Richtungen einerListe navigiert werden und deshalb komplexe Operationen aufeiner Liste unterstützen.

• In Java: LinkedList (Unterklasse vonAbstractSequentialList in java.util)

560

class DElement {… // die bekannten Deklarationen der linearen Listeprivate DElement voran, weiter;void SetzeVoran(DElement e) { voran = e; }Element GibVoran() { return voran; }

}class DListe {

… // die bekannten Deklarationen der linearen Listevoid FügeAn(int an) {

DElement neu;neu = new DElement(an);if (fuß != null) {

fuß.SetzeWeiter(neu);neu.SetzeVoran(fuß);fuß = neu;

} elsekopf = fuß = neu;

}void OrdneEin(int i) {

kopf = Positioniere(kopf, i);}

Doppelt verkettete Listen

Page 140: Java

561

private DElement Positioniere(DElement anfang, int i) {if (anfang == null)

anfang = new DElement(i);anfang.SetzeVoran(fuß);fuß = anfang;

else {if (i < anfang.GibWert()) {

DElement neu = new DElement(i, anfang);

neu.SetzeVoran(anfang.GibVoran());anfang.SetzeVoran(neu);if (neu.GibVoran != null)

neu.GibVoran().SetzeWeiter(neu);anfang = neu;

}if (i > anfang.GibWert())

anfang.SetzeWeiter(Positioniere(anfang.GibWeiter(), i));

}

return anfang;}

Doppelt verkettete Listen

562

void ReversivDrucke() {

DElement aktuell = fuß;

while (aktuell != null) {

System.out.println(aktuell.GibWert());

aktuell = aktuell.GibVoran();

}

}

}

Doppelt verkettete Listen

563

Exkurs: java.util - Hilfsklassen

Umfaßt Interfaces und Klassen, um unterschiedlicheDatenstrukturen zu realisieren, insbesondere:

• Interfaces:– Enumeration für Objekte, die mehrere Elemente generieren– Set für Mengen ohne doppelte Elemente

• Klassen:– Vector : Mehr Flexibilität als [] -Arrays– Stack : Stapel für allgemeine Objekte, abgeleitet von Vector

– LinkedList: für doppelt verkettete Listen– StringTokenizer : Einfaches Zerlegen von Strings– Random: Zufallsgenerator

(für Kryptographie: java.security.SecureRandom )

– Verschiedene Kalender und Datumsklassen564

java.util.Vector

• Klasse java.util.Vector– public Object[] toArray()

• Wandelt Vector in ein Array vom Basistyp Object

– public int size()• Gibt Anzahl der enthaltenen Komponenten zurück

– public boolean contains(Object elem)• Prüft, ob ein Objekt enthalten ist. Gleichheit wird mit equals() überprüft.

– public int indexOf(Object elem)• Gibt Index eines Objektes zurück. Gleichheit wird mit equals() überprüft.

– public Object elementAt(int index)• Gibt Element an entsprechender Position zurück

– public void insertElementAt(Object obj, int index)

– public void removeElementAt(int index)• Fügt Objekt an Position ein, bzw. entfernt Objekt

Page 141: Java

565

• Zugriff auf Elemente mit einem Index (analog zu Arrays)

• Abarbeiten der Liste mit einem Enumeration - Objekt

public interface Enumeration {

// liefert true, falls noch Elemente vorhanden sind

public abstract boolean hasMoreElements();

// liefert das nächste Objekt der Aufzählung

public abstract Object nextElement();

}

java.util.Vector

566

• Methode elements() von Vector liefert ein Enumeration -Objekt

Vector v = new Vector();

Person p1 = new Person( “ Urs“, “ Müller“, “ Hauptstr. 1“, “ 12345“, “ Berlin“);

Person p2 = new Person( “ Max“, “ Muster“, “ Südwall 1“, “ 44332“,“Dortmund“);

v.addElement(p1);

v.addElement(p2);

for (Enumeration el = v.elements(); el.hasMoreElements(); ) {

Person p = (Person) el.nextElement();

String inhaber = p.toString();

Bildschirm.gibAus(inhaber);

}Explizites Typcasting durchvorangestellte runde Klammern:

Person p = (Person) el.nextElement();

Das Interface Enumeration

567

• add (int index, Object element)• addFirst (Object element)• addLast (Object element)• get (int index)• remove (int index)• remove (Object o) löscht das erste Auftreten des Elementes o• getFirst()• getLast()• size() gibt die Anzahl der Elemente zurück

Methoden der Klasse LinkedList

Kapitel 17.2

Bäume

Page 142: Java

569

• Bäume sind hierarchische Strukturen. Man kommt von einerWurzel zu inneren Knoten und letztlich zu Blättern.

• Es gibt keine Zyklen zwischen Mengen von Knoten.• Bäume sind damit auch verkettete Strukturen, die dynamisch

wachsen und schrumpfen können.• Binäre Bäume sind Bäume, in denen jeder Knoten maximal

zwei Söhne hat (zur Definition siehe vorne).• Ein Beispiel für die nützliche Anwendung binärer Bäume ist

das Heapsort von weiter vorne.• Eine andere Anwendung binärer Bäume sind die binären

Suchbäume.

Allgemeines zu Bäumen

570

• Typische Zugriffsmethoden– einfügen einer Wurzel– einfügen eines inneren Knotens– entfernen der Wurzel– entfernen eines inneren Knotens– suchen– nach links/rechts navigieren

Allgemeines zu Bäumen

571

Binäre Suchbäume

Die Grundidee

Ein vorgelegtes Element x wird in einer geordneten Mengegesucht, es wird rekursiv vorgegangen.

Man beschaffe sich das mittlere Element der geordneten Menge undvergleiche es mit dem vorgelegten Element x. Stimmt das mittlere Elementmit x überein, so ist man fertig; ist x kleiner, so wende man diese Idee aufalle Elemente an, die kleiner als das mittlere Element sind; ist x größer,wende man die Idee auf alle Elemente an, die größer als das mittlereElement sind. So kommt man durch fortgesetztes Halbieren sehr schnell zuder Entscheidung, ob x in der vorgegebenen Menge liegt oder nicht.

572

Definition:Sei B ein binärer Baum, dessen Knoten mit ganzen Zahlenbeschriftet sind. B heißt binärer Suchbaum, falls gilt:

B ist leer oder

– der linke und der rechte Unterbaum von B sind binäre Suchbäume,– ist w die Beschriftung der Wurzel, so sind alle Elemente im linken

Unterbaum kleiner als w, alle Elemente im rechten Unterbaum größerals w.

Binäre Suchbäume

Page 143: Java

573

Beispiel für einen binären Suchbaum:

16

10

9 14

13 15

18

24

Binäre Suchbäume

574

• Der Aufbau eines binären Suchbaums erfolgt durchwiederholtes Einfügen in einen leeren Baum.

• Die Reihenfolge der Werte, die in einen binären Suchbaumeingefügt werden, bestimmt die Gestalt des Baumes.

• Eine Menge von Werten kann bei unterschiedlichenEingabereihenfolgen zu verschiedenen Repräsentationen alsBaum führen.

Binäre Suchbäume

575

Beispiele:

1

2

3

3

2

1

2

1 32

1

3

Eingabefolge 1 2 3

Eingabefolge 3 2 1

Eingabefolge 3 1 2Eingabefolge 2 1 3 oder 2 3 1

Binäre Suchbäume

576

class Knoten {

private int wert;

private Knoten links, rechts;

Knoten(int i) { wert = i; links = rechts = null; }

void SetzeWert(int i) { wert = i; }

int GibWert() { return wert; }

void SetzeLinks(Knoten k) { links = k; }

Knoten GibLinks() { return links; }

void SetzeRechts(Knoten k) { rechts = k; }

Knoten GibRechts() { return rechts; }

};

Binäre Suchbäume - die Klasse Knoten

Page 144: Java

577

Algorithmus für das Einfügen von Knoten

Gegeben seien ein binärer Suchbaum B und eine ganze Zahl k, die in Beingefügt werden soll. Es können vier Fälle auftreten:

• B ist leer: Erzeuge einen neuen Knoten, weise ihn B zu und setze B.wertauf k.

• B ist nicht leer und B.wert = k: Dann ist nichts zu tun, da keine doppeltenEinträge vorgenommen werden sollen.

• B ist nicht leer und B.wert < k: Füge k in den rechten Unterbaum von B ein.

• B ist nicht leer und B.wert > k: Füge k in den linken Unterbaum von B ein.

Binäre Suchbäume

578

class BST {

private Knoten wurzel;

BST() { wurzel = null; }

void FügeEin(int i) {

wurzel = FügeEin(wurzel, i);

}

Die Klasse Binary Search Tree (BST)

579

private Knoten FügeEin(Knoten aktuell, int ein) {

if (aktuell == null)

aktuell = new Knoten(ein);

else {

if (ein < aktuell.GibWert())

aktuell.SetzeLinks

(FügeEin(aktuell.GibLinks(), ein));

if (ein > aktuell.GibWert())

aktuell.SetzeRechts

(FügeEin(aktuell.GibRechts(), ein));

}

return aktuell;

}

}

Die Klasse Binary Search Tree (BST) - Einfügen

580

Algorithmus für die Suche von Konten

Der am Beginn dieses Kapitels skizzierte Algorithmus für das binäreSuchen läßt sich nun mit der durch die Methode FügeEin aufgebautenDatenstruktur recht einfach realisieren.

Gegeben sind ein binärer Suchbaum B und eine Zahl k,die in dem Baum B gesucht werden soll:

B ist leer: k kann nicht im Baum sein.B ist nicht leer, so betrachtet man die Fälle

B.wert = k : k ist gefunden, d.h. bereits in dem Baum B vorhanden.B.wert < k : Suche im rechten Unterbaum von B.B.wert > k : Suche im linken Unterbaum von B.

Binäre Suchbäume

Page 145: Java

581

class BST {...boolean Suche(int i) {

return Suche(wurzel, i);}private boolean Suche(Knoten aktuell, int i) {

boolean gefunden = false;if (aktuell != null) {

gefunden = (aktuell.GibWert() == i) ;if (aktuell.GibWert() < i)

gefunden = Suche(aktuell.GibRechts(), i);if (aktuell.GibWert() > i)

gefunden = Suche(aktuell.GibLinks(), i);}return gefunden;

}...

}

Die Klasse Binary Search Tree (BST) - Suchen

582

Suchen in binären Suchbäumen

Definition:

Ist B ein binärer Baum, so definiert man die Höhe h(B) von B rekursiv durch:

h(B):={

Ist B ein binärer Suchbaum mit h(B)=n, so enthält B mindestens n und höchstens2n-1 Knoten, nämlich n, wenn der Baum zur Liste degeneriert ist, und 2n-1, wennjeder von 2n-1-1 inneren Knoten genau zwei Söhne und jedes von 2n-1 Blätternkeine Söhne hat.

0, falls B leer ist1 + max {h(B1), h(B2)}, falls B1 und B2 linker bzw.

rechter Unterbaum von B sind

583

Behauptung : In einem beliebigen binären Suchbaum B, braucht man für eineerfolglose Suche maximal h(B) Vergleiche

Beweis : durch vollständige Induktion nach dem Aufbau von B.

Induktionsanfang : Ist B leer, also h(B)=0, so ist kein Vergleich nötig.

Induktionsschritt : Wenn für zwei Bäume B1 und B2 mit der Höhe n gilt,daß in jedem eine erfolglose Suche in maximal n Vergleichen möglich ist,so gilt für den binären Suchbaum mit einer neuen Wurzel und derenUnterbäume B1, B2, dass maximal n+1 Vergleiche nötig sind.Beweis des Induktionsschrittes : Durch Wurzelvergleich (ein Vergleich)wird ermittelt, ob im linken oder rechten Teilbaum weitergesucht werdenmuß. Die maximale Zahl der Vergleiche in einem Teilbaum ist n. Also,braucht man insgesamt maximal n+1 Vergleiche. In einem Baum der Höhen+1 braucht man also maximal n+1 Vergleiche.

Suchen in binären Suchbäumen

584

Daraus ergibt sich:

Bei einer erfolglosen Suche in einem binären Suchbaum mit n Elementensind mindestens log n (Basis 2) und höchstens n Vergleiche notwendig.

Der günstige Fall (log n Vergleiche) gilt in einem minimal ungleichgewichtigenBaum. Der ungünstige (n Vergleiche) gilt in einem vollständig degeneriertenBaum, der beispielsweise immer dann entsteht, wenn die Elemente insortierter Reihenfolge eintreffen.

Um diese Unsicherheit auszuräumen (und somit eine Laufzeit auf der Basisvon log n Vergleichen sicherzustellen), werden balancierte, binäreSuchbäume benutzt.

Suchen in binären Suchbäumen

Page 146: Java

585

Eine Art balancierter, binärer Suchbäume sind die AVL-Bäume (nach ihrenErfindern Adelson, Velskii, Landis).

Def.: Ein AVL-Baum ist ein binärer Suchbaum, in dem sich für jeden Knotendie Höhen seiner zwei Teilbäume um höchstens 1 unterscheiden.

Einfüge- und Entferne-Operationen werden dann etwas aufwendiger, aberdafür ist die Suche auch in ungünstigen Fällen effizienter (mehr dazu in derVorlesung Datenstrukturen).

Suchen in binären Suchbäumen

586

Schema der vollständigen Induktion über Bäumen

• Spezifikation der Behauptung S(T), wobei T ein Baum ist.• Beweis, daß S(T) gilt für Bäume, die nur einen Knoten haben.

• Aufsetzen des Induktionsannahme, T ist ein Baum mit Wurzel w und k ≥1Unterbäume, T1, ..., Tk. Annahme, daß S(Ti) gilt für i ∈ 1,2, ..., k

• Beweis, daß S(T) unter der Induktionsannahme gilt.

587

Entfernen der Wurzel aus einem binären Suchbaum

Algorithmus für das Entfernen

• Entfernen der Wurzel führt zur Konstruktion eines neuen binärenSuchbaums.

• Darum: Finden eines Knotens, der an die Stelle der Wurzel gesetzt wird unddie Kriterien für einen neuen binären Suchbaum erfüllt.

• Der Knoten muß größer als die Wurzel des linken Unterbaumes sein undkleiner als die Wurzel des rechten Unterbaumes.

588

16

10

9 14

13 15

18

24

Kandidaten

15

10

9 14

13

18

24

Situation vor dem Löschen Situation nach dem Löschen

Entfernen der Wurzel - Beispiel

Page 147: Java

589

Algorithmus für das Entfernen

• Es wird der Knoten mit der größten Beschriftung im linken Unterbaumgenommen.

• Dieser Knoten wird entfernt und als Wurzel eingesetzt.• Ist der linke Unterbaum einer Wurzel leer, nimmt man analog zur

vorgestellten Methode das kleinste Element der rechten Wurzel.• Ist der Unterbaum einer Wurzel leer, kann auch auf eine Umgestaltung

des Baumes verzichtet werden: Wird die Wurzel entfernt, bildet derverbleibende Unterbaum wieder einen binären Baum.

Entfernen der Wurzel aus einem binären Suchbaum

590

Wird ein innerer Knoten aus einem binären Suchbaum entfernt,stellt dieser Knoten die Wurzel eines Unterbaumes dar unddiese Wurzel wird dann entfernt.

Entfernen eines Knotens aus einem binären Suchbaum

591

Durchlaufstrategien für binäre Suchbäume

• Tiefendurchlauf : Hier wird von einem Knoten aus in die Tiefegegangen, indem einer der Söhne besucht wird und danndessen Söhne usw. Erst wenn man die Blätter erreicht hat,beginnt der Wiederaufstieg.– Preorder-Durchlauf– Inorder-Durchlauf– Postorder-Durchlauf

• Breitendurchlauf : Mit dem Besuch eines Knotens werdenauch seine Nachbarn besucht.„Schichtweises Abtragen“

592

Dynamische Datenstrukturen Binäre Suchbäume

Tiefendurchlauf / Preorder

void PreOrder() {PreOrder(wurzel); }

private void PreOrder(Knoten aktuell) {

if (aktuell != null) {

System.out.println(aktuell.GibWert());

PreOrder(aktuell.GibLinks());

PreOrder(aktuell.GibRechts());

}

}

16

10

9 14

13 15

18

24

Reihenfolge der besuchten Knoten: 16, 10, 9, 14, 13, 15, 24, 18

Page 148: Java

593

Tiefendurchlauf / Inorder

void InOrder() { InOrder(wurzel); }

private void InOrder(Knoten aktuell) {

if (aktuell != null) {

InOrder(aktuell.GibLinks());

System.out.println(aktuell.GibWert());

InOrder(aktuell.GibRechts());

}

}

16

10

9 14

13 15

18

24

Reihenfolge der besuchten Knoten: 9, 10, 13, 14, 15, 16, 18, 24594

void PostOrder() { PostOrder(wurzel); }

private void PostOrder(Knoten aktuell) {

if (aktuell != null) {

PostOrder(aktuell.GibLinks());

PostOrder(aktuell.GibRechts());

System.out.println(aktuell.GibWert());

}

}

16

10

9 14

13 15

18

24

Reihenfolge der besuchten Knoten:

9, 13, 15, 14, 10, 18, 24, 16

Tiefendurchlauf / Postorder

595

16

10

9 14

13 15

18

24

Reihenfolge der besuchten Knoten: 16, 10, 24, 9, 14, 18, 13, 15

Breitendurchlauf

596

• Noch nicht besuchte Knoten werden in einer verketteten Listegespeichert, so daß der Knoten, der als nächster besucht wird,am Anfang der Liste steht.

• Wird ein Knoten besucht, so wird er aus der Liste entfernt und sein linkerund sein rechter Sohn werden, falls vorhanden, in dieser Reihenfolge ansEnde der Liste angefügt.

• Dies geschieht solange, bis die Liste leer ist.• Die Liste wird mit der Wurzel des Baumes initialisiert.• Insgesamt wird also durch die Liste eine Warteschlange von Knoten

aufgebaut:Der Knoten am Anfang der Warteschlange wird als nächsterausgedruckt.Der Knoten am Ende der Warteschlange ist als

letzter hinzugefügt worden.

Idee zur Realisierung des Breitendurchlaufs

Page 149: Java

597

Dynamische Datenstrukturen Binäre Suchbäume

Warteschlange für die Breitensuche16

10

9 14

13 15

18

24

ws null

ws null

16

10

9 15

13 14

18

24

nach Besuch des Knotens16, vor Besuch des Knotens10

nach Besuch des Knotens 10

598

Breitendurchlauf durch einen binären Suchbaumclass BST {

...

void Breitendurchlauf() {

SohnListe ws = new SohnListe();

Knoten aktuell;

ws.FügeAn(wurzel);

while ((aktuell = ws.Entferne()) != null) {

System.out.println(aktuell.GibWert());

if (aktuell.GibLinks() != null)

ws.FügeAn(aktuell.GibLinks());

if (aktuell.GibRechts() != null)

ws.FügeAn(aktuell.GibRechts());

}

}

...

}

599

Die Klasse SohnElem

class SohnElem {

private Knoten wert;

private SohnElem weiter;

SohnElem(Knoten k) { wert = k; weiter = null; }

void SetzeWert(Knoten k) { wert = k; }

Knoten GibWert() { return wert; }

void SetzeWeiter(SohnElem s) { weiter = s; }

SohnElem GibWeiter() { return weiter; }

}

600

class SohnListe {

private SohnElem kopf, fuß;

SohnListe() { kopf = fuß = null; }

void FügeAn(Knoten an) {

SohnElem neu = new SohnElem(an);

if (fuß != null) {

fuß.SetzeWeiter(neu);

fuß = neu;

} else

kopf = fuß = neu;

}

Die Klasse SohnListe

Page 150: Java

601

Knoten Entferne() {

Knoten erster = null;

if (kopf != null) {

erster = kopf.GibWert();

kopf = kopf.GibWeiter();

if (kopf == null)

fuß = null;

}

return erster;

}

}

Die Klasse SohnListe

Kapitel 17.3

Graphen

603

Allgemeines zu Graphen

Programm: Die Klasse SohnListe

• Listen stellen eindimensionale Verkettungen von Informationendar: Jeder Knoten einer Liste hat einen oder keinen Nach-folger.

• Binäre Bäume stellen eine zweidimdensionale Informations-verkettung dar: Jeder Knoten ist mit höchstens zwei Söhnenverbunden.

• Graphen stellen für jeden Knoten dar, in welcher Weise diesermit anderen Knoten gerichtet verbunden ist.

604

• Eine der originären Anwendungen ist die Darstellungräumlicher Beziehungen, Bäume reichen hier nicht aus, weil esBeziehungen zwischen allen Knoten geben kann.

• Oft ist es so, daß den Kanten zwischen zwei Knoten auch nochAttribute zugeordnet werden (Kosten, Entfernungen, etc.).

• Wenn die Beziehung zwischen zwei Knoten unabhängig vonder Richtung ist (Erreichbarkeit zwischen Orten), dann reichenungerichtete Kanten.

• Wenn die Beziehung von der Richtung abhängt (eine Stellungim Schach läßt sich per Zug aus einer anderen erreichen),dann braucht man gerichtete Kanten.

Allgemeines zu Graphen

Page 151: Java

605

Allgemeines zu Graphen

Typische Methoden:

• das Erzeugen eines neuen Graphen• das Einfügen oder Löschen eines Knotens• das Einfügen oder Löschen einer Kante• den Test, ob ein Knoten vorhanden ist• den Test, ob eine Kante vorhanden ist

606

Programm: Die Klasse SohnListe

G = (V, E) heißt gerichteter Graph mitKnotenmenge V und Kantenmenge E, falls gilt:

V (englisch: vertex, vertices) ist eine endlicheMenge und

E (englisch: edges) ⊆ V × V

Definition Graph

607

2

1

3

8

9

7

4

6

5

Beispiel eines gerichteten Graphen

608

Sei G = (V, E) ein gerichteter Graph, so besteht ein Pfad ausKnoten (p0, p1,…, pk) von p0 nach pk für k > 0 aus Knotenp0, … , pk ∈ V, so daß jedes Paar aufeinanderfolgender

Knoten (pi, pi+1) eine Kante bildet. Dies gilt für 0 ≤ i ≤ k-1.

Ein Zyklus ist ein Pfad von einem Knoten zu sich selbst.

Definition Pfad

Page 152: Java

609

Ein gerichteter Graph heißt stark zusammenhängend , wennes zwischen je zwei Knoten des Graphen einen Pfad gibt.

Ein gerichteter Graph heißt schwach zusammenhängend ,wenn es zwischen zwei Knoten immer einen Semiweg gibt.Ein Semiweg ist ein Pfad, wobei von der Richtung der Kantenabgesehen wird.

Definition Zusammenhang

610

Ein Teilgraph heißt Zusammenhangskomponente , wenn erbzgl. der Zusammenhangseigenschaft (stark oder schwach)maximal ist, d.h. der Teilgraph kann nicht durch einen odermehrere Knoten und/oder eine oder mehrere Kanten desGraphen erweitert werden, ohne diese Eigenschaft zuverlieren.

Definition Zusammenhang

611

Graphen werden rechnerintern durch Adjazenzlisten oderAdjazenzmatrizen dargestellt werden.

Speicherdarstellung von Graphen

612

Ist n ∈ V ein Knoten im gerichteten Graphen (V, E), so heißt{p ∈ V; (n, p) ∈ E}die Adjazenzliste zum Knoten n.

Eine Alternative zu dieser Darstellung ist die Darstellungüber Boolesche Matrizen:Man definiere eine Matrix (ak,l)k,l ∈∈∈∈ V und setze:

ak,l :=((k,l) ∈ E)

Adjazenz von Knoten

Page 153: Java

613

Knoten Adjazenzliste

1 5

2 1, 3

3 (leer)

4 2, 8

5 2, 3, 7, 8

6

7 (leer)

8 7

9 6

2

1

3

8

9

7

4

6

5

Beispiel Adjazenzliste

614

2

1

3

8

9

7

4

6

5

Adjazenzmatrix

Beispiel Adjazenzmatrix

615

Der Platzverbrauch von Adjazenzmatrizen ist unabhängig vonder Zahl der Kanten pro Knoten. Bei n Knoten werden n2

Speicherplätze gebraucht.

In Adjazenzmaztrizen läßt sich schnell prüfen, ob eine Kantevorhanden ist (indizierter Zugriff auf zweidimensionales Array).

Adjazenzlisten brauchen Speicherplatz pro Kante. Wenn wenigKanten vorkommen, dann wird auch wenig Platz gebraucht.Bei vielen Kanten muß man beim Suchen nach einer Kanteerst eine ggf. lange Kantenliste durchlaufen.

Adjazenz von Knoten

616

Deshalb folgende Daumenregel:

Adjazenzlisten sind für Graphen mit wenig Kanten pro Knotengeeignet.

Adjazenzmatrizen sind für dichte Graphen geeignet.

Adjazenz von Knoten

Page 154: Java

617

Klassen Knoten, ..., Graph

class Graph {private Knoten erster;…

}

class Knoten {private int name;private KnotenListeadjazenz;private Knoten nächster;…

}

class KnotenListe {private KnotenElem kopf,fuß;…

}

class KnotenElem {Knoten verweis;KnotenElem weiter;…

}

618

Listendarstellung gerichteter Graphen

2

16

4

7

9

8

5

3

erster

619

Realisierung der Graph-Methoden

• Das Erzeugen eines neuen Graphen erfolgt durch den Aufrufeine Konstruktors.

• Das Hinzufügen eines Knotens ist eine Listenoperation auf derListe der Knoten.

• Das Entfernen eines Knotens ist eine Listenoperation auf derListe der Knoten und auf all den Adjazenzlisten, die einenZeiger auf den zu entfernenden Knoten besitzen.– Aufwand!

620

Realisierung der Graph-Methoden

• Das Hinzufügen einer Kante ist eine Operation auf denAdjazenzlisten.

• Der Test, ob ein Knoten vorhanden ist, stellt eine Operation aufder Liste aller Knoten dar.

• Der Test, ob eine Kante vorhanden ist, stellt zunächst eineOperation auf der Liste aller Knoten - Ausgangsknoten derKante finden - und anschließend auf der entsprechendenAdjazenzliste dar.

Page 155: Java

621

Die Klasse Graph

class Graph {

private Knoten erster;

void Graph( ) { … }

void FügeKnotenEin(int kno ) { … }

void EntferneKnoten(int kno ) { … }

void FügeKanteEin(int start, int ende ) { … }

boolean IstKnotenDa(int kno ) { … }

boolean IstKanteDa(int kno1, int kno2 ) { … }

}

622

Durchlaufen mit einmaligem Besuchen

• Ausdrucken aller Knotennamen• Da Graphen keine vergleichbar reguläre Struktur haben wie

Bäume kann man keine vergleichbaren Durchlaufstrategienangeben. Durch Zyklen kann man beispielsweise auf bereitsbesuchte Knoten kommen.

• Die Klasse Knoten wird deshalb erweitert um ein AttributwarDa .

623

Ergänzung der Klasse Knoten

class Knoten {

private boolean warDa;

void SetzeWarDa(boolean wd) { warDa = wd; }

boolean GibWarDa() { return warDa; }

}

624

Durchlaufen mit einmaligem Besuchen

• Problem: Was passiert, wenn noch mal ausgedruckt werdensoll?

• Idee: Umdrehen der Werte.• Das Einfügen muß dann aber entsprechend arbeiten und die

Belegung der warDa-Attribute berücksichtigen.• Eine ganz einfache Ausgabestrategie wäre das Durchlaufen

der Knotenliste, allerdings verliert man dann jeden Aufschlussüber die Graphenstruktur.

• Deshalb wird oft ein so genannter Tiefendurchlauf benötigt.Hierdurch werden zusammenhängende Teilgraphen auchzusammenhängend ausgegeben.

Page 156: Java

625

Durchlaufen mit einmaligem Besuchen

• Erst wenn in einem Teilgraph alle Knoten besucht sind, wirdüber nächster der nächste Knoten aufgesucht.

• Wir versuchen von einem Knoten alle erreichbaren Knoten zufinden. Dabei steigen wir erst hinab und erst wieder hinauf(zum Vorgängerknoten), wenn nichts mehr gefunden wird.

• Beispiel:

626

Durchlaufen mit einmaligem Besuchen

• Das Durchlaufen der Adjazenzlisten wird durch den rekursivenAufruf von BesucheTeil für die in der Adjazenzlistevorkommenden Knoten unterbrochen.

• Die Methoden InitIteration und GeheWeiter sorgendafür, dass die Adjazenzliste dennoch nicht jedes Mal vonvorne durchlaufen werden muß.

627

Die Klasse KnotenListeclass KnotenListe {

private KnotenElem position = null;

Knoten InitIteration() {

position = kopf;

return position.Gibverweis();

}

Knoten GeheWeiter() {

position = (position != null?

Position.GibWeiter(): null);

return position.GibVerweis();

}

}

628

Tiefensuche in gerichteten Graphen

Programm: Die Tiefensuche in einemgerichteten Graphen (1/2)

class Graph {

void Durchlaufe() {

Knoten inListe;

boolean besucht = !erster.GibWarDa();

inListe = erster;

while (inListe != null) {

System.out.println(“Teilgraph:“);

if (inListe.GibWarDa() != besucht)

BesucheTeil(inListe, besucht);

inListe = inListe.GibWeiter();

}

}

Page 157: Java

629

Programm: Die Tiefensuche in einemgerichteten Graphen (1/2)

private void BesucheTeil(Knoten aktuell, boolean besucht){

KnotenListe adjazenz;

Knoten inAdjazenz;

aktuell.SetzeWarDa(besucht);

System.out.println(aktuell.GibWert());

adjazenz = aktuell.GibAdjazenz();

inAdjazenz = adjazenz.InitIteration();

while (inAdjazenz != null)

if (inAdjazenez.GibWarDa() == besucht)

inAdjazenz = adjazenz.GeheWeiter();

else

BesucheTeil(adjazenz.GeheWeiter(),besucht);

}

}

Tiefensuche in gerichteten Graphen

Kapitel 17.4

Schlangen / Queues

631

Allgemeines zu Queues

16

10

9 14

13 15

18

24

ws null

ws null

16

10

9 15

13 14

18

24

vor Besuch des Knotens 10

nach Besuch des Knotens 10

Programm: Die Klasse SohnListe

• Queues sind wichtig für die Abarbeitung von Aufgaben in derReihenfolge FIFO (first-in-first-out), wie an derSupermarktkasse

• Typische Methoden:– Prüfen auf Gefülltheit (bei beschränkten Schlangen)– Prüfen auf Leerheit– Anfügen– Entfernen (am Anfang)– Liefern des ersten Elementes– Ermittlung der Länge

632

Allgemeines zu Queues

16

10

9 14

13 15

18

24

ws null

ws null

16

10

9 15

13 14

18

24

vor Besuch des Knotens 10

nach Besuch des Knotens 10

Programm: Die Klasse SohnListe

• Queues werden realisiert über Listen, auf die mittels dergenanten Methoden zugegriffen wird.

• Da nur über diese Methoden zugegriffen wird, ist sichergestellt,daß keine anderen, nicht Queue-kompatiblen Manipulationenstattfinden.

Page 158: Java

Kapitel 17.5

Kellerspeicher / Stapel / Stacks

634

Allgemeines zu Stacks

• Stacks sind ein weiteres Beispiel für einen abstrakten Datentypund den Umgang mit verketteten Listen.

• Stacks basieren auf den Elementen wie sie in linearen Listenverwendet wurden.

• Das letzte in einem Stack abgelegte Element wird als erstesherausgenommen.

• Elemente dieser Datenstruktur werden nach dem LIFO-Prinzip(Last In First Out) verwaltet.

635

• Initialisieren eines leeren Stacks.• Testen, ob der Stack leer ist.• Ablegen eines Elements auf dem Stack

(push -Operation)• Inspektion des obersten Elementes

(top -Operation)• Entfernen des obersten Elementes des Stacks

(pop -Operation)

Methoden auf Stacks

636

Darstellung der Stack-Methoden

17

9

8

19

4

17

9

8

17

9

8

24

17

9

8

push 19

push 24

pop

pop4

Page 159: Java

637

Die Klasse Stackclass Stack {

private Element derStack;

Stack() { derStack = null; }

Stack(int i) { derStack = new Element(i); }

boolean empty() {

return derStack == null;

}

void push(int i) {

derStack = new Element(i, derStack);

}

int pop() {

int topWert = (derStack != null ? derStack.GibWert() : 0);

derStack = derStack.GibWeiter();

return topWert;

}

int top() {

return (derStack != null ? derStack.GibWert() : 0);

}

}

638

java.util.Stack

• Klasse java.util.Stack extends java.util.Vector– Stapel auf Objekten basierend mit allen geerbten Funktionalitäten von

Vector– Sehr mächtig und sehr langsam

=> für reine Stackfunktionalität Eigenimplementierung besser– public Stack()

• Konstruktor für leeren Stack

– public Object push(Object item)• Legt Objekt auf Stapelspitze

– public Object pop() throws EmptyStackException• Holt Objekt von Stapelspitze (und entfernt es)

– public Object peek() throws EmptyStackException• Gibt Referenz von Objekt auf Stapelspitze, ohne es zu entfernen

– public boolean empty()• Testet, ob Stack leer ist

639

java.util.Stack - Beispieljava.util.Stack stapel = new java.util.Stack();stapel.push("Text");stapel.push(new Integer(2));stapel.push(new Double(1e100));

System.out.println("Gesamt: " + stapel);try {

while (!stapel.empty())System.out.println("Objekt: " + stapel.pop());

} catch (java.util.EmptyStackException e) {}

Ausgabe:Gesamt: [Text, 2, 1.0E100]Objekt: 1.0E100Objekt: 2Objekt: Text

Kapitel 17.6

Mengen

Page 160: Java

641

Allgemeines zu Mengen

• ist nicht erforderlich, weil jeder Mengen kennt :-)• Interessant ist dann nur die Frage, wie Mengen rechnerintern

dargestellt werden.• Dazu gibt es zwei grundlegende Möglichkeiten:

– Charakteristische Vektoren– Hashing-Tabellen

642

Charakteristische Vektoren

• Für jedes potentielle Mengenelement wird in einem Array-Eintrag des Typs Boolean festgehalten, ob es in der Menge istoder nicht.

• Vorteil: einfache Prüfung auf Enthaltensein• Vorteil: einfache Durchführung von Mengenoperationen• Nachteil: enorme Platzverschwendung, gerade bei vielen

potentiellen Elementen und kleinen Mengen

643

Charakteristische Vektoren

• Beispiel:– Grundmenge: alle potentiellen 600 Programmierungsstudenten

(Erstsemester Informatik, Physik, Mathe)– Menge der am Vorlesungsende regelmäßig teilnehmenden

Studierenden, voraussichtlich 300.– Studierende seien gegeben durch Name, Fach– Wir nehmen an, dass der Name eindeutig ist.

• Das Prüfen, ob Studierende nach am Ende vonProgrammierung und RS noch in der Vorlesung sind, ist danneine einfach Bitoperation (UND)

• Schema der aktuellen Teilnehmermenge:

644

Charakteristische Vektoren

• Beispiel:– Grundmenge: alle Erstligavereine im DFB, also 18– Vereine seien gegeben durch offiziellen Namen, letzte Meisterschaft,

letzter internationaler Wettbewerb, Bundesland– Darzustellende Mengen:

• die in bestimmten Pokalrunden vertretenden Verein• die Menge der Meistermannschaften,• die Menge der Mannschaften aus NRW,• die Meistermannschaften aus NRW mit internationalem Titel.

Page 161: Java

645

Hashing

• Die begrenzte Einsetzbarkeit von charakteristischen Vektorenzeigt sich an sehr großen Mengen.

• Beispiel:– Grundmenge: Liste aller Wörter im Duden– Darzustellende Menge: die Menge aller Wörter auf den Prog-Folien

• Wenn wir nun die Speicherplatzverschwendung begrenzenwollen, dann stellen wir nicht mehr für jedes potentielleElement der Menge einen Speicherplatz zur Verfügung,sondern nur noch eine kleine Anzahl von Speicherplätzen, aufdie die Elemente der darzustellenden Menge abgebildetwerden.

646

Hashing

• Eine Hash-Funktion bildet die darzustellende Menge(=Teilmenge der Grundmenge) auf eine feste Anzahl vonSpeicherplätzen ab.

• Da man nicht für jedes Element der Grundmenge einenSpeicherplatz hat, werden mehrere Elemente der Grundmengeauf die gleiche Position abgebildet.

• Schema einer Hash Table:

647

Hashing

• B sei die Anzahl der Speicherplätze.• Eine Hash-Funktion h arbeitet auf den Elementen der

Grundmenge und bildet diese auf einen Wert zwischen 0 undB-1 ab. Auf Grund dieser Eigenschaft nennt man Hash-Funktionen auch Schlüsseltransformationen.

• B wird die Anzahl der „Buckets“ der Hash Table genannt.• h(x) ist der Bucket, in dem das Element x der Grundmenge zu

finden ist.• Wenn die Elemente Integer-Zahlen sind, dann ist h(x) = x mod

B eine sinnvolle Hash-Funktion

648

Hashing

• Wenn die Elemente Strings sind, dann kann man die Integer-Werte der Character addieren, die Summe ganzzahlig durch Bteilen und hat damit eine sinnvolle Hash-Funktion

Page 162: Java

649

Hashing

• Die Qualität einer Hash-Funktion hängt davon ab, ob sie dieElemente der Grundmenge gleichmäßig auf die Speicherplätzeverteilt, d.h. für beliebige darzustellende Teilmengen aus derGrundmenge soll eine gelichmäßige Verteilung auf die Bucketsstattfinden.

• Konkreter:– Eine Hash-Funktion sollte surjektiv sein, also auf alle Buckets abbilden.– Sie sollte die Elemente der Grundmenge gleichmäßig auf die Buckets

verteilen.– Sie sollte effizient zu berechnen sein.

650

Hashing

• Beispiel:– Grundmenge: Fußballvereine,– darzustellende Menge: DFB-Viertelfinal-Teilnehmer,– 8 Speicherplätze, Zuordnung über Bundesland.– Das könnte kollisionslos klappen.– Das kann aber auch ganz daneben gehen.

• Beispiel: Monatsnamen auf 17 Buckets

• Beispiel: Wörter und ASCII-Summen

651

Hashing

16

10

9 14

13 15

18

24

ws null

ws null

16

10

9 15

13 14

18

24

vor Besuch des Knotens 10

nach Besuch des Knotens 10

Programm: Die Klasse SohnListe

• Der Lastfaktor einer Hash Table ergibt sich bei BSpeicherplätzen und einer Kardinalität M der darzustellendenMenge durch M/B.

• Beispiel: Viertelfinalvereine, Monate, Wörter

• Beim offenen Hashing wird zu jedem Bucket eine dynamischeDatenstruktur (typischerweise eine verkettet Liste) benutzt.

652

Hashing

16

10

9 14

13 15

18

24

ws null

ws null

16

10

9 15

13 14

18

24

vor Besuch des Knotens 10

nach Besuch des Knotens 10

Programm: Die Klasse SohnListe

• Beim geschlossenen Hashing kann pro Bucket nur eine kleine,fest definierte Anzahl von Elementen aufgenommen werden.

– Hier braucht man dann rehashing-Verfahren, die im Fall desÜberschreitens der Grenze ein freies Plätzchen suchen.

– Das rehashing kann dabei kaskadieren.– Die feste Begrenzung kann dabei zu mühevollem Suchen führen.

Page 163: Java

653

Die Klasse java.util.Hashtable

• Kartenverwaltung: Zwei Listen (Kartennummern, PINs), die paralleldurchlaufen werden müssen

• besser: Datenstruktur, die Schlüssel und Wert gemeinsam speichert• Lösung: java.util.Hashtable

public class Hashtable extends Dictionary ... {

...

public boolean contains(Object value) {...};

public boolean containsKey(Object key) {...};

public Enumeration elements() {...};

public Enumeration keys() {...};

public Object put(Object key, Object value) {...};

public Object get(Object key) {...};

public Object remove(Object key) {...};

...

}

Hilfsklassen

654

Kartenverwaltung mit Hashtableimport java.util.*;

public class Kartenverwaltung {

private Hashtable karten;

...

public void erfasseWeiteresKonto (String kartennummer, String pin,Girokonto konto) {

karten.put(kartennummer, pin);

...

}

public boolean pinIstGültig (String kartennummer, String pin) {

String geheim = (String) karten.get(kartennummer);

return (pin.equals(geheim));

}

}

Hilfsklassen

Importieren von Klassen :

* importiert alle Klassen eines Packages

655

Übung: Hashtable

Motivation• Verwenden von Hashtable statt Arrays• Schneller Zugriff auf die gespeicherten Daten

Aufgabe• Verwenden Sie zur Speicherung der Konten ebenfalls eine Hashtable

– Überlegen Sie sich dazu, was als Schlüssel und was als Eintrag verwendetwerden kann

• Ändern Sie die Klasse Kartenverwaltung• Fügen Sie eine Methode hinzu, die zu allen Konten den Inhaber ausgibt• Testen Sie die neue Kartenverwaltung

– Verwenden Sie hierzu die alte Testklasse– Erweitern Sie die Testklasse zum Testen der neuen Methode

Hilfsklassen

656

Übung: Hashtableimport java.util.*;

public class Kartenverwaltung {

private Hashtable karten;

private Hashtable konten;

public Kartenverwaltung(){

karten = new Hashtable();

konten = new Hashtable();

}

public void erfasseWeiteresKonto (String kartennummer, String pin,

Konto einKonto) {

karten.put(kartennummer, pin);

konten.put(kartennummer, einKonto);

}

Hilfsklassen

Page 164: Java

657

Übung: Hashtablepublic Konto holeKonto (String kartennummer) throws

KontoNichtVorhandenException {

Konto k = (Konto) konten.get(kartennummer);

if (k == null) throw new KontoNichtVorhandenException();

return (k);

}

public boolean pinIstGültig (String kartennummer, String pin){

String geheimzahl = (String) karten.get(kartennummer);

return (pin.equals(geheimzahl));

}

public void listeInhaber() {

for (Enumeration el=konten.elements(); el.hasMoreElements(); ) {

Konto k = (Konto) el.nextElement();

Bildschirm.gibAus(k.holeInhaber().toString());

}

}

Hilfsklassen

658

Zusammenfassung

• Dynamische Datenstrukturen sind wesentlich für fast alle Informatik-Probleme.

• Es gibt eine natürliche Hierarchie dieser Strukturen.• Alle dynamischen Strukturen verfügen über strukturell ähnliche Methoden.• In Java sind vordefinierte Lösungen für die grundlegenden dynamischen

Strukturen verfügbar, und zwar im Paket java.util

– Listen werden mit java.util.Vector realisiert

– Stapel werden mit java.util.Stack realisiert– Realisierung von Tabellen (mit zwei Spalten) mit java.util.Hashtable

– Durchlauf durch Listen mit java.util.Enumeration

Hilfsklassen

Kapitel 18

Ein- und Ausgabe (java.io)

660

java.io Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

Page 165: Java

661

java.io - Ein- und Ausgaben, Streams

• Ergebnisse der Durchführung von Programmen müssenzuweilen persisten gemacht werden.

• Von Persistenz eines Objektes spricht man, wenn das Objektdas Ende einer Programmausführung überlebt und von einemanderen Programm (oder einer anderen Ausführung desgleichen Programms) benutzt werden kann.

• Persistent werden Objekte, indem man sie speichert.Speicherort kann das Dateisystem sein oder auch eineDatenbank (dazu mehr in der Vorlesung Informationssysteme).

• Die Beschreibung der Struktur persistenter Objekte wird dasFormat genannt.

• Wie lassen sich die Fußballvereine persistent machen?

662

java.io - Ein- und Ausgaben, Streams

• Und wie lassen sich solche persistent gemachten Objektewieder einlesen?

• Wie einigen sich Schreiber und Leser auf Formate?

• Java-Ansatz: Eine Reihe von Formaten wird in Form vonKlassen und Interfaces vordefiniert. Hierzu gehört daseigentliche Format und natürlich auch der schreibende /lesende Zugriff.

663

Streams– Ein Objekt, aus dem eine Sequenz von Bytes gelesen

werden kann, ist ein Eingabe-Stream.

– Das Schreiben von Bytes erfolgt in Ausgabe-Streams.

– Die Implementierung erfolgt mit Hilfe der abstrakten KlassenInputStream und OutputStream

– Character (Unicode) werden analog über die abstraktenKlassen Reader und Writer behandelt.

java.io - Ein- und Ausgaben, Streams

664

java.io - Ein- und Ausgaben, Streams

• In diesem Kapitel:

– Streams: Merkmale, Klassen, einfache Verwendung– Ablegen der Ergebnisse eines binären Suchbaums

Page 166: Java

665

java.io - Ein- und Ausgaben, Streams

• Ein- und Ausgaben werden über Streams realisiert(außer GUI-Komponenten!)

• Streams (Ströme) sind sequentiell organisierte Datenmengen.• Streams sind Objekte, in die Daten hineingegeben bzw. aus

denen Daten ausgelesen werden können.• Mittels des Pakets java.io werden unterschiedliche Streams

unterstützt, so dass das in vielen Programmiersprachenmühevolle Thema der Dateibehandlung vereinfacht wird.

• Grob:– InputStream als Superklasse für Eingabeströme, also Ströme, aus

denen gelesen wird.– OutputStream als Superklasse für Ausgabeströme, also Ströme, in die

geschrieben wird.

666

java.io - Ein- und Ausgaben, Streams

• Unterschiedliche Formate von Streams für– Ströme von Bytes / Ströme von Unicode-Zeichen– Schreiben oder Lesen– Unterschiedliche Ziele bzw. Quellen:

• Dateien• Standardeingabe und -ausgabe• Andere Klassen, wie z.B. Strings• Piped-Streams, in denen Schreibe- und Lesestreams gepuffert

verbunden sind• gefilterte Streams, in denen Inhalte verändert werden können• Streams für sicheren Datenaustausch zwischen Threads• Objektserialisierung

667

java.io - Ein- und Ausgaben, Streams

• Von besonderer Bedeutung: Filter

• Ein Filter verbirgt den Zugriff auf einen Strom und gruppiert(filtert) die von diesem gelesenen Informationen durchgeeignete Methoden.

• Der Filter DataInputStream stellt beispielsweise Methodenbereit, die als Ergebnis des Lesevorgangs einen Wer einesprimitiven Typs liefern.

• Der Filter FileInputStream liefert einzelne Zeichen.

• Durch diesen vordefinierten Zugriff wird die Detailkenntnis desFormats entbehrlich! 668

java.io - Ein- und Ausgaben, Streams

• In Java wird strikt unterschieden zwischen:

– der Manipulation der Inhalte einer Datei und– der Änderung des organisatorischen Rahmens (Namensänderung,

Öffnen, Schließen etc.)

– Inhaltsänderungen basieren auf Methoden der KlasseInputStream, OutputStream

– Änderungen der Rahmenbedingungen basieren auf Methoden derKlasse File

• Hinweis: Portabilität!

Page 167: Java

669

java.io

• java.io.OutputStream– abstrakte Klasse– Superklasse aller Byte Output Streams

– definiert grundlegende Methoden für alle Byte Output Stream Klassen– close unterbricht die Verbindung zwischen Programm und Datei

Die Java Klassenbibliotheken

public void close()

public void flush()

public void write(byte[] b)

670

java.io.OutputStream

• Abstrakte Klasse java.io.OutputStream :– public abstract void write(int b) throws IOException

• Schreibt ein Byte b in den Stream• muß von abgeleiteter Klasse überschrieben werden

– public void write(byte[] b) throws IOException• Schreibt ein Array von Bytes• Falls nicht überschrieben, wird write(int b) benutzt

– public void write(byte[] b, int off, int len)throws IOException

• Zusätzlich lassen sich Anfang und Ende bestimmen

– public void flush() throws IOException• Kann überschrieben werden, um eine Entleerung eines Puffers gewährleisten

zu können

671

java.io

• java.io.InputStream– abstrakte Klasse– Superklasse aller Byte Input Streams

– definiert grundlegende Methoden für alle Byte Input Stream Klassen

Die Java Klassenbibliotheken

public int available()

public void close()

public void read(byte[] b)

public void reset()

672

java.io.InputStream

• Abstrakte Klasse java.io.InputStream :– public abstract int read() throws IOException

• Liest ein Byte aus dem Stream• muß von abgeleiteter Klasse überschrieben werden

– public int read(byte[] b) throws IOException• Liest ein Array von Bytes• Falls nicht überschrieben, wird read() benutzt

– public int read(byte[] b, int off, int len)throws IOException

• Zusätzlich lassen sich Anfang und Ende bestimmen

– public int available() throws IOException• Bestimmt Anzahl der noch lesbaren Bytes

– public void close() throws IOException• Schließt Stream und läßt belegte Systemresourcen frei

Page 168: Java

673

java.io

• java.io.Writer– abstrakte Klasse– Superklasse aller Character Output Streams

– definiert grundlegende Methoden für alle Character Output StreamKlassen

Die Java Klassenbibliotheken

public void close()

public void flush()

public void write(char[] c)

674

java.io.Writer

• Abstrakte Klasse java.io.Writer :– public void write(int c) throws IOException

• Schreibt ein Zeichen c in den Stream. Untere 16 Bit werden benutzt.

– public void write(char[] cbuf) throws IOException• Schreibt ein Array von Zeichen

– public abstract void write(char[] cbuf, int off,int len) throws IOException

• Zusätzlich lassen sich Anfang und Ende bestimmen

– public void write(String str) throws IOException• Ausgabe eines Strings

– public abstract void flush() throws IOException• Muß überschrieben werden, soll eine Entleerung eines eventuellen Puffers

gewährleisten

675

java.io

• java.io.Reader– abstrakte Klasse– Superklasse aller Character Input Streams

– definiert grundlegende Methoden für alle Character Input StreamKlassen

Die Java Klassenbibliotheken

public void close()

public void read(char[] c)

public void reset()

676

java.io.Reader

• Abstrakte Klasse java.io.Reader :– public int read() throws IOException

• Liest ein einzelnes Zeichen aus dem Stream• -1 wird bei Stream-Ende zurückgegeben

– public int read(char[] cbuf) throws IOException• Liest ein Array von Zeichen• Bis Eingabe erhältlich ist, wird gewartet

– public abstract int read(char[] cbuf, int off,int len) throws IOException

• Zusätzlich lassen sich Anfang und Ende bestimmen

– public boolean ready() throws IOException• Fragt ab, ob der Stream fertig ist, um ausgelesen zu werden

– public void close() throws IOException• Schließt Stream und läßt belegte Systemresourcen frei

Page 169: Java

677

Stream Sorten• Ströme von Bytes (z. B. für Byte[] )

– Schreibende Streams sind Unterklassen von OutputStream– Lesende Streams sind Unterklassen von InputStream

• Ströme von Unicode-Zeichen (z. B. für String )– Schreibende Streams sind Unterklassen von Writer– Lesende Streams sind Unterklassen von Reader

• Abgeleitete Klassen für spezifische Zwecke sollten Namenhaben, die auf Reader , Writer , InputStream oderOutputStream enden=> Sie sind so einfach in die richtige Kategorie einzuordnen

678

InputStream Hierarchy

InputStream

StringBufferInputStream

FileInputStream

FilterInputStream

SequenceInputStream

ByteArrayInputStream

PipedInputStream

java.io

679

Filter InputStream Hierarchy

FilterInputStream

CheckedInputStream

DigestInputStream

BufferdInputStream

LineNumberInputStream

DataInputStream

PushbackInputStream

InflaterInputStream

GZIPInputStream

ZIPInputStream

java.io

680

Output Stream Hierarchy

OutputStream

FileOutputStream

FilterOutputStream

ByteArrayOutputStream

PipedOutputStream

java.io

Page 170: Java

681

Filter OutputStream Hierarchy

FilterOutput Stream

CheckedOutputStream

BufferdOutputStream

DigestOutputStream

DataOutputStream

PrintStream

DeflaterOutputStream

GZIPOutputStream

ZIPOutputStream

java.io

682

Benutzung eines I/O Stream

Ein FileInputStream ist ein I/O stream, der an eineDatei gekoppelt ist:

FileInputStream f = new FileInputStream("myfile.dat");

byte b = f.read();

Ein DataInputStream verfügt über Methoden, umnumerische Typen zu lesen:

DataInputStream d = irgendwas;

double a = d.readDouble();

683

Kombination von Stream-Filtern

FileInputStream kann keine Zahlen lesen,DataInputStream können nicht auf Dateien operieren

FileInputStrea m f = new FileInputStream("myfile.dat");

DataInputStrea m d = new DataInputStream(f);

doubl e a = d.readDouble();

Diese Kombination ist in den meisten I/O-Anwendungen nötig.

684

Eigenschaften von Streams

read() und write() werden selten direkt benutzt.

read() und write()( direkt oder indirekt benutzt)blockieren Threads.

available() wird benutzt, um Blockierungen durchread() zu vermeiden.

Streams sollten mit close beendet werden .

Streams können mit flush geleert werden .

Page 171: Java

685

Unicode Streams

Unicode Streams benutzen Klassen, die von Reader undWriter abgeleitet sind.

Readerpublic abstract int read()

throws IOException

Writerpublic abstract void write(int b)

throws IOException

686

Reader hierarchy

FilterReader

CharArrayReader PipedReader

BufferedReader

StringReader

Reader

InputStreamReader

LineNumberReader

PushbackReader

FileReader

java.io

687

Writer hierarchy

FilterWriter

CharArrayWriter PipedWriter

BufferedWriter

StringWriter

Writer

OutputStreamWriter

FileWriter

PrintWriter

java.io

688

Schreiben von Text

Benutzung eines PrintWriter

PrintWriter out = new PrintWriter

(new FileWriter("myfile.txt"));

out.println("Hello world");

Die Methoden print() und println() werden durchInstanzen von PrintWriter implementiert.

Page 172: Java

689

Lesen von Text

Verwendet BufferedReader Klasse

Liest Zeile für Zeile und „parsed“ diese.

BufferedReader in = new BufferedReader(

new FileReader("myfile.txt"));

String s;

while ((s = in.readLine()) != null)

{

process s;

}

690

java.io

• java.io.File– Objekte werden erzeugt, um Dateien erzeugen, öffnen und schließen zu

können

public void erzeugeDatei {File datei = new File(“Test.txt”);System.out.println(“Dateiname: ” + datei.getName());

}

Ausgabe:

Dateiname: Test.txt

Die Java Klassenbibliotheken

691

java.io.File

• Klasse java.io.File– Objekte werden erzeugt, um Dateien zu Erzeugen, zu öffnen und zu

schließen. Dateisystem kann dem SecurityManager unterliegen

Konstruktor :– public File(String pathname)throws NullPointerException

• Erzeugt Objekt über Pfadnamen

Prüfung von Eigenschaften:– public boolean exists()– public boolean canRead()– public boolean canWrite()– public boolean isFile()– public boolean isDirectory()– public boolean isHidden()– public long length()

692

java.io.File

Filesystem-Handhabung:– public boolean delete()

• Löscht Datei oder Verzeichnis

– public void deleteOnExit()

• Löscht bei Beendigung der Virtual Machine• Flag wird gesetzt, welches nicht zurückgenommen werden kann

– public boolean mkdir()

• Erstellt Verzeichnis

– public boolean mkdirs()

• Erstellt Verzeichnis und eventuell benötigte, nicht existierendeMutterverzeichnisse

Page 173: Java

693

FileWriter

• Klasse java.io.FileWriter– Indirekt abgeleitet von java.io.Writer

Konstruktoren:– public FileWriter(File file) throws IOException

– public FileWriter(String fileName, boolean append)throws IOException

• append == true: Daten sollen angehängt werden

– public FileWriter(String fileName) throws IOException

694

FileReader

• Klasse java.io.FileReader– Indirekt abgeleitet von java.io.Reader

Konstruktoren:– public FileReader(File file) throws IOException

– public FileReader(String fileName) throws IOException

695

FileOutputStream

• Klasse java.io.FileOutputStream– Abgeleitet von java.io.OutputStream

Konstruktoren:

– public FileOutputStream(File file) throws IOException

– public FileOutputStream(String fileName,boolean append) throws IOException

• append == true: Daten sollen angehängt werden

– public FileOutputStream(String fileName)throws IOException

696

FileInputStream

• Klasse java.io.FileInputStream– Abgeleitet von java.io.InputStream

Konstruktoren:

– public FileInputStream(File file) throws IOException

– public FileInputStream(String fileName)throws IOException

Page 174: Java

697

Beispiel FileWriter

try {

FileWriter out = new FileWriter("Datei.txt");

out.write("Erste Zeile\n");

out.write("Zweite Zeile\n");

out.close();

} catch (IOException e) {

System.out.println("Fehler: " + e);

}

• Es entsteht eine Datei mit entsprechendem Inhalt

698

Beispiel FileReader / StringWritertry {

FileReader in = new FileReader("Datei.txt");

StringWriter sout = new StringWriter();

int c;

while ((c = in.read()) != -1) // Solange Ende nicht erreicht

sout.write(c);

System.out.println(sout); // gesamter Inhalt in string// gewandelt, inklusive der// Zeilenumbrüche

} catch (IOException e) {

System.out.println("Fehler: " + e);

}

Ausgabe:Erste Zeile

Zweite Zeile

699

Unterschiedliche Streams• Andere Sorten von Streams funktionieren ähnlich:

Zeichen- Streams Byte StreamsCharArrayReaderCharArrayWriter

ByteArrayInputStreamByteArrayOutputStreamHaupt-

speicher StringReaderStringWriter

StringBufferInputStream

Pipe PipedReaderPipedWriter

PipedInputStreamPipedOutputStream

File FileReaderFileWriter

FileInputStreamFileOutputStream

700

Beispiel: Zählen von Zeichen in Dateien

• Typische Struktur des Programms:– Identifikation der Datei und Überprüfung ihrer Existenz– implizites Öffnen durch den Aufruf eines Konstruktors für einen Strom– Bearbeiten des Inhalts und Schließen (hier implizit am Programmende)

import java.io.*;

class Auswertung {

public static void main(String[] args) throws IOException {

InputStream eingabedatei = null;

StringBuffer dateiname = new StringBuffer();

Page 175: Java

701

Beispiel: Zählen von Zeichen in Dateien// Datei bestimmen

if (args.length == 0) {

while (dateiname.length() == 0) {

System.out.println("Bitte Dateinamen angeben: ");

char zeichen;

boolean wortende = false;

do {

zeichen = (char)System.in.read();

wortende = (zeichen == ' ' || zeichen == '\n');

if (!wortende) dateiname.append(zeichen);

} while (!wortende);

}

} else dateiname.append(args[0]);

702

Beispiel: Zählen von Zeichen in Dateientry {

eingabedatei = new FileInputStream(dateiname.toString());

}

catch (FileNotFoundException f) {

System.out.println("Datei " + dateiname + "nicht vorhanden!");

System.exit(1);

}

703

Beispiel: Zählen von Zeichen in Dateien// Datei auswerten

int nächstesZeichen;

int zeilen = 0, andereZeichen = 0, leerzeichen = 0;

while ((nächstesZeichen = eingabedatei.read()) != -1) {

switch ((char)nächstesZeichen) {

case '\n': zeilen++; break;

case ' ': leerzeichen++; break;

default: andereZeichen++;

}

}

// Auswertung ausgeben

System.out.println("Auswertung der Datei " +dateiname);

System.out.println("Zeilen: " + zeilen);

System.out.println("Leerzeichen: " + leerzeichen);

System.out.println("andere Zeichen: " + andereZeichen);

}

}704

Erläuterungen zur Klasse Auswertung

• Die Referenz eingabedatei verwaltet bei der Ausführungdes Programms die zu analysierende Datei, der variable TextStringBuffer dateiname ihren Namen.

• Parameter, die beim Aufruf eines Programms angegebenwerden, werden durch den Parameter args (Feld vonTexten) an die Methode main übergeben.

Page 176: Java

705

Erläuterungen zur Klasse Auswertung

• Falls kein Parameter übergeben wurde, wird der Dateinamezeichenweise eingelesen.

• Innerhalb des Paketes java.lang steht eine Klasse Systemzur Verfügung, die ein öffentliches, statisches Attribut mit demNamen out hat. out ist eine Referenz auf ein Objekt derKlasse PrintStream , die eine Unterklasse vonFilterOutputStream ist.

706

Klasse PrintStream

• PrintStream ist (indirekt) von OutputStream abgeleitet• Es werden print - und println -Methoden für Objekte und

sämtliche simple Datentypen zur Verfügung gestellt.– println -Methode hängt im Gegensatz zur print -Methode ein

Zeilenumbruch bei jedem Aufruf an.

• Im Package System sind statische Attribute definiert:– public static final PrintStream out // Standard-Out– public static final PrintStream err // Standard-Error– public static final InputStream in // Standard-In

• Aus diesem Grunde geschieht Ausgabe mitSystem.out.println( ...)

707

Objektserialisierung

• Serialisierung bedeutet, Objekte in einen Stream zu schreibenund Objekte aus einem Stream zu lesen

• Schreiben geschieht mit java.io.ObjectOutputStream– Unterklasse von java.io.OutputStream

• Lesen geschieht mit java.io.ObjectInputStream– Unterklasse von java.io.InputStream

708

Konstruktoren für Object-Streams

• Konstruktoren für ObjectOutputStream /ObjectInputStream :

– public ObjectOutputStream(OutputStream out)throws IOException

– public ObjectInputStream(InputStream in)throws IOException, StreamCorruptedException

• => Objekte können durch beliebige InputStreams undOutputStreams geschickt werden

• Um Objekte in Dateien zu speichern, wirdFileOutputStream und FileInputStream benutzt

Page 177: Java

709

Interface Serializable

• Klassen, deren Objekte serialisierbar sein sollen, müssen dasInterface java.io.Serializable implementieren

• Interface java.io.Serializable ist leer, hat also keineMethoden oder Attribute=> Interface wird nur als Markierung benutzt

• Viele Klassen in den Standardbibliotheken sind serialisierbar(Achtung, nicht alle)

710

Kontrolle über Serialisierung (Teil 1)

• Von Objekten werden alle serialisierbaren Attribute mitserialisiert– Bei komplexen Datenstrukturen, wie Bäumen oder Listen muß nur das

Basisobjekt serialisiert werden, weil automatisch alle referenziertenObjekte mit berücksichtigt werden.

• Statische Attribute werden nicht serialisiert• Attribute, die nicht zum persistenten Teil von Objekten

gehören, können bei Deklaration mit transientgekennzeichnet werden.

• Als transient werden die abgeleiteten Attribute gekennzeichnet.

711

Methoden der Object-Streams

• ObjectOutputStream:– public final void writeObject(Object obj)

throws IOException• Schreibt serialisierbares Objekt in den Stream

– public void writeDouble(double d) throws IOException

– public void writeLong(long l) throws IOException• Viele andere primitive Datentypen können geschrieben werden

• ObjectInputStream:– public final Object readObject()

throws OptionalDataException,ClassNotFoundException,IOException

– public double readDouble() throws IOException• viele andere primitive Datentypen können gelesen werden

712

Beispieltry {

FileOutputStream out = new FileOutputStream("Persistenz.txt");ObjectOutputStream objout = new ObjectOutputStream(out);objout.writeObject("Text");objout.writeInt(200);objout.flush();out.close();

FileInputStream in = new FileInputStream("Persistenz.txt");ObjectInputStream objin = new ObjectInputStream(in);String zeichen = (String)objin.readObject();int zahl = objin.readInt();in.close();

System.out.println(zeichen + "\n" + zahl);} catch (IOException e) {} catch (ClassNotFoundException e) {}

Ausgabe:Text

200

Page 178: Java

713

Kontrolle über Serialisierung (Fortsetzung)

• Es gibt für Klassen, die serialisiert werden sollen, dieMöglichkeit, den Vorgang selbst zu bestimmen da– Zusatzinformationen mit serialisiert werden sollen, um Konsistenz mit

Umgebung sicherzustellen (z. B. statische Attribute)• Hier kann Standardserialisierung erweitert werden• Mit wenig Aufwand möglich

– Informationen über transiente under nicht serialisierbare Attributebenötigt werden

• Objektkonsistenz ist bei Existenz von transienten Attributen nicht immer trivial

– Ein Objekt selbst situationsabhängig bestimmen möchte, ob esserialisierbar ist

714

Kontrolle über Serialisierung

• Kontrolle von ObjectOutputStream :– In der Klasse des zu serialisierenden Objektes muß die Methode

private void writeObject(ObjectOutputStream s)throws IOException

mit exakt dieser Signatur definiert sein.– Statt der Standard-Serialisierung wird diese Methode aufgerufen– Der Outputstream (s) wird übergeben, daher kann die Serialisierung von

Hand vorgenommen werden– Mit s.defaultWriteObject(); kann die Standard-Serialisierung

aufgerufen werden, die ggf. noch ergänzt wird– Soll dem ObjectOutputStream die Serialisierung verweigert werden,

kann NotSerializableException geworfen werden.• Der ObjectOutputStream fängt diese Exception ab und wertet sie aus.

715

Kontrolle über Deserialisierung

• Kontrolle von ObjectInputStream :– In der Klasse des zu deserialisierenden Objektes muß die Methode

private void readObject(ObjectInputStream s)throws IOException, ClassNotFoundException

mit exakt dieser Signatur definiert sein.– Statt der Standard-Deserialisierung wird diese Methode aufgerufen– Der Inputstream (s) wird übergeben, daher kann die Serialisierung von

Hand vorgenommen werden– Mit s.defaultReadObject(); kann die Standard-Serialisierung

aufgerufen werden, die ggf. noch ergänzt wird.– Soll dem ObjectInputStream die Serialisierung verweigert werden,

kann NotSerializableException geworfen werden.• Der ObjectInputStream fängt diese Exception ab und wertet sie aus.

716

Interface Externalizable

• Die stärkste Kontrolle über Serialisierung wird durchImplementierung des Interfaces Externalizable erreicht

package java.io;

public interface Externalizable extends Serializable {

public void writeExternal(ObjectOutput out)

throws IOException;

public void readExternal(ObjectInput in)

throws IOException, java.lang.ClassNotFoundException;

}

– Die Methoden writeExternal und readExternal müssen überschriebenwerden

– Die Klasse ist selbst für das Lesen und Schreiben verantwortlich undmuß das auch für die Oberklassen gewährleisten

– Methoden writeExternal und readExternal sind public=> Gefahr des Überschreibens

Page 179: Java

717

Beispiel: Ablegen von binären SuchbäumenZiel: binäre Suchbäume werden persistent gemacht, sie können

nach Beendigung eines Programms wieder geladen werden.

Dazu werden die Methoden Sichere und Lade in die KlasseBST eingefügt.

Sichere arbeitet rekursiv (Preorder) und verwendet die privateMethode PreSichere .

Lade arbeitet iterativ.

718

Beispiel: Ablegen von binären Suchbäumenimport java.io.*;

class BST {

private Knoten wurzel;

BST() { wurzel = null; }

void Sichere(String dateiname) throws IOException {

DataOutputStream ausStrom =

new DataOutputStream( new FileOutputStream(dateiname);

PreSichere(ausStrom, wurzel);

}

private void PreSichere(DataOutputStream aus, Knotenaktuell) throws IOException {

if (aktuell != null) {

aus.writeInt(aktuell.GibWert());

PreSichere(aus, aktuell.GibLinks());

PreSichere(aus, aktuell.GibRechts());

}

}

719

Beispiel: Ablegen von binären Suchbäumen

void Lade(String dateiname) throws IOException {

DataInputStream inStrom =

new DataInputStream( new FileInputStream(dateiname);

try {

while (true)

FügeEin(inStrom.readInt());

}

catch (EOFException eof) {};

720

Beispiel: Ablegen von binären SuchbäumenEtwas trickreich ist die Konstruktion:

new DataOutputStream( new FileOutputStream(dateiname);

Von innen nach außen:

• zunächst wird ein Objekt der Klasse FileOutputStreamerzeugt, das auf einer Datei arbeitet, deren Name durchdateiname gegeben ist,

• das erzeugte Objekt der Klasse FileOutputStream wird anden Konstruktor der Klasse DataOutputStream übergeben,der es so verkapselt, daß die komfortable Schnittstelle vonDataOutputStream genutzt werden kann

Page 180: Java

Kapitel 19

Graphische Oberflächen (java.awt, java.swing)

722

javax.swing Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

723

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

724

Graphische Benutzungsoberflächen

Ziel: Erstellen einer GUI (z.B. für Bankautomaten)

Applets

Container für mehrerezusammengehörendeKomponenten

Behandlung vonBenutzereingaben(Mausklicks,...)

Eingabebereiche für Text

Schaltknöpfe

Anzeigefelder (Label)

Menü's

Page 181: Java

725

GUI-Bibliotheken in Java: JFC

• Java Foundation Classes (JFC)

– Swing Komponentenbibliothek (oftmals ungenauerweise synonym zuJFC verwendet)

– Unterstützung für frei wählbares Look&Feel– API für Dialoghilfen (Accessibility)– API für Einbinden von 2D-Grafik, Text, Bildern– Unterstützung für Drag&Drop

726

GUI-Bibliotheken in Java: Swing, AWT

• Erweiterbare Komponenten für Java-Benutzerschnittstellen– sichtbare („J“-Klassen) und unsichtbare Klassen

• JButton, JTextField vs. Modell-Klassen, Event-Klassen

• Swing 1.1 (javax.swing)– ist im JDK 1.2 enthalten– com.sun.java.swing in der Version 1.0.3 für JDK 1.1.x

• AWT (bereits im JDK 1.0 definiert)– wird weiterhin unterstützt– Button und JButton– wird vor allem für anspruchslose Anwendungen eingesetzt

727

Unterschied AWT - Swing

• AWT - Klassen (Abstract Window Toolkit)• Plattformabhängige Darstellung (Peer Klassen) („schwergewichtig“)• plattformabhängige Behandlung von Benutzereingaben• rechteckige Zeichenfläche, nicht überlappend• AWT umfaßt Schnittmenge aller Plattformen

• Swing - Klassen• Plattformunabhängige Darstellung• in Java geschrieben („leichtgewichtig“), bauen auf AWT auf• nicht nur rechteckige Formen• Swing umfaßt Konjunktion der Plattformen

GUI und Ereignisse

728

Entwicklungsziele

• Implementierung in Java ÿ(„lightweight components“)ÿ Ausführung ist plattformunabhängig

• frei wählbaren Look&Feels ÿÿ Darstellung ist plattformunabhängig

• Modell-basierter Programmierung ÿÿ MVC

• Komponenten als JavaBeans verpackt ÿ

• Kompatibilität zu AWT nein!

Page 182: Java

729

Aufbau der Swing-API

• Insgesamt 15 öffentliche Pakete, z.B.• javax.swing Elementare GUI-Komponenten

• javax.swing.event Ereignisbehandlung von Swing

• javax.swing.text Textdaten anzeigen, editieren• ...• (früher com.sun.java.swing)

• Benutzen eines Paketes:import javax.swing.*;import javax.swing.event.*;

GUI und Ereignisse

730

Bezug AWT - SwingVererbungshierarchie AWT-Swing

javax.swing

java.awt

JComponent

(java.applet)

JFrame

java.awt.Frame

JDialog

java.awt.Dialog

JWindow

java.awt.Window

java.awt.Window

JApplet

java.applet.Applet

java.awt.Panel

java.awt.Container

java.awt.Component

java.lang.Object

731

Aufbau von Swing 1.1

15 öffentliche Pakete:• javax.swing GUI-Komponenten• javax.swing.event Ereignisbehandlung von Swing• javax.swing.border Rahmen für GUI-Komponenten• javax.swing.table Tabellendaten anzeigen• javax.swing.tree Hierachische Daten anzeigen• javax.swing.text Textdaten anzeigen, editieren• javax.swing.text.html, javax.swing.text.html.parser ... In HTML• javax.swing.colorchooser Farbe auswählen-Dialog• javax.swing.filechooser Datei auswählen-Dialog• javax.swing.undo „Rückgängig“ bei GUI-Komp.• javax.swing.plaf, javax.swing.plaf.basic Frei wählbares Look&Feel• javax.swing.plaf.metal, javax.swing.plaf.multi• javax.accessibility Dialoghilfen für Ein-/Ausgabe

732

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

Page 183: Java

733

Fenster-Objekt: JFrame

• Bildschirm-Fenster mit Rahmen, Titel mit Buttonsund Menüzeile

• kann minimiert, verschoben, geschlossen undvergrößert werden

• ErzeugenJFrame f= new JFrame();

• JFrame hat einen Container "ContentPane".• enthält alle Komponenten, die auf der Zeichenfläche gezeichnet werden:

Container c= f.getContentPane();

•Hinzufügen von Komponenten zu einem JFrame

f.getContentPane().add(...);

GUI und Ereignisse

734

GUI-Komponenten (1/3)

Auf der Zeichenfläche können Komponenten angelegt werden!

wichtige Komponenten:

• JButtonKnopf, beim Drücken wird eine Aktion ausgeführt

JButton b= new JButton();b.setText("Drück' mich!");getContentPane().add(b);

GUI und Ereignisse

735

GUI-Komponenten (2/3)

• JTextField• Eingeben eines einzeiligen TextesJTextField t = new JTextField();String eingabetext = t.getText();

• JTextArea• Eingeben eines längereren Textes

• JLabel• einzeiliger Text, auch für Icon-Anzeige verwendbarJLabel l= new JLabel();l.setText("Eine Menge Buchstaben...");

GUI und Ereignisse

736

GUI-Komponenten

In der Zeichenfläche können Komponenten gezeichnet werden.

Die wichtigsten Komponenten:

• JButton– Knopf, beim Drücken wird eine Aktion ausgeführt

JButton b= new JButton()b.setText("Drück' mich!")

• JCheckBox– Boolesche Anzeige: "wahr"/"falsch"

• JRadioButton– exklusive Wahl aus Alternativen

Page 184: Java

737

GUI-Komponenten

• JComboBox– Einstellung eines Wertes (oben) mit

vorgegebenen Alternativen

738

• JList– damit kann man ein oder mehrere Element aus

einer Liste auswählen lassenString[] data = {“January", “February",...};

JList dataList = new JList(data);

– Holen der markierten ZellenObject[] objekte=eineListe.getSelectedValues();

• JTree– Darstellung von Hierarchien als Baum– Die Baumäste können an einem Knoten

auf- und zugeklappt werden

GUI-Komponenten

739

• JTable– Darstellen zweidimensionaler Daten in Tabellenform– Die dargestellten Daten werden im TableModel

gespeichert und verwaltet– Man kann einzeln, zeilen- oder spaltenweise Elemente

selektieren

– Erzeugen einer 4x3 TabelleJTable tabelle=new JTable(4,3);

– Holen des zugeordneten TableModelTable Model modell=tabelle.getModel();

– Ereignissez.B. TableColumnModelEvent mit MethodencolumnAdded(), -Moved();

GUI-Komponenten

740

Weitere Elemente

• JSlider– Schieberegler für Werteingabe

aus Zahlenbereich

• Datei-Dialog „Öffne“/Speichere“FileDialog(vaterFenster, „Titel“, LOAD);

Page 185: Java

741

GUI-Komponenten (3/3)import javax.swing.*;public class EinfachesGUI extends JFrame {

public EinfachesGUI() {getContentPane().setLayout(null);setSize(300,300);

JLabel l= new JLabel();l.setText(“Label-Fläche");l.setBounds(0,0,200,50);getContentPane().add(l);JButton b= new JButton();b.setText("Button-Fläche");b.setBounds(0,100,200,50);getContentPane().add(b);

}}public static void main (String args[]){

EinfachesGUI oberflaeche = new EinfachesGUI();oberflaeche.setVisible( true );

}}

GUI und Ereignisse

742

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

743

Komponenten-Hierarchien

• Grundlegende Idee: Komponenten enthalten wiederum Komponenten• übersichtlich• leicht austauschbar• Komponente ist verantwortlich für ihre "Kinder"

(z.B. Anordnung und Größe aller Kinder bestimmen)

• Beispiel: Komponenten-Baum für die EinfachesGUI (vereinfacht)

EinfacheGUI

ContentPane

b (JButton)l (JLabel)

...

GUI und Ereignisse

744

Strukturieren von Fenstern

Ziel: Fenster aus kleineren Gruppen zusammensetzen• Übersichtliche Gestaltung• Wiederverwendung: Code wird nicht mehrmals geschrieben

Lösung: Container (für Komponenten)

• Beispiel eines Containers: JPanel• Container mit Zeichenfläche• faßt Komponenten zusammen zu einer Einheit• ordnet diese in seinem Zeichenbereich an

Container und Layout

Page 186: Java

745

JPanels bei der BankautomatGUI Container und Layout

746

Beispiel: JPanel für PIN-Eingabeimport javax.swing.*;import java.awt.*;

public class PINPanel extends JPanel {

public PINPanel() {setLayout(null);

JLabel pinLabel = new JLabel();pinLabel.setText("PIN");pinLabel.setBounds(10,5,50,20);add(pinLabel);

JPasswordField pinField = new JPasswordField();pinField.setBounds(100,5,150,20);add(pinField);

}}

Container und Layout

747

Beispiel: JPanel für PIN-Eingabe

public static void main (String[] args) {

JFrame f= new JFrame();f.setBounds(0,0,300,70);

PINPanel p= new PINPanel();

f.getContentPane().add(p);f.setVisible( true );

}

Das JFrame:

Container und Layout

748

Weitere Container

Es gibt weitere Container in Swing:• Toplevel-Container:

• JFrame Fenster mit Rahmen, Titelzeile mit Buttons• JApplet Fenster für Darstellung im Web-Browser• JDialog kurzzeitig erscheinendes Fenster, um Mitteilungen an den

Benutzer und Reaktionen des Benutzers abzufragen

• Allgemeine Container (Auswahl)

JScrollPane JSplitPane JTabbedPane

Container und Layout

Page 187: Java

749

Container: Dialogfenster

• Aufteilung des Dialogfensters• Icon• Text-Botschaft• Knopf-Leiste

• abhängig• gehört zu einem Toplevel-Container,

der nach Dialogende aktiviert wird

• Arten von Dialogen:• Bestätigungs-Dialoge Frage mit Ja/Nein/Abbruch• Eingabe-Dialoge Text, Eingabefeld und "Ok"• Nachricht-Dialoge Text und "Ok"• Auswahl-Dialoge Text mit frei beschrifteten Knöpfen

Container und Layout

750

Beispiel: Bestätigungs-Dialog

//das Fenster, das am Dialogende aktiviert wird

JFrame f = new JFrame();

JOptionPane.showConfirmDialog(f,"Möchten Sie wirklich alle Daten löschen?","Warnung",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE

);

Container und Layout

751

Vererbung bei Containern

Ziel: Alle Container sollen dieselben grundlegendeFähigkeiten für Container-Verwaltung besitzen

Lösung: Benutze Vererbung!

• Alle Container erben von einer Klasse java.awt.Container:• Hinzufügen und Entfernen von Komponenten• Anordnen der Komponenten auf der Zeichenfläche

(Layout-Management)

Container und Layout

752

Container: Vererbungshierarchie

com.sun.java.swing

java.awt

JComponent

(java.applet)

JFrame

java.awt.Frame

JDialog

java.awt.Dialog

JWindow

java.awt.Window

java.awt.Window

JApplet

java.applet.Applet

java.awt.Panel

java.awt.Container

java.awt.Component

java.lang.Object

Container und Layout

Page 188: Java

753

Vererbung bei Komponenten

Ziel: gleiche Fähigkeiten für alle Swing-Komponentenbereitstellen, dabei Code wiederverwenden

Lösung: Benutze Vererbung!

• Alle Swing-Komponenten erben von einer Klasse JComponent:– Behandlung von Tastatureingaben– Rahmen

– Accessibility, Lokalisation (Datum, Währung,...), Tooltips

• Analog können neue, eigene Klassen von beliebigen Swing-Komponentenerben und diese ebenfalls um neue Fähigkeiten erweitern

Container und Layout

754

• Mutter (fast) aller GUI-Klassen– Ausnahme: Toplevel-Container

• leichtgewichtig• vererbt an alle Komponenten:

– (z.B. frei wählbares Look&Feel)

• ist ein Container und kanndamit andere Komponenten enthalten.

• in der Enthaltensein-Hierarchie stetsunterhalb eines Toplevel-Container(benutzt dessen Zeichenfläche)

javax.swing.JComponent

javax.swing.JComponent

java.awt.Container

java.awt.Component

java.lang.Object

755

Erweitern von Swing-Komponenten

Ziel: Neue Klassen von bestehenden Swing-Kom-ponenten ableiten und neue Fähigkeiten hinzu-fügen:z.B. neuer Schaltknopf

Lösung: Benutze Vererbung!

public class MeinEigenerButtonextends JButton{

...

}

MeinEigenerButton b= new MeinEigenerButton()

MeinEigenerButton

javax.swing.JButton

javax.swing.AbstractButton

javax.swing.JComponent

java.awt.Container

java.awt.Component

java.lang.Object

Container und Layout

756

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

Page 189: Java

757

Layout-Management

Ziel: Anordnen von Komponenten in einer anderenKomponente (Größe, Position festlegen)

Idee 1: Angabe von festen Layout-Koordinaten für jeden BestandteilNachteil: unflexibel, aufwendig, nicht nachträglich änderbar

Idee 2: Komponente „layoutet“ sich selbst.

Es gibt mehrere Layout-Strategien, die Komponenten selbstständig in einerZeichenfläche anordnen:

FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout,GridBagLayout,

Layout-Strategie auswählen: eineKomponente.setLayout( new FlowLayout())

Container und Layout

758

FlowLayout und GridLayout

• FlowLayout (Fluß)• Komponenten von links nach rechts• Zeilenumbruch am Zeilenende• Default für JPanel

• GridLayout (Gitter)• Alle Komponenten bekommen gleiche Größe• Plazierung durch Angeben von Zeile und Spalte

Container und Layout

759

Beispiel: FlowLayoutimport java.awt.*; import javax.swing.*;

public class FlowWindow extends JFrame {

public FlowWindow() {JButton b1= new JButton ("Button 1");JButton b2= new JButton ("Button 2");...

setLayout( new FlowLayout());add(b1);add(b2);...

}...

public static void main(String args[]) {FlowWindow w = new FlowWindow();w.setSize(300,300);w.setVisible( true );

}

Container und Layout

760

BoxLayout und CardLayout

• BoxLayout (Kiste)– Hängt Komponenten in 1 Spalte

untereinander

• CardLayout (Spielkarte)– Komponenten liegen

als „Spielkartenstapel“– Nur die oberste „Karte“ sichtbar– Zugriff auf oberste, unterste,

folgende, vorherige Karte

Container und Layout

Page 190: Java

761

BorderLayout und GridBagLayout

• BorderLayout (zuerst die Grenzen)– zuerst 4 Komponenten innen an die

Kanten fügen, zuletzt die verbliebeneZentralfläche mit 1 Komponenteausfüllen

– Orte: Nord, Süd, Ost, West, Center

• GridBagLayout– in Gitter anordnen, aber Größe

für jede Komponente frei wählbar– Plazierung durch Angeben

der Zeile und Spalte– mehrere Gitterplätze belegbar

Container und Layout

762

Beispiele: Auswahl eines Layout-Managers

• Viel Platz für jede einzelne Komponente– BorderLayout, GridBagLayout– im Zentrum liegt größte Komponente

• Wenige Komponenten aufgereiht– FlowLayout, BoxLayout

• Wenige Komponenten gleicher Größe– Gridlayout

• Viele Komponenten mit komplexem Layout– GridBagLayout

763

Weitere Layout-Möglichkeiten

•keinen Layout-Manager benutzen

eineKomponente.setLayout(null)

→ absolute Positionierung durch Angabe der Positions- Koordinaten (x/y)sowie Breite und Höhe für jede einzelne Komponente

JRadioButton rb = new JRadiuoButton();rb.setText("zahle aus");rb.setBounds(5,26,113,26); // (x,y, breite, höhe)

• eigenen Layout-Manager schreiben

Container und Layout

764

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

Page 191: Java

765

Frei wählbares Look&Feel

• Aussehen(Look) und Verhalten(Feel) einer GUI-Schnittstelle

• Look&Feel-Verwaltung übernimmt das Paketjavax.swing.plaf

• Schaltzentrale „UI-Manager“– Wählen eines Look&Feel:

...// zuerst das Look&Feel auf CrossPlatform einstellen

try {UIManager.setLookAndFeel(

UIManager.getCrossPlatformLookAndFeelClassName());

} catch (Exception e) { }

...// jetzt erst die GUI aufbauen und anzeigen

766

Die verfügbaren Look&Feels

• Java (Metal)

• Windows

• CDE, OSF/Motif(Common Desktop Environment)

• Apple Macintosh

767

Look&Feel Detail• Jede Klasse „J...“ hat in javax.swing.plaf eine Klasse „...UI“ (Delegate)

– z.B. die Klasse „JButton“ duch „ButtonUI“.– Ausnahme: Toplevel-Container (JFrame etc.) haben stets Windows-Look&Feel,

weil sie schwergewichtig sind

• Delegate kennt für alle Look&Feels, in denen die Klasse gezeichnet werdenkann, die konkreten API‘s– In jedem API‘s ist eine Klasse bereitgestellt, mit der die sichtbare Klasse sich

zeichnen kann.z.B. „MetalButton“, „WindowsButton“, etc.

• Zeichnen– Für ein Objekt holt beim UI-Manager den Delegate. Von diesem Delegate kann

für das aktuell verwendete Look&Feel zu der Klasse verzweigt werden, die fürdas Zeichnen in diesem Look&Feel sorgt.

768

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

Page 192: Java

769

Das MVC-Modell• Model-View-Controller (MVC) ist eines der bekanntesten

Entwurfsmuster

• Ein Entwurfsmuster ist ein bewährter Lösungsansatz• MVC trennt Datenhaltung von Datendarstellung

– Modell hält Daten einer Anwendung– View für graphische Repräsentation der Daten– Controller übersetzt Benutzereingaben im View

in Änderungen am Zustand des Modells

770

MVC-Beispiel

a b cx 60 30 10y 50 30 20z 80 10 20

window window window

A B C

A

BC

a=50%b=30%c=20%

change notification

requests, modifications

771

MVC - Model

Das Model enthält den funktionalen Anwendungskern.Es kapselt die enstprechenden Daten und bietet Operationen an.Diese werden vom Controller aufgerufen.Zusätzlich bietet das Model Operationen zum Zugriff auf Daten, die die

Views brauchen, um Daten abzufragen.Das Model verwaltet die abhängigen Komponenten.Alle Ansichten und einige Controller (diejenigen, die mit Views

zusammenhängen, von denen Änderungen veranlaßt werden) lassensich beim Model registrieren.

772

MVC - View

Views präsentieren dem Anwender Informationen.Jede View definiert eine Aktualisierungsoperation, die vom

Änderungsmechanismus des Models aufgerufen wird.Diese Änderungsoperation ermittelt die anzuzeigenden Werte und zeigt

sie an.Während der Initialisierung werden alle Views mit dem Model assoziiert.Jede View erzeugt eine Controller-Komponente (1:1-Beziehung).

Page 193: Java

773

MVC - Controller

Ein Controller-Objekt akzeptiert Bedieneingaben als Ereignisse.Ereignisse werden in Anforderungen an das Model oder die assoziierte

View übersetzt.Wenn das Verhalten eines Controllers vom Zustand des Models abhängt,

läßt sich der Controller beim Mechanismus zur Benachrichtigung überÄnderungen registrieren und implementiert eineAktualisierungsoperation (z.B. nötig, wenn eine Änderung des Modelseinen Menüeintrag aktiviert oder deaktiviert).

774

Das MVC-Modell

• Varianten

– Vollständige Entkopplung von Modell und View

– Einseitige Abkopplung des View• Modell kennt seine Views direkt• Views müssen Controller benutzen

(düfen Modell nicht direkt manipulieren)

775

Das MVC-Modell: Diskussion

• Vorteile– View leicht änderbar– Wiederverwendung durch Entkopplung– Modell mit mehreren Darstellungen– Views sind schachtelbar

(schwer, wenn Modelldaten und View vermischt sind).– Controller (zur Laufzeit) änderbar

• Z.B. View „abschalten“: Controller, der alle Eingabeereignisse ignoriert

• Nachteile– Kleinere, einfache Anwendungen werden unnötig aufgeblasen.– Die Trennung von Controller und View kann schwierig sein.

776

Ereignisse

• Programme ohne GUI haben klaren Programmablauf

• Programme mit GUI sind ereignisgesteuert

– Aktionen des Benutzers erzeugen Ereignisse(Tastaturanschläge, Mausklicks, Mausbewegungen etc.)

Problem: GUI kann nicht vorhersehen, was Benutzer tun wird.

Idee: GUI wartet auf Aktionen des BenutzersKomponenten erzeugen Ereignisse(Maus, Tastatur,...)

Page 194: Java

777

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

778

Benutzer-EreignisseProblem: GUI kann nicht vorhersehen, was Benutzer tun wird.Idee: GUI wartet auf Aktionen des Benutzers

Komponenten erzeugen Ereignisse (Maus, Tastatur,...)

• Ereignis-Objekte (erben von java.util.EventObject )• stellen bestimmte Ereignisse dar (Interaktion des Benutzers)

• Ereignis-Auslöser-Objekte• lösen Ereignisse aus (in der Regel graphische Elemente)

• Ereignis-Lauscher-Objekte (EventListener -Objekte):• melden sich bei Auslöser-Objekten an,• werden bei Ereignissen benachrichtigt• stellen für Behandlung der Ereignisse passende Methoden bereit• implementieren EventListener -Schnittstellen• bilden die Schnittstelle zur Anwendungsfunktionalität!

GUI und Ereignisse

779

Beispiel: Mausklicks

Ereignis: Benutzer drückt Maustaste über einem Schaltknopf

Reaktion: Schaltknopf erzeugt Ereignis-Objektnew java.awt.event.ActionEvent

• Schaltknopf benachrichtigt alle registrierten Listener und

• ruft dort die passende Listener-Methode auf:

• Listener muß Schnittstelle ActionListener implementierenactionPerformed(ActionEvent e)

• Jede „zuhörende“ Klasse kann die Methode beliebig implementieren

• Jede Klasse hält Methoden für alle interessierenden Ereignisarten bereit

GUI und Ereignisse

780

Beispiel (1/2)Ziel: Button mit wechselnder Aufschriftimport java.awt.event.*;import javax.swing.*;

public class Wechselbutton extends JButton {public Wechselbutton (String text){

super(text);}public void wechsle() {

if (this.getText().equals("Drück mich!")){this.setText("Nochmal...");} else {this.setText("Drück mich!");}

}}public class WechselbuttonFrame extends JFrame {

private Wechselbutton b;public WechselbuttonFrame(Hoerer h){

b = new Wechselbutton("Drück mich!");getContentPane().add(b);b.addActionListener(h);

}

}

GUI und Ereignisse

Page 195: Java

781

Beispiel (2/2)

import javax.swing.*;import java.awt.event.*;public class Hoerer implements ActionListener {

public void actionPerformed(ActionEvent e){Wechselbutton but=(Wechselbutton) e.getSource();but.wechsle();

}}

public class Testumgebung {public static void main(String[] args) {

Hoerer h = new Hoerer();WechselbuttonFrame wbf = new WechselbuttonFrame(h);wbf.setSize(200,50);wbf.setVisible(true);

}}

GUI und Ereignisse

782

Ereignis-Objekt

• Ein Ereignis ist ein Objekt

• in java.util.EventObjekt , java.awt.Event oderjavax.swing.event

• enthält

– auslösende Quelle (z.B. Button)

– Nachricht (z.B. „Maustaste 1 wurde gedrückt“)

Event-Quelle(Button) Event

Listener

Event

EventListener

783

Arten von Ereignissen

Basis-Ereignisse und semantische Ereignisse

Verwendung Ereignisart Schnittstelle Lauscher-Methoden

BasisereignisseTastaturereignisse KeyEvent KeyListener keyPressed, keyReleasedMausereignisse MouseEvent MouseListener mouseClicked,-PressedKomponentenereign. ComponentEvent ComponentList. componentHidden, -movedContainerereignisse ContainerEvent ContainerListener componentAdded, -RemovedFokusereignisse FocusEvent FocusListener focusGained, focusLostFensterereignisse WindowEvent WindowListener windowIconified, -Opened

Semantische EreignisseAktion des Benutzers ActionEvent ActionListener actionPerformedTextereignisse TextEvent TextListener textValueChangedAuswählen (Checkb.) ItemEvent ItemListener itemStateChangedWertmanipulation AdjustmentEvent AdjustmentListener adjustmentValueChanged

GUI und Ereignisse

784

Zugehörigkeit von Listener-Interfaces zu Kompon.Ausschnitt (siehe JDK-Dokumentation und Tutorial)

Komponente ActionListener

ChangeListener

ItemListener

WindowListener

JFrame X

JDialog X

JScrollPane X

JButton X X X

JComboBox X X

JSlider X

JTextField X

JFileChooser X

Page 196: Java

785

Methoden der Listener-Interfaces:ComponentListener:

void componentHidden(ComponentEvent e)

void componentMoved(ComponentEvent e)

void componentResized(ComponentEvent e)

void componentShown(ComponentEvent e)

FocusListener:void focusGained(FocusEvent e)

void focusLost(FocusEvent e)

KeyListener:keyPressed(KeyEvent e)

keyReleased(KeyEvent e)

keyTyped(KeyEvent e)

786

Methoden der Listener-Interfaces:MouseListener:

void mouseClicked(MouseEvent e)

void mouseEntered(MouseEvent e)

void mouseExited(MouseEvent e)

void mousePressed(MouseEvent e)

void mouseReleased(MouseEvent e)

MouseMotionListener:void mouseDragged(MouseEvent e)

void mouseMoved(MouseEvent e)

ActionListener:void actionPerformed(ActionEvent e)

787

Methoden der Listener-Interfaces:ChangeListener:

void stateChanged(ChangeEvent e)

ItemListener:void itemStateChanged(ItemEvent e)

WindowListener:void windowActivated(WindowEvent e)

void windowClosed(WindowEvent e)

void windowClosing(WindowEvent e)

void windowDeactivated(WindowEvent e)

void windowDeiconified(WindowEvent e)

void windowIconified(WindowEvent e)

void windowOpened(WindowEvent e)

788

Listener implementieren:

• Listener-Interfaces beinhalten Methoden, an die Eventsweitergeleitet werden.– Beispiel: interface FocusListener {

void focusGained(FocusEvent e);void focusLost(FocusEvent e);

}

• Swing-Komponenten können nur Ereignisse an Objektebestimmte Listener-Interfaces weiterleiten. EntsprechendeObjekte werden mit add...Listener() bei der Swing-Komponente registriert. Hier:

addFocusListener(...);

Page 197: Java

789

Benutzen von anonymen Klassenimport javax.swing.*; import java.awt.event.*;public class Wechselbutton2 extends JFrame {

public Wechselbutton2(){JButton b= new JButton("Drück mich!");getContentPane().add(b);

b.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){JButton but=(JButton) e.getSource();if (but.getText().equals("Drück mich!")){

but.setText("Nochmal...");} else {

but.setText("Drück mich!");}

}}

);}

}

GUI und Ereignisse

Wird von

Programmier

umgebungen

generiert!

790

Benutzen von Anonymen Klassen...

public static void main(String[] args) {Wechselbutton2 wb2 = new Wechselbutton2();wb2.setSize(200,50);wb2.setVisible( true );

}

GUI und Ereignisse

791

1 Motivation, Historie Java und Guis, AWT, SWING, JFC

2 Einfaches Bildschirmfenster mit elementaren Komponenten3 Komponenten zusammenfassen in Containern (Übersicht)

• JPanel• alle Container erben von Container• alle Komponenten erben von JComponent

4 Layout von Containern (Komponenten-Anordnung, -Größe)FlowLayout, GridLayout, BoxLayout,CardLayout, BorderLayout, GridBagLayout

5 Pluggable Look&Feel (inkl. Vorführung/Demo Swing-Set zur PräsentationGUI-Elemente)

6 Allgemeine Betrachtung: Interaktion, MVC-Konzept, Ereignisse,7 Behandlung von Benutzer-Ereignissen (Mausklicks, ...)8 Menüs für Funktionsauswahl

792

Menüs

Ziel: Menüs an Bildschirm-Fenstern- Gruppieren von Funktionen in Menüs

- Anordnen aller Menüs in 1 Menüleiste am oberen Fensterrand- Anbinden an Methoden über Ereignisse (analog Knöpfe, etc.)

Menüs und Applets

Page 198: Java

793

Bestandteile eines Menüsystems

• Menüleiste• nimmt Menüs auf

• Trennlinien• Popup-Menü

• Menu-Elemente• Menüeinträge• Radiobuttons• Checkbuttons• Kommando-Sammlung (JMenu)

(ein bzw. mehrere Kommandos,verschachtelte Menüs)

Menüs

794

Vererbungshierarchie für Menüs

Alle Menu-Elemente sind Container und Komponenten

JMenuBar JPopupMenu

JMenu JCheckBoxMenuItem JRadioButtonMenuItem

JMenuItem

JAbstractButton JSeparator

JComponent

java.awt.Container

java.awt.Component

Menüs

795

Beispiel: Menüleiste

public class BankautomatGUI extends JFrame {public BankautomatGUI(String s) {

super (s);JMenuBar mbar = new JMenuBar();setJMenuBar(mbar);JMenu dateiMenu = new JMenu(“Datei“);mbar.add(dateiMenu);JMenu bearbeitenMenu = new JMenu("Bearbeiten");mbar.add(bearbeitenMenu);JMenuItem editierenItem = new JMenuItem();editierenItem.setText("Editieren");bearbeitenMenu.add(editierenItem);JMenuItem anschauenItem = new JMenuItem();anschauenItem.setText("Anschauen");bearbeitenMenu.add(anschauenItem);setJMenuBar(mbar);...

Menüs

796

Look&Feel Detail• Jede Klasse „J...“ hat in javax.swing.plaf eine Klasse „...UI“ (Delegate)

– z.B. die Klasse „JButton“ duch „ButtonUI“.– Ausnahme: Toplevel-Container (JFrame etc.) haben stets Windows-Look&Feel,

weil sie schwergewichtig sind

• Delegate kennt für alle Look&Feels, in denen die Klasse gezeichnet werdenkann, die konkreten API‘s

– In jedem API‘s ist eine Klasse bereitgestellt, mit der die sichtbare Klasse sichzeichnen kann.z.B. „MetalButton“, „WindowsButton“, etc.

• Zeichnen– Für ein Objekt holt beim UI-Manager den Delegate. Von diesem Delegate kann

für das aktuell verwendete Look&Feel zu der Klasse verzweigt werden, die fürdas Zeichnen in diesem Look&Feel sorgt.

Page 199: Java

Kapitel 20

Applets (java.applet)

798

java.applet Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java

• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

799

Application / Applet / Servlet

• Application– Java-Programm, welches (in der Regel) alle Systemresourcen nutzen

darf– Abgrenzung von Applets mit eingeschränkten Rechten

• Applet– Java Programm, welches innerhalb von Web-Browsern lauffähig ist

• Netscape Navigator• HotJava von Sun Microsystems• InternetExplorer von Microsoft

– Es gibt eingeschränkte Rechte, z.B. darf nicht ohne Erlaubnis desAdministrators auf lokales Dateisystem zugegriffen werden

• Servlet– Serverprogramm, mit dem Applets eine Verbindung aufnehmen können– Ersetzt CGI-Scripts, die kein "Gedächnis" haben

800

Applets

Ziel:Applet für Bankautomatzur Anzeige im Web-Browserbzw. im AppletViewer

Menüs und Applets

Page 200: Java

801

Applets

• Klasse "com.sun.java.swing.JApplet"• Applets:

– Programmcode wird vom Web-Browser angefordert (per URL)– Web-Server verschickt Programmcode zum Web-Browser– Web-Browser führt Programmcode aus (eigene Java Virtual Machine)

• Lebenszyklus eines Applets:applet.init() Selbstinitialisierung automatisch nach dem

Laden aufgerufen

applet.start() Starten automatisch nach demInitialisieren

applet.stop( ) Beenden beim Verlassen der Web-Seiteim Browser

applet.destroy() Löschung für Garbage Collection

Menüs und Applets

802

Toplevel-Container: Applet

• Konstruktion einer Applet-KlassePublic class HelloApp extends JApplet...

• Erzeugung eines JAppletHelloApp applet=new HelloApp();

• Festlegen eines Layouts für das Fensterapplet.setLayout (einLayoutManager);

• Anheften einer Menüzeile am oberen Fensterrandapplet.setJMenuBar(einJMenubar);

• Hinzufügen von darzustellenden JComponentsapplet.getContentPane().add(new JButton(„Swing!“));

803

Das java.applet - Package

Appletinit();

start();

stop();

destroy();

getAppletInfo();

getParameterInfo();

AppletContextDefinition von Interaktionsschnittstellen

AppletStubinterne Schnittstelle zur Implementierung eines Appletviewers

AudioClip

804

Beispiel: "Hello World" - Applet

import java.awt.*;

import com.sun.java.swing.applet.*;

public class HelloApp extends JApplet {

public void init() {

setSize(200,100);

JLabel l= new JLabel();

l.setText("Hello World !");

this .getContentPane().add(l);

}

}

Menüs und Applets

Page 201: Java

805

Ausführen eines Applets

Zwei Möglichkeiten:

• AppletViewer vom JDK benutzen

• Aufruf des Applets in Web-Seite einbetten– <APPLET> Tag:

<APPLET CODE=HelloApp.classWIDTH=500HEIGTH=300NAME=„HelloWorld“>

</APPLET>

Menüs und Applets

806

Parameterübergabe an Applets

• Übergabe von der HTML-Seite zum AppletHTML: <PARAM> TagsApplet: getParameter() - Methode

• Lesen aller Parameter innerhalb des <APPLET> Tags möglich• Parameter enthält immer einen Namen und einen Wert

<PARAM name=„Name“ value=„MyApplet“>

• Anzeigen aller einlesbaren Parameter:String info[][] = getParameterInfo();

• Lesen eines Parameters:String titel = getParameter(„Name“);

807

Sicherheit bei Applets

• Verboten– Herstellen von Netzwerkverbindungen (außer zum Host)– Lesen und Schreiben von Dateien auf dem Host– Starten von Programmen auf dem Host– Auslesen von sicheren System-Einstellungen auf dem Client– Laden von Klassenbibliotheken– Definieren von native Methoden

• Erlaubt– Herstellen von Netzwerkverbindungen zum Host– Aufruf anderer Webseiten (per URL)– Abspielen von Sounds– Kommunikation mit weiteren Applets auf dem Client

Menüs und Applets

808

(Standard)-Sicherheitsrestriktionen von Applets

• Kein Überschreiben von Standard-Klassenbibliotheken undDefinieren von native Methoden

• Kein Lesen und Schreiben von Dateien auf dem Host• Kein Herstellen von Netzwerkverbindungen

– außer zum Host, von dem es geladen wurde

• Kein Starten von Programmen auf dem Host• Kein Auslesen von sicheren System-Einstellungen• Unterschiedliches Aussehen von Applet-Fenstern und

Anwendungsfenstern

Page 202: Java

809

Was können Applets?

• Aufbau von Netzwerkverbindungen zum Host

• einfaches Aufrufen anderer Web-Seiten

showDocument(„http://www.javasoft.com/index.html“);

• Applets aus dem lokalen Filesystem unterliegen nicht den

Sicherheitsrestriktionen

• Abspielen von Sounds

• Kommunikation mit anderen Applets

• Für signierte Applets können Sicherheitsrestriktionen gelockert

werden

Kapitel 21

Threads

811

Multithreading Die Java Klassenbibliotheken

• java.applet (JDK 1.0) Java-Applets (für WWW-Browser)• java.awt (JDK 1.0) AWT-Komponenten

• java.beans (JDK 1.1) Beans-Development• java.io (JDK 1.0) Input / Output / Datenströme• java.lang (JDK 1.0) Basispackage für Java• java.math (JDK 1.1) Zahlen großer Genauigkeit• java.rmi (JDK 1.1) Remote Method Invocation• java.security (JDK 1.1) Sicherheit, Kryptographie

• java.sql (JDK 1.1) JDBC-Paket• java.util (JDK 1.0) Verschiedene Hilfsklassen• javax.swing (JDK 1.2) Swing-Komponenten

Für JDK 1.1.x: com.sun.java.swing

• org.omg.CORBA (JDK 1.2) CORBA-Schnittstelle

812

Threads

• Threads können auf einer Maschine mit nur einem Prozessorablaufen und sich dabei aufführen, als ob sie eigene Prozessewären.

• Ihr Unterschied zu wirklich eigenständigen Prozessen ist, daßsie aus einem Hauptprogramm erzeugt werden.

• Ein Thread modelliert Objekte, die innerhalb einesumgebenden Prozesses einen eigenen Kontrollfluß haben.

• Der Zusammenhang mit anderen Threads ergibt sich durch dieNutzung gemeinsamer Ressourcen (Objekte, CPU-Zeit, Zugriffauf Datenbanken).

Page 203: Java

813

Multithreading

• Multithreading bedeutet:– Programmpfad wird in unterschiedliche Richtungen verzweigt, diese

laufen parallel.– Ein Thread hier ein Programmpfad, wird auch Ausführungskontext oder

leichtgewichtiger Prozeß genannt.– Multithreading bedeutet nun, dass es möglich ist, mehrere Threads

parallel laufen zu lassen (bei nur einem Prozessor ist dies natürlich leineechte Parallelität).

814

Multithreading

• Probleme:– Konkurrierende Threads benutzen gleiche Ressourcen und Daten

=> Bei Zugriff auf gemeinsam genutzte Ressourcen muß Schutzeingreifen (nur ein Thread hat den Monitor)

– Threads, die mehrere Resourcen gleichzeitig benötigen, können sichgegenseitig blockieren (Deadlock), indem sie jeweils eine Ressourcefesthalten und auf die anderen warten.

– Nicht jede Virtual Machine verteilt CPU-Zeit automatisch gerecht(Es gibt Timeslicing-fähige und -unfähige Systeme)=> Laufende Threads sollten auch anderen eine Chance geben

– Mögliche Zustände oft schwer verständlich, da Parellelität nicht sehrintuitiv verständlich

815

Beispiel

class AddThread extends Thread{

public void run(){

for(int i=0;i<10;i++){

MyThreadExample.count++;

System.out.print("Add ");

System.out.println(MyThreadExample.count);

}

}

}

816

Beispiel

class SubtractThread extends Thread{

public void run(){

for(int i=0;i<10;i++){

MyThreadExample.count--;

System.out.print("Subtract ");

System.out.println(MyThreadExample.count);

}

}

}

Page 204: Java

817

Beispiel

class MyThreadExample{public static int count=0;

public static void main(String args[]){AddThread a = new AddThread();SubtractThread b = new subtractThread();a.start();b.start();

}}

818

Beispiel

Mögliches Ergebnis

Add 1

Add 2

Add 3

Add 4

Add 5

Subtract 5

Subtract Add 4

4

Subtract 3

Subtract 4

Subtract 2

Subtract Add 1

Add 2

1

Subtract 2

Subtract 1

Subtract Add 0

Add 0

Subtract 0

1

819

Thread / Runnable

• Ein Thread wird immer in einer run-Methode gestartet– public void run()

– Diese Methode muß von einer Klasse implementiert werden, dessenObjekt sich mit einem eigenen Thread ablösen möchte

– Bei Start des Threads wird die run -Methode vom System automatischaufgerufen (nicht selbst aufrufen!)

• Ein Threadfähige Klasse kann durch zwei Möglichkeitendefiniert werden:A) Erben von der Klasse Thread , hier muß die run() -Methode der

Klasse Thread überschrieben werdenB) Implementieren des Interfaces Runnable , hier muß die run() -

Methode des Interfaces implementiert werden

820

java.lang

• Threadfähigkeit einer Klasse kann auf zwei Arten erreichtwerden– erben von der Klasse Thread

– implementieren des Interfaces Runnable

Die Java Klassenbibliotheken

Thread

MyClass

RunnableMyClass

Page 205: Java

821

java.lang

• in beiden Fällen wird die Methode run() implementiert

– im erbenden Fall wird sie überschrieben

class MyClass extends Thread {

public void run() {

// hier wird run() überschrieben

}}

Die Java Klassenbibliotheken

Thread

MyClass

822

java.lang

• in beiden Fällen wird die Methode run() implementiert

– im Interface Fall wird sie implementiert

class MyClass implements Runnable {

public void run() {

// hier wird run() implementiert

}}

Die Java Klassenbibliotheken

RunnableMyClass

823

Using the Runnable Interface

class AddThread extends SomeClass implements Runnable{

public void run(){

for(int i=0;i<10;i++) SyncThread.incCount();

}

}

...

// Where the thread shall be started

// a new Thread Object is created

AddThread a = new AddThread();

Thread this_is_the_Thread = new Thread(a);

this_is_the_Thread.start();

...

824

Thread / Runnable

• Erzeugen eines Objektes, welches später einen eigenenProgrammpfad bekommen soll:A) Bei Unterklasse von Thread (z. B. MeinThread extends Thread )

kann einfach durch new das startfähige Objekt erzeugt werden(hier: Thread leicht = new MeinThread() )

B) Bei Implementierung von Runnable(z. B. MeineKlasse implements Runnable ) wird durchMeineKlass e a = new MeineKlasse(); ein Objekt erzeugt unddurchnew Thread dann das startfähige Objekt erzeugt(hier: Thread leicht = new Thread(a) )

• Starten des Threads:– Durch die start() -Methode von Thread wird der Thread gestartet:

leicht.start();

Page 206: Java

825

Warum zwei Möglichkeiten?

• Einfache Möglichkeit ist, von Thread abzuleiten=> einfacheres Verständnis

• Aber:– Java kennt keine Mehrfachvererbung von Klassen, jedoch

Mehrfachvererbung von Interfaces– Es ist Wünschenswert, auch Unterklassen multithreadingfähig zu

machen

=> Hier bleibt nur die Möglichkeit, Runnable zu implementieren

826

Methoden von Thread

• Konstruktoren:– public Thread()

• Muß von abgeleiteter Klasse durch super() aufgerufen werden

– public Thread(String name)• Muß von abgeleiteter Klasse durch super(name) aufgerufen werden

• Dem Thread wird hier ein Name gegeben

– public Thread(Runnable target)• Muß direkt aufgerufen werden, um Threads über das Runnable -Interface zu

definieren

• Methoden:– public native synchronized void start()

• Startet den Thread. Die Virtuelle Maschine startet die run() -Methode in eigenemProgrammpfad

• synchronized ist neues Schlüsselwort, später mehr

827

Methoden von Thread

• Methoden:– public static native Thread currentThread()

• Klassenmethode, um den aktuell laufenden Thread zu ermitteln

– public static native void yield()• Aufforderung, eventuell andere wartende Threads zum Zuge kommen zu lassen

– public static native void sleep(long millis)throws InterruptedException

• Thread wartet angegebene Zeit. Andere Threads kommen zum Zuge, sofern sie nichtdurch belegte Resourcen blockiert sind

– public final void setPriority(int newPriority)• Legt die Priorität des Threads fest. Threads höherer Priorität laufen bevorzugt

– public final String getName()• Gibt den Namen des Threads zurück

828

Deaktivierung eines Threads

• Methoden:– sleep

siehe oben

– suspend

Unterbricht die Arbeit eines Prozesses

– wait

veranlaßt, daß ein Prozeß eine vorgegebene Zeit wartetvon Object ererbt

Page 207: Java

829

Aktivierung eines passiven Threads

• Methoden:– resume

Gegenstück zu suspend

– notify, notifyAll

reaktiviert wartende Prozesse (Gegenstück zu wait)von Object ererbt

830

Vernichten eines Prozesses

• Methoden:– stop

anomale und sofortige Beendigung eines aktiven oder gerade erzeugtenProzesses (mit Aufräumarbeiten)

– destroy

wie stop aber ohne Aufräumarbeiten

831

Zustandsübergänge von Threads

832

Ein neuer Thread (Zustand new), der noch nicht ausgeführtwurde, erfordert vor der ersten Ausführung erst mal dieZuweisung von Ressourcen (Speicher).

Dann wird er mittels der Methode start() in den Zustandrunnable überführt.

Runnable bedeutet, daß der Prozeß durchgeführt werdenkann (also aktiv werden kann). Allerdings kann nur einProzeß zu jeder Zeit aktiv sein.

Die wartenden, schlafenden, unterbrochenen Prozesse sindim Zustand blocked.

Wenn der aktive Prozeß in den Zustand blocked übergeht,dann wird ein runnable Prozeß aktiviert.

Zustandsübergänge von Threads

Page 208: Java

833

Die JVM wählt aus der Menge der runnable Prozesse dendurchzuführenden aus.

Hier gibt es Unterschiede zwischen den JVMs aufverschiedenen Plattformen.

Ein Prozeß verläßt den Zustand blocked, wenn

die Schlafperiode zu Ende geht,

er notifiziert wird (notify),

die I/O-Operation, auf die er wartet, terminiert,

wenn er per resume fortgesetzt wird.

Zustandsübergänge von Threads

834

Threads gehen in de Zustand dead über, wenn

seine run()-Methode beendet wird,seine stop()- oder destroy-Methode aufgerufen wird.

Ein dead Thread kann nicht reaktiviert werden.

Zustandsübergänge von Threads

835

Prioritäten

Jeder Thread hat eine Priorität.

Die JVM bevorzugt die Threads mit hohen Prioritäten, wennein Thread von runnable in aktiv überführt werden soll.

Threads laufen solange bis:

er die yield()-Methode aufruft,er nicht mehr runnable ist (z.B. weil er auf einen initiierten I/O warten

muß),ein Thread mit höherer Priorität runnable wird.

836

Egoistische Threads

Ein langlaufender Thread mit hoher Priorität, der kein I/Overanlaßt, kann den Prozessor dauerhaft beanspruchen.

Das ist kein Problem, wenn die JVM zeitscheiben-fähig ist.

Langlaufende Threads sollten regelmäßig sleep() oder yield()aufrufen, um auch anderen Threads Zugriff zu erlauben.

Page 209: Java

837

Monitore

Sperren sind ein Mittel, um den parallelen Zugriff aufRessourcen zu reglementieren.

Ein kritischer Abschnitt ist ein Speicherbereich, auf den immernur ein Prozeß zugreifen darf.

Eine typische Art von kritischen Abschnitten sind Variablen,diese dürfen nicht beliebig parallel gelesen und geschriebenwerden.

Es ist möglich, Bereiche zu schützen, die nur ein Thread zurZeit abarbeiten darf.

838

Monitore

Jedes Objekt besitzt genau einen Monitor,ein Thread kann nur in einen geschützten Bereich eintreten,wenn der entsprechende Monitor frei ist

Objekte, die Threads blockieren können und die Threadsnotifizieren, wenn die Bearbeitung weitergehen kann,werden Monitor genannt. Monitore realisieren Sperren.

Jedes Objekt mit einer oder mehreren synchronisiertenMethoden, wird Monitor genannt.

In einer synchronisierten Methode kann ein Thread seineSperre mittels wait() aufgeben.

839

Synchronisation

Wenn ein Objekt zu einer Klasse mit synchronisisertenMethoden gehört, dann hat es eine Schlange, in der alleThreads verwaltet werden, die die synchronized Methodeaufgerufen haben.

Aufrufende Threads kommen in diese Schlange, wenn:

sie eine synchronized Methode aufrufen, während ein anderer Threadauf das Objekt zugreift,

wenn sie in der aufgerufenen, synchronized Methode wait()aufrufen.

840

Parallelitätsregeln

Wenn 2 oder mehr Threads ein Objekt modifizieren, solltendie modifizierenden Methoden als synchronizeddeklariert werden.

Wenn eine Methode einen Thread anhalten muß, um dasObjekt selbst zu ändern, dann sollte wait() aufgerufenwerden.

Wenn eine synchronized Methode ihr Objekt ändert, dannsollten die gerade wartenden Prozesse mit notifyAll()alarmiert werden.

Page 210: Java

841

Monitorkonzept

• Es lassen sich sowohl einzelne Blöcke, als auch ganzeMethoden schützen:– Eine ganze Methode kann durch Kennzeichnung von synchronized

geschützt werden, z. B.:public synchronized int get() { ...}

– Ein Block kann durchsynchronized( ObjektName) {

...}geschützt werden. Hierbei wird der Monitor des Objektes ObjektNamebelegt.

842

Methoden der Klasse Object

• Alle Threads, die den Monitor einer Klasse bekommen wollen,werden in einer Warteliste aufgenommen. Hier greifen danndie bereits oben diskutierte Zustandsübergänge.

• Sie sind solange blockiert, bis sie geweckt werden:– Die Methode public final void notify() der Klasse Object

benachrichtigt einen Thread aus der Warteliste auf den zum Objektzugehörigen Monitor (willkürliche Auswahl)

– Die Methode public final void notifyAll() der Klasse Objectbenachrichtigt alle Threads aus der Warteliste, diese werden um denMonitor konkurrieren

843

Methoden der Klasse Object

• Monitor vorübergehend freigeben:– Mit der Methode

public final void wait() throws InterruptedExceptionwird der Monitor freigegeben und der Thread geht in Wartezustand, biser von einem anderen Thread durch notify() oder notifyAll()geweckt wird

– Nach Wecken setzt der Thread seine Arbeit an gleicher Stelle fort– Wichtig, um auf nicht freie Resourcen zu warten

=> andere Threads müssen die Chance bekommen, die Resourcenfreizugeben

844

Beispiel: Handshake-Verfahren

• Wenn Daten zwischen Threads ausgetauscht werden sollen,gibt es Synchronisationsprobleme.

• Tunnel-Klasse soll von einem Thread jeweils ein Paket Datenaufnehmen und an einen anderen Thread weitergeben

• Alle Synchronisationsprobleme sollen in dieser Klasse gelöstwerden

• Erzeuger- und Verbraucherklassen sollen in eigenem Threadlaufen

Page 211: Java

845

Handshake-Verfahren: Tunnelclass Tunnel {

private int inhalt;private boolean verfügbar = false;

public synchronized int nehmen() { // List int aus Tunnelwhile (verfügbar == false) {

try {wait();

} catch (InterruptedException e){}}verfügbar = false;notifyAll();return inhalt;

}public synchronized void geben(int wert) { // Schreibt int in Tunnel

while (verfügbar == true) {try {

wait();} catch (InterruptedException e) {}

}inhalt = wert;verfügbar = true;notifyAll();

}}

846

Handshake-Verfahren: Erzeugerclass Erzeuger extends Thread {

private Tunnel t;

public Erzeuger(Tunnel tunnel) {t = tunnel;

}

public void run() {for (int i=0; i<5; i++) {

t.geben(i);System.out.println("Erzeuger schreibt " + i);try {

Thread.sleep((int)(Math.random() * 100));} catch (InterruptedException e) {}

}}

}

847

Handshake-Verfahren: Verbraucherclass Verbraucher extends Thread {

private Tunnel t;

public Verbraucher(Tunnel tunnel) {t = tunnel;

}

public void run() {int wert = 0;for (int i=0; i<5; i++) {

wert = t.nehmen();System.out.println("Verbraucher liest " + wert);

}}

}

848

Handshake-Verfahren: StartKlasseclass StartKlasse {

public static void main(String[] args) {Tunnel t = new Tunnel();Erzeuger e = new Erzeuger(t);Verbraucher v = new Verbraucher(t);

e.start();v.start();

} Ausgabe:} Erzeuger schreibt 0

Verbraucher liest 0Verbraucher liest 1Erzeuger schreibt 1Verbraucher liest 2Erzeuger schreibt 2Verbraucher liest 3Erzeuger schreibt 3Verbraucher liest 4Erzeuger schreibt 4