HOCHSCHULE MUENCHEN

Werbung
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – Inhalt – TH/KR – 01
-------------------------------------------------------------------------------------------------------------------------------------------------------
Programmieren Grundlagen (4. Sem.)
Teil 2: Einführung in die OOP mit Java
Unterlagen erstellt durch Prof. Dr. Rainer Thomas
Vorlesung Prof. Dr. Heribert Kristl
10. Grundlegende Eigenschaften von Java
10.1
10.2.
10.3.
10.4.
10.5.
10.6.
Java und C
Klassen und Kapselung
Programmstruktur und Startklasse
Erzeugung und Start von Java-Programmen
Packages in Java
Java-Standardbibliothek (Java API)
11. Datentypen in Java
11.1.
11.2.
11.3.
11.4.
11.5.
11.6.
11.7.
11.8.
Einfache Datentypen
Referenztypen und Objekterzeugung
Konstante in Java
Wrapper-Klassen für die einfachen Datentypen
Strings
Arrays
Die Klasse Object
Beispiel : Klasse Ratio
12. Elementare Programmfunktionalitäten
12.1.
12.1.
12.3.
12.4.
Zugriff zu Programmparametern
Standard-Ein- und Ausgabe
Exceptions
Dateizugriff
13. Vererbung und Polymorphie
13.1.
13.2.
13.3
13.4.
13.5.
Umfassende Klassendefinition
Klassenableitung
Polymorphie
Interfaces und ihre Implementierung
Programmbeispiel : Simpson-Integration
14. Grundkonzepte der Objektorientierten Programmierung
14.0.
14.1.
14.2.
14.3.
14.4.
14.5
Grundgedanke der OOP
Objekte und Klassen
Kapselung
Vererbung
Polymorphie
Klassenbeziehungen
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/00/0 – TH – 01
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Programmieren (4. Sem.)
Kapitelüberblick
10. Grundlegende Eigenschaften von Java
10.1. Java und C
10.2. Klassen und Kapselung
10.3. Programmstruktur und Startklasse
10.4. Erzeugung und Start von Java-Programmen
10.5. Packages in Java
10.6. Java-Standardbibliothek (Java API)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/01/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Java und C (1)
• Java-Entwicklung
◇ Java wurde von der Fa. Sun entwickelt. Die Entwicklung begann im Jahr 1990.
1995 wurde Java erstmals der Öffentllichkeit vorgestellt (Sun World 95).
Seit 1996 stellt die Fa. Sun (jetzt Oracle) "offizielle Java-Versionen" in Form von Java Development Kits
kostenlos zum Download bereit.
Die Java Development Kits enthalten alle für die Entwicklung von Java-Programmen benötigten Tools
(Compiler, Interpreter (Java Virtual Machine, JVM), weitere Dienstprogramme und die Standardbibliothek)
▻ 1996
(Jan.) Freigabe des Java Development Kits 1.0 (JDK 1.0)
▻ 1997
JDK 1.1
▻ 1998
JDK 1.2, kurze Zeit später umbenannt in Java 2 Platform
▻ 2000
JDK 1.3 (Offizieller Name : Java2 System Development Kit 1.3, J2SDK 1.3)
▻ 2002
JDK 1.4 (J2SDK 1.4)
▻ 2004
JDK 1.5 (JDK 5.0)
▻ 2006
JDK 1.6 (JDK 6.0)
▻ 2011
(Mitte) geplant : JDK 7.0
• Java2-Plattformen
► Java2 Standard Edition (J2SE)
► Java2 MicroEdition (J2ME), eingeschränkter Sprachstandard für den Einsatz in Geräten wie Mobiltelefonen,
PDAs usw
► Java2 Enterprise Edition (J2EE), zusätzliche Komponenten zur Entwicklung unternehmensweiter verteilter
Anwendungen (u.a. Enterprise Java Beans, EJB)
• Java – ein C-Derivat
◇ Java kann als Derivat der Sprache C betrachtet werden.
Die Syntax und großenteils die Semantik von Java entsprechen weitgehend der Syntax und Semantik von C.
Anweisungen und Variablenvereinbarungen werdem im wesentlichen wie in C formuliert.
◇ Im Unterschied zu C++, einer ebenfalls von C abgeleiteten hybriden (prozedural und objektorientiert
verwendbaren) Programmiersprache, ist Java eine rein objektorientierte Sprache.
◇ Außer von C ist Java auch stark von C++ und weiteren objektorientierten Programmiersprachen wie Oberon,
Ada, Eiffel, Objective-C beeinflusst worden.
◇ Zahlreiche fehleranfällige oder redundante Bestandteile /Eigenschaften von C/C++ wurden nicht
implementiert. Wo sinnvoll und erforderlich sind diese durch "bessere" Konzepte ersetzt.
◇ Ein weiterer elementarer Unterschied zwischen C und Java liegt in der Anwendbarkeit der erzeugten
Programme :
- Ein C-Compiler erzeugt Maschinen-Code, C-Programme laufen direkt, aber nur auf der jeweiligen
Hardware, für die sie erzeugt wurden.
- Ein Java-Compiler erzeugt einen maschinenunabhängigen Byte-Code. Dieser kann als Maschinencode
einer virtuellen Maschine aufgefasst werden. Æ Java-Programme müssen mittels eines Interpreters
(Java Virtual Machine, JVM) ausgeführt werden.
Ein einmal erzeugtes Java-Programm läuft damit aber auf jeder Hardware, für die eine JVM existiert.
Æ Motto von Sun : Write Once , Run Anywhere
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/01/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Java und C (2)
• In Java nicht implementierte C-Eigenschaften
Im wesentlichen fehlen in Java die folgenden C- Eigenschaften bzw Sprachelemente :
▻ Pointer und Pointerarithmetik
▻ Funktionspointer
▻ Speicherklassen (auto, register, extern)
▻ globale Variable
▻ freie Funktionen
▻ inline-Funktionen
▻ die strukturierten Typen struct und union
▻ Bitfelder
▻ Datentyp long double
▻ vorzeichenlose Datentypen (kein unsigned und damit auch kein signed)
▻ Äquivalenz zwischen logischen (bool) und ganzzahligen Werten (keine Konvertierung zwischen bool
und int)
▻ Einführung neuer Typnamen mittels typedef
▻ Sprunganweisung goto
▻ sizeof-Operator
▻ Komma-Operator
▻ ->-Operator
▻ Preprozessoranweisungen (Textersatz (Makros), bedingte Kompilierung)
▻ Header-Dateien
▻ Extern- und Vorwärtsreferenzen
▻ Dynamische Allokation von Variablen einfacher Datentypen
▻ Datentypen long long, _Bool, sowie komplexe und imaginäre Datentypen (C99)
▻ Datentyp wchar_t (ein in C in Headerdateien mittels typedef definierter Typ)
• In Java geänderte Eigenschaften von C (C90)
▻ Die Trennung eines Blockes in Vereinbarungsteil (am Anfang) und Anweisungsteil existiert in Java nicht
Æ Vereinbarungen und Anweisungen können beliebig gemischt werden.
▻ Der Anfangsausdruck im Kopf einer for-Anweisung kann durch eine initialisierte Variablendefinition
ersetzt werden Æ keine vorherige Definition einer "Laufvariablen" notwendig
Beispiel :
for (int i=1; i<=end; i++)
// ...
▻ In der Parameterliste einer parameterlosen Funktion darf das Schlüsselwort void nicht angegeben
werden. Die Parameterliste muß leer bleiben.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/01/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Vergleich der Schlüsselworte und Identifier von Java und C
• Schlüselworte (key words)
reine CSchlüsselworte
++) C-99
Schlüsselworte,
die in C und Java
enthalten sind
*) in Java reserviert,
aber nicht
verwendet
neue
Schlüsselworte
von Java
auto
extern
inline
register
restrict
signed
sizeof
struct
typedef
union
unsigned
_Bool
_Complex
_Imaginary
break
case
char
const
*)
continue
default
do
double
else
enum
float
for
goto
if
int
long
return
short
static
switch
void
volatile
while
abstract
assert
boolean
byte
catch
class
extends
false
**)
final
finally
implements
import
instanceof
interface
native
new
null
**)
package
private
protected
++)
*)
++)
++)
++)
public
strictfp
super
synchronized
this
throw
throws
transient
true
**)
try
**) genau genommen handelt es sich hierbei in Java nicht um ein Schlüsselwort,
sondern um eine Konstante (literal)
• Identifier
◇ Identifier (Namen) in Java werden nach den gleichen Regeln wie in C gebildet :
▻ Sie bestehen aus Buchstaben, dem Underscore ('_') und Ziffern
▻ Sie müssen mit einem Buchstaben oder dem Underscore ('_') beginnen
▻ Groß- und Klein-Buchstaben sind unterschiedlich
▻ Sie dürfen nicht wie ein reserviertes Wort (einschliesslich false, true und null) lauten
◇ Zusätzlich dürfen Java-Identifier das Dollarzeichen ('$') enthalten.
Dieses wird wie ein Buchstabe behandelt (Beginn mit '$' ist zulässig)
◇ Als Buchstaben sind alle Unicode-Buchstaben (also auch andere als im lateinischen Alphabet) zulässig
◇ Java-Identifier dürfen aus beliebig vielen Zeichen bestehen.
◇ Konventionen (nicht verpflichtend) bezüglich der Schreibweise :
▻ Variable : nur Kleinbuchstaben, z. Tl. aber auch Unterteilung in Folge-Abschnitte (Beginn mit Groß-Bu)
▻ Konstante : nur Großbuchstaben
▻ Funktionen : Beginn mit Klein-Bu, häufig Unterteilung in Abschnitte, die jeweils mit Groß-Bu beginnen
▻ Typen (Klassen) : Beginn mit Groß-Bu, Unterteilung in Abschnitte, die jeweils mit Groß-Bu beginnen
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/01/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Operatoren in Java
• Operator-Hierarchie von Java
Priorität
Operator
Operation
1
[]
()
.
++ (Postfix)
-- (Postfix)
Indizierung
Funktionsaufruf
Komponentenzugriff
Increment
Decrement
lÆr
2
++ (Prefix)
-- (Prefix)
+
!
~
Increment
Decrement
Identität
Negation (arithmetisch)
Negation (logisch)
bitweises Komplement
lÅr
3
new
(type)
Objekterzeugung
Typkonvertierung (Cast)
lÅr
4
* / %
Multiplikation / Division / Modulus
lÆr
5
+
-
Addition bzw Konkatenation (Strings)
Subtraktion
lÆr
6
<<
>>
>>>
Linkssschieben
Rechtsschieben, Nachschieben des Vorzeichens
Rechtsschieben, Nachschieben von 0
lÆr
*)
*)
Assoziativität
7
< <=
> >=
instanceof *)
Vergleich (kleiner / kleiner gleich)
Vergleich (größer / größer gleich)
Typprüfung
lÆr
8
== !=
Vergleich (gleich / ungleich)
lÆr
9
&
bitweises UND
lÆr
10
^
bitweises EXOR
lÆr
11
|
bitweises ODER
lÆr
12
&&
logisches UND
lÆr
13
||
logisches ODER
lÆr
14
?:
bedingte Auswertung
lÅr
15
=
*= /= %=
+= -=
<<= >>=
>>>=
*)
&= ^= |=
Zuweisung
Zuweisung mit Verknüpfungsoperation
lÅr
*) neue Operatoren in Java
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/02/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassen und Kapselung (1)
• Klassen – Grundbausteine eines Java-Programms
◇ Im vorigen Kapitel wurde ein OOP-Programm im wesentlichen als eine Ansammlung miteinander kommunizierender Objekte definiert.
Objekte werden durch Klassen beschrieben. Eine Klasse definiert die jeweiligen Eigenschaften (den Aufbau)
und das Verhalten (die Funktionalität) der von ihr instanzierbaren Objekte.
◇ Klassen sind die elementaren Bestandteile jedes Java-Programms.
Sämtlicher Code eines Java-Programms befindet sich innerhalb von Klassen.
Ein Programm kann aus beliebig vielen Klassen bestehen.
• Aufbau von Klassen
◇ Eine Klasse ist aus Klassenkomponenten aufgebaut. Diese werden in einer Klassendefinition festgelegt.
Klassenkomponenten können sein :
- Datenkomponenten (Membervariable) Æ Variablendefinitionen
Die Gesamtheit der Datenkomponenten beschreibt den Aufbau und – mit ihren jeweiligen konkreten
Werten in einem Objekt – den Zustand der Objekte (Æ Objektvariable).
- Funktionskomponenten (Memberfunktionen) Æ Funktionsdefinitionen
Diese legen das Verhalten, die Fähigkeiten der Objekte fest (Æ Objektfunktionen).
◇ Eine Klasse kann auch Komponenten (sowohl Daten- als auch Funktionskomponenten) enthalten, die nicht
objekt-spezifisch sind, sondern den Zustand und das Verhalten der Klasse selbst beschreiben.
Sie sind durch den Modifizierer static gekennzeichnet.
Æ statische Datenkomponenten (Klassenvariable) bzw statische Funktionskomponenten
(Klassenfunktionen)
◇ Zusätzlich kann eine Klassendefinition
- Konstruktoren enthalten
Konstruktoren sind spezielle klassenspezifische Funktionen, die bei der Objekterzeugung aufgerufen werden.
Sie tragen immer den Klassennamen und besitzen keinen Rückgabetyp (auch nicht void).
Sie werden in Java nicht zu den Memberfunktionen und nicht zu den Klassenkomponenten gerechnet.
Ihre primäre Aufgabe besteht in der Initialisierung der Datenkomponenten des erzeugten Objekts.
Konstruktoren können Parameter besitzen (Æ Initialisierungswerte). Ein parameterloser Konstruktor wird
auch als no-arg-Konstruktor bezeichnet.In einer Klasse können mehrere Konstruktoren – mit jeweils
unterschiedlicher Parameterliste – definiert sein. Falls eine Klassendefinition keinen Konstruktor enthält,
wird vom Compiler implizit ein Default-Konstruktor (parameterlos) bereitgestellt.
◇ Eine Klassendefinition kann noch weitere Bestandteile enthalten (s. später)
• Kapselung
◇ Das Konzept der Kapselung wird in Java durch die Festlegung von Zugriffsberechtigungen zur Klasse
selbst und zu den Datenkomponenten realisiert.
◇ Dies erfolgt durch die Angabe von Zugriffs-Modifizierern. Hierfür existieren folgende Möglichkeiten :
- kein Zugriffs-Modifizierer : Zugriffsberechtigung "package".
Ein Zugriff besteht nur von innerhalb des Packages (eine Art Namensraum), in dem die Klasse definiert ist.
- Modifizierer public : Ein Zugriff ist von überall her möglich (öffentlicher Zugriff).
- Modifizierer private (nur für Klassenkomponenten) : Zugriff nur von innerhalb der Klasse, in dem
die jeweilige Komponente definiert ist.
- Modifizierer protected (nur für Klassenkomponenten) : Zugriff beschränkt auf die Klasse selbst,
auf abgeleitete Klassen und auf das Package
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/02/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassen und Kapselung (2)
• Vereinfachte Syntax der Klassendefinition
(vollständiges Syntax-Diagramm s. später)
class
Klassen-Name
{
Komponentendefinition
public
}
Konstruktordefinition
;
◇ Komponentendefinition : Variablen- oder Funktionsdefinition
Beide können beliebig gemischt werden
▻ Variablendefinition (Definition von Datenkomponenten)
Typangabe
Variablenname
Feld-Modifizierer
Initialisierer
=
;
,
Datenkomponenten können bei der Definition initialisiert werden (mit einem typkonformen Ausdruck)
Æ Feld-Initialisierer
▻ Funktionsdefinition (Definition von Memberfunktionen), vereinfacht
Rückgabetyp
MethodenModifizierer
Methoden-Name
(
Methoden-Kopf
{
Formal-Parameterliste
)
throws-Klausel
Anweisung
}
MethodenRumpf
Die wichtigsten Feld- bzw Methoden-Modifizierer sind (es gibt noch weitere) :
- die Zugriffs-Modifizierer public, private und protected
- static
: Die Komponente ist eine Klassenkomponente
- final : Bei Datenkomponenten : Komponente ist eine Konstante
Bei Memberfunktionen : Methode kann in abgeleiteten Klassen nicht überschrieben werden
Wenn eine Methode keine Parameter besitzt, ist die Formal-Parameterliste leer (kein void !!!)
Die throws-Klausel deklariert Exceptions, die von der Funktion geworfen werden (s. später)
◇ Konstruktordefinition : analog zur Funktionsdefinition, mit folgenden Unterschieden :
▻ als (Konstruktor-) Modifizierer sind nur die Zugriffs-Modifizierer zulässig
▻ kein Rückgabetyp
▻ Methodenname == Klassenname
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/02/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassen und Kapselung (3)
• Beispiel einer einfachen Klassendefinition :
class Uhr
{
private long acttime;
public Uhr()
{ acttime = 0;
}
// Datenkomponente
// Konstruktor
void setTime(long time)
{ acttime = time;
}
long tick()
{ ++actTime;
return acttime;
}
// Funktionskomponenten
void displayClock()
{
/* ... */
};
}
Anmerkung : Der Klassenname allein dient als Typ-Bezeichnung für Variablendefinitionen
• Zugriff zu Klassenkomponenten
◇ Ein Zugriff von ausserhalb der Klasse ist nur entsprechend der durch den jeweiligen Zugriffs-Modifizierer
festgelegten Berechtigung möglich.
Zu private-Komponenten ist ein Zugriff von außen grundsätzlich nicht zulässig
◇ Klassenkomponenten (sowohl Daten- als auch Funktionskomponenten) werden mittels des – aus C für den
Struktur-Komponenten-Zugriff bekannten – Komponentenzugriff-Operators . ausgewählt :
▻ objektspezifische Komponenten über eine Objekt-Referenz
Beispiel :
myClck sei eine Referenz auf ein Uhr-Objekt
Æ myClck.displayClock();
// Methodenaufruf
Interpretation : An das durch myClock referierte Objekt wird die Botschaft displayClock
geschickt. Das Objekt reagiert daraufhin mit der Ausführung der zugeordneten Methode.
▻ klassenspezifische Komponenten (static !!!) über den Klassennamen.
Beispiel :
System ist eine Bibliotheksklasse, die u.a. die statische Methode
getProperties() besitzt.
Æ System.getProperties()
// Methodenaufruf
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/03/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Struktur von Java-Programmen (1)
• Modulkonzept
◇ Ein Java-Programm besteht nur aus Klassen.
◇ Jede Klasse muß in einer eigenen Quelldatei vollständig definiert und implementiert werden.
Ausnahme von der eigenen Quelldatei : eingebettete Klassen (nested classes).(hier nicht betrachtet)
Der Quelldatei-Hauptname muß wie der (Haupt-)Klassenname lauten.
Die Quelldatei-Extension ist .java.
Beispiel : Klasse Welcome Æ Quelldateiname : Welcome.java
◇ Eine Quelldatei ist die Übersetzungseinheit (Übersetzungs-Modul).
Für jede enthaltene Klasse wird vom Compiler eine eigene Byte-Code-Datei erzeugt.
Die Byte-Code-Datei für die (Haupt-)Klasse bekommt den Hauptnamen der Quellcode-Datei und die
Extension .class
Beispiel : Aus Welcome.java erzeugt der Compiler Welcome.class
Nur bei eingebetteten Klassen : Die Hauptnamen der übrigen Byte-Code-Dateien sind aus den Namen der
Haupt-Klasse und der eingebetteten Klassen zusammengesetzt.
• Programmstruktur
◇ Ein Linken der getrennt übersetzten Module (Klassen-Dateien) zu einer – ausführbaren – Programm-Datei
findet in Java nicht statt.
◇ Ein Java-Programm ist damit konzeptionell nicht in einer einzigen Datei zusammengefasst. Vielmehr
besteht es – entsprechend den im Programm eingesetzten Klassen – aus einer oder mehreren Dateien.
Anmerkung : Es gibt Möglichkeiten der Zusammenfassung zu einer Archiv-Datei (hier nicht betrachtet)
◇ Eine dieser Dateien muß die Start-Klasse des Programms enthalten.
◇ Ausgehend von der Start-Klasse werden die übrigen Klassen des Programms referiert.
• Programmarten
◇ Es werden zwei Java-Programmarten unterschieden :
▻ Applikations-Programme
▻ Applets
◇ Applikationsprogramme
"Normale" Java-Programme. Sie werden durch direkten Start der Virtuellen Maschine (JVM) ausgeführt.
Hierfür ist dieser beim Start die Start-Klasse des Programms als Parameter zu übergeben
◇ Applets
Diese Programme werden innerhalb eines Java-fähigen Web-Browsers (oder im Kontext eines anderen
"applet viewers") ausgeführt. Ein derartiger Browser (bzw "applet viewer") enthält eine – gegebenenfalls über
ein Plug-In eingebundene – JVM. Der Applet-Code befindet sich üblicherweise auf einem Server und wird
durch ein <Applet>-Tag im HTML-Code einer Web-Seite referiert. Stößt der Browser beim Interpretieren
des HTML-Codes auf ein derartiges <Applet>-Tag, startet er seine JVM. Diese lädt von der angegebenen
URL den Byte-Code der Start-Klasse des Applets und führt ihn aus.
Applets sind damit – i.a. kleine – Programme, die in einfacher Art und Weise über das Internet verteilt werden
können. Da Applets prinzipiell unzuverlässigen Code enthalten können, unterliegt ihre Ausführung strengen
Sicherheitsrestriktionen.
Der Start und die Ausführung eines Applets unterscheidet sich aber erheblich von Start und Ausführung eines
Applikations-Programms.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/03/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Struktur von Java-Programmen (2)
• Start-Klasse eines Java-Applikations-Programms
◇ Die der JVM beim Start zu übergebene Klasse muß – neben möglicherweise beliebig vielen anderen
Methoden – eine statische main()-Methode besitzen.
Diese main()-Methode muß öffentlich zugänglich (public) und vom Typ void sein.
Als formalen Parameter muß sie ein String-Array besitzen.
Sie stellt den Startpunkt der Programmausführung dar.
◇ Beispiel für ein minimales Java-Programm :
// Welcome.java
public class Welcome
{
public static void main(String[] args)
{
System.out.println("Welcome to the world of Java");
}
}
◇ I.a. ist ein Java-Programm nicht klassenorientiert sondern objektorientiert. D.h. im Programm werden
Objekte erzeugt, die miteinander kommunizieren.
Die Erzeugung des "ersten" Objekts erfolgt dann in der main()-Methode der Start-Klasse :
▻ Entweder durch Instantiierung einer anderen Klasse (Start-Klasse dient nur zum Programmstart)
▻ oder durch Instantiierung der eigenen Klasse (Start-Klasse enthält auch spezifische Programmfunktionalitäten)
◇ Ausgehend vom ersten Objekt werden dann die weiteren Objekte erzeugt.
◇ Beispiel für ein minimales Java-Programm mit Objekterzeugung :
// Willkommen.java
public class Willkommen
{
Willkommen()
{
// nur zur Demonstration
}
// Konstruktor
void begruessung()
// Memberfunktion
{
System.out.println("Willkommen bei Java");
}
public static void main(String[] args)
{
Willkommen gruss = new Willkommen();
gruss.begruessung();
}
// Erzeugung eines Objekts
}
◇ Anmerkung :
Häufig wird auch bei Klassen, die in der späteren Verwendung nicht als Start-Klassen dienen sollen, eine
statische main()-Methode vorgesehen. Diese Methode enthält dann i.a. Code, der das – weitgehend
isolierte – Testen der Klasse ermöglicht.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/04/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Erzeugung und Start von Java-Programmen
• Vom Quellprogramm zur Programmausführung
Quell-Datei
(z.B.Welcome.java)
Java-Compiler
weitere
Byte-Code-Dateien
javac
Byte-Code-Datei
(z.B.Welcome.class)
Java-Interpreter
(Java Virtual Machine)
java
• Aufruf des Java-Compilers (Kommandozeilen-Tool javac des JDK)
◇ Der Compiler sucht die zu übersetzende Quelldatei ausgehend vom aktuellen Arbeitsdirectory.
Befindet sich die Datei in einem anderen Directory, ist ein entsprechender Zugriffspfad anzugeben.
◇ Der Name der zu übersetzenden Quelldatei ist einschließlich der Extension .java anzugeben.
◇ Beispiel :Quelldatei Welcome.java im Directory E:\Java\Vorl
E:\Java\Vorl>javac Welcome.java
◇ Der Compiler erzeugt – bei Fehlerfreiheit – eine Byte-Code-Datei (hier : Welcome.class) im
Verzeichnis der Quelldatei.
◇ Fehler werden zusammen mit der Zeilennummer und dem Quelldateinamen gemeldet.
◇ Werden in einer Quelldatei weitere Klassen referiert und findet der Compiler keine entsprechenden
.class-Dateien, versucht er diese durch zusätzliches Übersetzen der entsprechenden .java-Dateien
zu erzeugen. (Ausnahme : Klassen der Standardbibliothek)
• Aufruf des Java-Interpreters (Kommandozeilen-Tool java des JDK)
◇ Dem Java-Interpreter ist der Klassenname (nicht der Dateiname, d.h. keine Extension !) der Start-Klasse als
Programm-(Kommandozeilen-)Parameter zu übergeben.
◇ Der Java-Interpreter sucht nach der Byte-Code-Datei der Start-Klasse im aktuellen Directory und – falls
dort nicht vorhanden – in den Directories, die in der Environment-Variablen CLASSPATH enthalten sind.
◇ Beispiel : Byte-Code-Datei Welcome.class (mit Klasse Welcome) im Verzeichnis E:\Java\Vorl
CLASSPATH-Variable ist nicht gesetzt.
E:\Java\Vorl>java Welcome
◇ Werden von der Start-Klasse weitere Klassen benötigt, sucht der Interpreter die entsprechenden Byte-CodeDateien im aktuellen Directory bzw in den Directories der CLASSPATH-Variablen
(Ausnahme : Klassen der Standardbibliothek)
◇ Wird eine benötigte Byte-Code-Datei nicht gefunden, wird die Exception NoClassDefFoundError
erzeugt.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/05/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Packages in Java (1)
• Packages als Namensräume
◇ Klassen lassen sich in Java in Pakete (Packages) gruppieren.
Packages können als Namensräume (name spaces) aufgefasst werden, in denen irgendwie zusammengehörige Klassen zusammengefasst sind (z.B. zu einem bestimmten Projekt gehörend, von einem bestimmten
Entwickler erzeugt, zu einer bestimmten Bibliothek gehörend usw).
◇ Packages haben einen Namen und können hierarchisch strukturiert (Package Æ Unter-Package) sein.
Æ Package-Namen können aus mehreren Bestandteilen bestehen, die durch einen Punkt ('.') vonein ander getrennt sind.
◇ Damit lässt sich eine Klasse über einen vollständigen Klassennamen ansprechen.
Dieser besteht aus dem eigentlichen Klassennamen, dem der durch einen Punkt (.) abgetrennte
Package-Name vorangestellt ist.
Æ voll-qualifizierter Klassenname
Package-Name
Beispiel :
.
Klassenname
Klasse Date im Package java.util
voll-qualifizierter Klassenname : java.util.Date
◇ Mittels Packages lassen sich Namenskonflikte, insbesondere zwischen Klassen unterschiedlicher Hersteller
(Bibliotheken), weitgehend vermeiden.
◇ Empfohlene Konvention zur Vergabe von Package-Namen :
Beginn des Package-Namens mit dem invertierten Internet-Domain-Namen des Herstellers.
Beispiel : Fa. SESA, Internet-Domain-Name : sesa.com
Package-Name : com.sesa.wmf
Es ist auch üblich, aus Gründen der Übersichtlichkeit den Top-Level-Domain-Namen wegzulassen.
◇ Klassen, die explizit keinem Package zugeordnet sind, befinden sich im namenlosen Package (unnamed
package). Für die Verwendung in Bibliotheken sind derartige Klassen nicht geeignet.
• Packages als Directory-Struktur
◇ Ein strukturierter Package-Name wird in eine entsprechende Directory-Struktur abgebildet.
◇ Beispiel : Klassen-Dateien des Packages com.sesa.wmf sind im Verzeichnis com\sesa\wmf
◇ Das Start-Verzeichnis einer derartigen Directory-Struktur muss sich im aktuellen Verzeichnis oder in
einem über die CLASSPATH-Variable festgelegten Verzeichnis befinden.
◇ Package-Namen ermöglichen damit eine strukturierte und dadurch übersichtliche Ablage von KlassenDateien.
◇ Klassen-Dateien des namenlosen Package müssen direkt im aktuellen Directory bzw in einem durch die
CLASSPATH-Variable festgelegten Verzeichnis liegen.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/05/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Packages in Java (2)
• Package-Zuordnung einer Klasse
◇ Hierzu dient die package-Vereinbarung
package
Beispiel :
Package-Name
;
package hm.ee.vorl;
◇ Die package-Vereinbarung muss am Beginn einer Quelldatei (erste Vereinbarung) stehen.
Sie legt fest, dass die nachfolgend definierte Klasse zu dem angegebenen Package gehört.
• Verwendung von Klassen des eigenen Packages
◇ Eine Klasse kann eine andere Klasse ihres eigenen Packages allein mit dem einfachen Klassennamen
verwenden.
◇ Jede Klasse eines Packages hat Zugriff zu den anderen Klassen desselben Packages, die nicht private
sind, auch wenn sie nicht explizit public deklariert sind. (Zugriffsberechtigung "package")
• Verwendung von Klassen aus anderen Packages
◇ Eine Klasse kann zu Klassen aus einem anderen Package nur zugreifen, wenn diese explizit public
deklariert sind.
◇ Für die Verwendung bestehen prinzipiell zwei unterschiedliche Möglichkeiten :
▻ Verwendung des voll-qualifizierten Namens.
▻ Importieren der Klassen und Verwendung der einfachen Klassennamen
◇ Verwendung des voll-qualifizierten Namens :
Beispiel : Verwendung der Klasse Date aus dem Package java.util
// Datum1.java
public class Datum1
{
public static void main(String[] args)
{ java.util.Date now = new java.util.Date();
System.out.println(now);
}
}
Nachteil : Klassennamen können sehr lang und damit unhandlich werden.
◇ Importieren von Klassen aus anderen Packages : mittels der import-Deklaration
Diese existiert in zwei Formen :
import
import
voll-qualifizierter Klassenname
Package-Name
.
Importieren einer einzelnen Klasse
;
*
;
Importieren aller Klassen eines
Packages (type import on demand),
aber nicht von dessen Unter-Packages
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/05/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Packages in Java (3)
• Verwendung von Klassen aus anderen Packages, Forts.
◇ Beispiel zum Importieren einer Klasse :
Verwendung der Klasse Date aus dem Package java.util
// Datum2.java
import java.util.Date;
// oder : import java.util.*;
public class Datum2
{
public static void main(String[] args)
{ Date now = new Date();
System.out.println(now);
}
}
◇ Anmerkung : Importieren bedeutet kein Einbinden von Code anderer Klassen.
• Die Zugriffsberechtigung "package"
◇ In Java haben alle Klassenkomponenten einer Klasse, die nicht explizit als public, protected oder
private gekennzeichnet sind, die Zugriffsberechtigung "package". Æ Default-Zugriffsberechtigung
◇ Diese Zugriffsberechtigung erlaubt den Zugriff durch alle Klassen desselben Packages.
◇ Die Zugriffsberechtigung durch ein Package erstreckt sich nicht auf dessen eventuelle Unter-Packages.
Klassen aus Unter-Packages haben keinen Zugriff zu "package"-Komponenten von Klassen ihres OberPackages.
◇ Die Zugriffsberechtigung protected umfasst in Java auch die Zugriffsberechtigung "package"
Æ Zu Klassenkomponenten mit der Zugriffsberechtigung protected können neben den abgeleiteten Klassen
auch alle Klassen desselben Packages zugreifen.
◇ Beispiel :
package vorl.pack1;
public class PackAccDemo
{
int ipa = 1;
protected int ipo = 2;
public int ipu = 3;
// ...
}
// Zugriffsberechtigung package
package vorl.pack1;
class PackAccDemoUse1
{
public static void main(String[] args)
{ PackAccDemo demo = new PackAccDemo();
System.out.println("PackAckDemo.ipa (package)
: " + demo.ipa);
System.out.println("PackAckDemo.ipu (public)
: " + demo.ipu);
System.out.println("PackAckDemo.ipo (protected) : " + demo.ipo);
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/06/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Java-Standardbibliothek (1)
• Allgemeines
◇ Die Java-Plattform stellt auch eine Laufzeit-Bibliothek (API) zur Verfügung.
◇ Diese sehr umfangreiche Java Standard-Bibliothek enthält zahlreiche nützliche Klassen für diverse
Anwendungsbereiche.
Eine Reihe dieser Klassen implementieren wesentliche Spracheigenschaften und sind damit sehr eng
mit der Sprache selbst verknüpft.
◇ Die Klassen der Standardbibibliothek sind auf verschiedene APIs aufgeteilt und in Paketen (Packages)
zusammengefasst. Dabei ist die Zuordnung der einzelnen Klassen zu den verschiedenen Paketen nicht immer
ganz stimmig, insbesondere stimmen die API-Grenzen nicht immer mit den Paketgrenzen überein.
◇ Zu vielen der Haupt-Paketen existieren Unter-Pakete.
◇ Die Pakete der im JDK enthaltenen Java Standard-Bibliothek lassen sich in drei Gruppen einteilen :
▻ Standard-Pakete. Sie gehören zu jeder Java-Plattform
▻ Standard-Erweiterungs-Pakete. Sie stellen erweiterte und ergänzende Funktionalitäten zur Verfügung
und müssen nicht unbedingt auf jeder Java-Plattform zur Verfügung stehen
▻ Ergänzende Pakete von Dritt-Herstellern. Sie ergänzen und erweitern ebenfalls die Funktionalität der
Bibliothek.
◇ Die Java Standard-Bibliothek ist ständig erweitert worden.
(JDK 1.0 : 8 Pakete, JDK 1.4 über 130 Pakete, JDK 5.0 über 170 Pakete, JDK 6.0 203 Pakete)
◇ Sun stellt in der das JDK begleitenden Dokumentation eine ausführliche Beschreibung der Klassen zur
Verfügung (Java Platform API Specification)
• Überblick über die Standard-Pakete
◇ Die Namen der Standard-Pakete beginnen mit java.
◇ Die folgende Tabelle gibt nur einen Überblick über die Haupt-Pakete dieser Gruppe
java.applet
Applets
java.awt
Abstract Windowing Toolkit : Erzeugung von GUIs, mehrere Unter-Pakete
java.beans
Java Beans (Komponenten-Architektur von Java), ein Unter-Paket
java.io
Ein-/Ausgabe mittels Streams, Dateien und Serialisierung
java.lang
Elementare Sprachunterstützung, fünf Unter-Pakete
java.math
Unterstützung von Ganzzahl- und Gleitpunkt-Arithmetik
java.net
Unterstützung von Netzwerkanwendungen
java.nio
New I/O Package, verbesserte I/O-Unterstützung, ab JDK 1.4, vier Unter-Pakete
java.rmi
Remote Method Invocation, Entfernte Objekt-Kommunikation, vier Unter-Pakete
java.security
Sicherheits-Framework, vier Unter-Pakete
java.sql
Datenbankzugriff
java.text
Erweiterte Textdarstellung und –bearbeitung, Internationalisierung, ein Unter-Paket
java.util
Utility-Klassen, Collection Framework, spezielle Datenstrukturen, neun Unter-Pakete
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 11/06/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Java-Standardbibliothek (2)
• Überblick über die Standard-Erweiterungs-Pakete
◇ Die Namen der Standard-Erweiterungs-Pakete beginnt mit javax.
◇ Die folgende Tabelle gibt nur einen Überblick über die Haupt-Pakete dieser Gruppe (hier : Standard Edition)
javax.accessibility
Unterstützung spezieller I/O-Geräte (z.B. für Braille-Zeichen)
javax.activation
Unterstützung der Objekt-Aktivierung
javax.activity
spezielle Exception-Klassen im Zusammenhang mit der CORBA-Serialisierung
javax.annotation
Unterstützung von Annotations, ein Unter-Paket
javax.crypto
Unterstützung kryptographischer Operationen, zwei Unter-Pakete
javax.imageio
I/O von Bilddateien, mehrere Unter-Pakete
javax.jws
Unterstützung von Web Services, ein Unter-Paket
javax.lang.model
Unterstützung der Modellierung der Sprache Java, drei Unter-Pakete
javax.management
Java Management Erweiterungen, mehrere Unter-Pakete
javax.naming
Zugriff zu Namensdiensten, vier Unter-Pakete
javax.net
Ergänzung zur Netzwerkunterstützung, ein Unter-Paket
javax.print
Print Service API, Zugriff zu Print Services, drei Unter-Pakete
javax.rmi
Ergänzung zum RMI-API, zwei Unter-Pakete
javax.script
Scripting API (Definition von Java Scripting Engines)
javax.security
Ergänzung zum Sicherheits-Framework, besteht nur aus Unter-Paketen
javax.sound
Sound API, besteht nur aus Unter-Paketen
javax.sql
Ergänzung zum Datenbankzugriffs-API (serverseitig), drei Unter-Pakete
javax.swing
Swing Toolkit, Erweiterungen zur GUI-Erzeugung, zahlreiche Unter-Pakete
javax.tools
Interfaces und Klassen für Tools zum Starten aus Programmen heraus
javax.transaction
Unterstützung von Transaktionen, ein Unter-Paket
javax.xml
Zugriff zu XML-Dateien, zahlreiche Unter-Pakete
• Ergänzende Pakete von Drittherstellern
◇ Hierzu gehören zahlreiche Pakete unterhalb der org.omg.-Hierarchie.
Sie stellen im wesentlichen CORBA-Unterstützung zur Verfügung
◇ Weitere Pakete befinden sich unter den Hierachien org.w3c. und org.xml.
Sie bieten Unterstützung für den Zugriff zu XML-Dateien.
◇ Das Paket org.ietf.jgss stellt ein Framework zur Nutzung von Sicherheitsdiensten (Authentifizierung,
Daten-Sicherheit, Daten-Integrität usw) unterschiedlichster Mechanismen (wie z.B. Kerberos) zur Verfügung
• Verwendung der Java Standard-Bibliothek
◇ Zur Verwendung von Komponenten der Standard-Bibliothek in eigenen Programmen werden entsprechende
import-Vereinbarungen benötigt, wenn nicht voll-qualifizierte Namen verwendet werden sollen.
Ausnahme : Das Paket java.lang ist so eng mit der Sprache verknüpft, dass es automatisch durch den
Compiler eingebunden wird. Eine explizite import-Anweisung ist daher für Komponenten aus diesem
Paket nicht erforderlich.
◇ Der Java-Compiler und der Java-Interpreter finden den Zugriffspfad zu den Bibliotheks-Dateien
automatisch. Er muss daher nicht in die CLASSPATH-Variable aufgenommen werden (ab JDK 1.2).
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/00/0 – TH – 01
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Programmieren (4. Sem.)
Kapitelüberblick
11. Datentypen in Java
11.1. Einfache Datentypen
11.2. Referenztypen und Objekterzeugung
11.3. Konstante in Java
11.4. Wrapperklassen für die einfachen Datentypen
11.5. Strings
11.6. Arrays
11.7. Die Klasse Object
11.8. Beispiel : Klasse Ratio
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/01/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Einfache Datentypen in Java (1)
• Allgemeines zu Datentypen
◇ Java ist eine streng typisierte Sprache.
Das bedeutet, dass jede Variable und jeder Ausdruck einen Typ hat, der zur Compilezeit bekannt sein muß.
◇ In Java muß jede Variable immer einen definierten Wert haben.: Membervariable werden automatisch mit
einem Default-Wert initialisiert, sofern ihnen nicht explizit ein Wert zugewiesen wird.
Bei lokalen Variablen verhindert der Compiler, dass sie ohne explizite Initialisierung bzw Wertzuweisung
verwendet werden (Definite Assignment).
◇ In Java gibt es zwei Kategorien von Datentypen :
▻ einfache (primitive) Datentypen (primitive types)
▻ Referenz-Typen (reference types)
• Überblick über die einfachen Datentypen
◇ Variable eines einfachen Datentyps enthalten einen Wert ihres jeweiligen Typs.
◇ Java kennt acht einfache Datentypen
◇ Für jeden Datentyp ist der Wertebereich und damit die Größe des belegten Speicherplatzes eindeutig
– unabhängig von der jeweiligen Plattform – festgelegt.
◇ Zu jedem primitiven Datentyp ist in der Standard-Bibliothek eine Wrapper-Klasse definiert (s. später).
◇ Überblick :
Typname Größe
Art des Typs
Wertebereich
Default-Wert WrapperKlasse
byte
1 Byte
vorzeichenbeh. ganze Zahl
-128 ... +127
0
Byte
short
2 Bytes
vorzeichenbeh. ganze Zahl
-215
0
Short
int
4 Bytes
vorzeichenbeh. ganze Zahl
31
-2
... +2 -1
0
Integer
long
8 Bytes
vorzeichenbeh. ganze Zahl
-263
... +263-1
0
Long
char
2 Bytes
Unicode-Zeichen
alle Unicode-Zeichen
'\u0000'
Character
float
4 Bytes
Gleitpunktzahl (reelle Zahl) +/-3.4028...*1038
0.0
Float
double
8 Bytes
Gleitpunktzahl (reelle Zahl) +/-1.7976...*10
0.0
Double
false
Boolean
boolean 1 Bit *) logischer Wert
... +215-1
31
308
false, true
*) Die belegte Speichergröße ergibt sich durch die kleinste adressierbare Speichereinheit (meist 1 Byte)
◇ Der Datentyp float entspricht dem 32-Bit-IEEE-Format (single precision)
Der Datentyp double entspricht dem 64-Bit-IEEE-Format (double precision)
◇ Der Datentyp char zählt (mit byte, short, int und long) zu den ganzzahligen Datentypen.
◇ Die ganzzahligen Datentypen bilden zusammen mit den Gleitpunkttypen (float und double) die
numerischen Typen.
◇ Der logische Datentyp boolean muß überall dort verwendet werden, wo ein logischer Operand
erforderlich ist (logische Operatoren, Steuerausdrücke in den Steueranweisungen, erster Ausdruck im
bedingten Auswerte-Operator).
Ein Ersatz durch ganzzahlige Typen (Werte 0 und !=0) ist nicht zulässig.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/01/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Einfache Datentypen in Java (2)
• Darstellung der Werte der einfachen Datentypen (Konstante, literals)
◇ Die Wertedarstellung entspricht im wesentlichen der von C
◇ Datentypen byte, short, int und long (ganzzahlige Datentypen ohne char) :
▻ Darstellung als Dezimalzahl (Ziffern 0 bis 9, Beginn nicht mit 0)
▻ Darstellung als Oktalzahl : Beginn mit 0 (nur Ziffern 0 bis 7)
▻ Darstellung als Sedezimalzahl : Beginn mit 0x oder 0X (Ziffern 0 bis 9, a bis f, A bis F)
▻ Ziffernfolgen sind grundsätzlich (ohne Suffix) vom Typ int.
Allerdings muss der dargestellte Wert innerhalb des für int zulässigen Bereichs liegen.
▻ Ziffernfolgen mit dem Suffix l oder L sind vom Typ long
▻ Jeder ganzzahlige Wert, kann mit dem Vorzeichen – oder + versehen werden.
◇ Datentypen float und double :
▻ Exponential- oder Dezimalbruchdarstellung
▻ ohne Suffix oder mit Suffix d oder D : Datentyp double
▻ mit Suffix f oder F : Datentyp float
▻ Zusätzlich kann eine Gleitpunktzahl mit dem Vorzeichen – oder + versehen werden.
◇ Datentyp char :
▻ Darstellung eines Einzelzeichens in einfachen Hochkommata (single quotes), z.B.: 'A', 'Π', ':'
▻ Darstellung durch eine C-kompatible Escape-Sequenz in einfachen Hochkommata:
'\b'
'\t'
'\n'
'\r'
'\f'
'\''
'\"'
'\\'
'\ooo'
Backspace (BS)
Horizontaler Tabulator (Horizontal Tab, HT)
Zeilenwechsel (Newline, Linefeed, LF)
Carriage Return (CR)
Seitenwechsel (Form Feed, FF)
Ersatzdarstellung für einfaches Hochkomma (single quote)
Ersatzdarstellung für doppeltes Hochkomma (double quote)
Ersatzdarstellung für Fluchtsysmbol \
Oktal-Escape-Sequenz, 1 bis 3 Oktalziffern, maximaler Wert : 0377
Anmerkung : Die C-Escape-Sequenzen '\v', '\a', '\?' und '\xhhh' sind in Java
nicht implementiert.
▻ Darstellung durch eine Unicode-Escape-Sequenz in einfachen Hochkommata : '\uhhhh'
(h Sedezimalziffer),
z.B. : '\u0041' (== 'A'), '\u00dc' (== 'Ü'), '\uffff'
◇ Für einige Grenzwerte (z.B. größter und kleinster darstellbarer positiver Wert) der numerischen
Datentypen sind in den entsprechenden Wrapper-Klassen (Package java.lang) symbolische
Konstanten (als static public) definiert. Æ s. später
◇ Datentyp boolean
▻ Es existieren nur die beiden Konstanten true und false
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/01/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Einfache Datentypen in Java (3)
• Typkonvertierungen bei einfachen Datentypen
◇ Typkonvertierungen (Casts) zwischen allen ganzzahligen Typen (einschließlich char) und den
Gleitpunkt-Typen sind grundsätzlich zulässig.
◇ Implizite Typkonvertierungen bei typgemischten zweistelligen arithmetischen Operationen vor
Ausführung der Operation (numeric promotion) :
▻ Nur ganzzahlige Operanden (Integer-Operation), kein Operand vom Typ long :
Alle Nicht–int-Operanden werden in den Typ int umgewandelt.
Die Operation wird als int-Operation ausgeführt und liefert ein int-Ergebnis
▻ Nur ganzzahlige Operanden (Integer-Operation), ein Operand vom Typ long :
Der andere Operand wird in den Typ long umgewandelt.
Die Operation wird als long-Operation ausgeführt und liefert ein long-Ergebnis
▻ Ein Operand ist vom Typ double.
Der andere Operand wird in den Typ double umgewandelt.
Die Operation wird als double-Operation ausgeführt und liefert ein double-Ergebnis
▻ Ein Operand ist vom Typ float und der andere nicht vom Typ double.
Der andere Operand wird in den Typ float umgewandelt.
Die Operation wird als float-Operation ausgeführt und liefert ein float-Ergebnis
◇ Implizite Typkonvertierungen zwischen numerischen Typen bei Wertzuweisungen (u. Initialisierungen) :
Nur zulässig, wenn sichergestellt ist, dass keine Information verloren gehen kann :
▻ Ganzzahl-Werte an Ganzzahl-Variable eines größeren Typs.
▻ Ganzzahl-Werte an Gleitpunkt-Variable
▻ int-Konstante an byte-, short- oder char-Variable, wenn die int-Konstante sich auch als
Wert des kleineren Datentyps darstellen lässt.
◇ Alle anderen Umwandlungen zwischen numerischen Typen, wenn also Information verloren gehen könnte,
sind nur explizit möglich (Cast-Operator !).
◇ Zwischen dem Typ boolean und den numerischen Datentypen sind keinerlei Typkonvertierungen
zulässig (auch nicht explizit).
◇ Werte eines numerischen Datentyps lassen sich mit einem String-Operanden (Bibliotheks-Klasse
String) mittels des Konkatenations-Operators (+) vernüpfen. In einem derartigen Fall wird der
numerische Wert in seine dezimale Text-Darstellung umgewandelt und mit dem String-Operanden zu
einem neuen String zusammengefasst.
Beispiel :
double dv = 74.25;
System.out.println("Wert von dv : " + dv);
Æ Ausgabe : Wert von dv : 74.25
◇ Analog lassen sich Werte des Typs boolean mit einem String-Operanden mittels des
Konkatenations-Operators (+) verknüpfen. In einem derartigen Fall wird der logische Wert in seine
Textdarstellung (entweder "true"
oder "false") umgewandelt und mit dem String-Operanden
zu einem neuen String zusammengefasst.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/02/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Referenz-Typen und Objekterzeugung in Java
• Eigenschaften von Referenz-Typ-Variablen
◇ Variable eines Referenz-Typs referieren Objekte, d.h. Instanzen einer Klasse.
Objekte können in Java nicht direkt als Werte verwendet werden (z.B. als Funktions-Parameter), sondern
nur über eine Referenz.
◇ Variable eines Referenz-Typs (Referenz-Variable) werden zwar i.a. als "Objekt-Variable" betrachtet,
tatsächlich sind sie aber Pointer-Variable, die auf ein Objekt verweisen. Sie belegen nur den Speicherplatz
zur Aufnahme einer Objekt-Adresse. Ihr Wert ist also eine Speicheradresse.
Bei ihrer Verwendung werden sie automatisch dereferenziert. (Anwendung des Punkt- (.) Operators
zum Komponentenzugriff).
◇ Eine Referenz-Variable kann immer nur auf Objekte eines bestimmten Typs bzw bestimmter Typen
(Polymorphie !) zeigen.
Formal werden drei Arten von Referenz-Variablen unterschieden :
▻ Klassen-Typen (sie verweisen auf Objekte der entsprechenden Klasse oder auf Objekte davon
abgeleiteter Klassen)
▻ Interface-Typen (sie verweisen auf Objekte, die das jeweilige Interface implementieren)
▻ Array-Typen (sie verweisen auf Arrays, Arrays sind in Java ebenfalls – spezielle – Objekte)
◇ Die für Referenz-Variable definierten Vergleichs-Operatoren == und != beziehen sich auf die
Referenzen (Adressen) und nicht auf die referierten Objekte.
Gleiche Referenzen bedeuten natürlich auch Gleichheit der referierten Objekte.
Ungleiche Referenzen bedeuten aber nicht, dass auch die referierten Objekte ungleich sein müssen.
◇ Als spezielle Referenz-Konstante ist der Wert null definiert.
Eine Referenz-Variable mit diesem Wert zeigt auf nichts (also auf kein Objekt).
Einer lokalen Referenz-Variablen, die auf nichts zeigen soll, muss dieser Wert explizit zugewiesen werden.
Beispiel :
String sa = null;
Für Referenz-Variable, die Member-Variable sind, ist null der ohne explizite Initialisierung zugewiesene Default-Wert.
◇ Mit dem auf Referenz-Variable anwendbaren Operator instanceof lässt sich überprüfen, ob das
referierte Objekt von einem bestimmten Typ ist (s. später).
• Erzeugung von Objekten
◇ Objekte werden grundsätzlich nur namenlos dynamisch auf dem Heap alloziert.
◇ Hierzu dient ein new-Ausdruck : new-Operator mit nachgestellten Konstruktor-Aufruf.
◇ Konstruktoren sind spezielle klassenspezifische Funktionen, die zur Erzeugung eines Objekts benötigt werden.
Sie tragen i.a. den Namen der Klasse des zu erzeugenden Objekts (Ausnahme s. Arrays).
Konstruktoren können Parameter besitzen.
◇ Der new-Ausdruck liefert die Adresse des erzeugten Objekts zurück, die dann einer Referenz-Variablen
als Wert zugewiesen werden kann.
Beispiel :
String sv = new String("Hallo !");
◇ In Java gibt eine in der JVM im Hintergrund laufende automatische Garbage Collection den allozierten
Speicher für ein Objekt wieder frei, wenn keinerlei Referenz mehr auf das Objekt existiert
Eine explizite Freigabe des dynamisch allozierten Speichers ist daher weder notwendig noch überhaupt
möglich Æ In Java existiert daher kein Speicherfreigabe-Operator (wie z.B. delete in C++).
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/03/1 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Konstante in Java
• Der Modifizierer final für Daten
◇ Er legt fest, dass der entsprechende Datenwert nicht geändert werden kann
◇ Anwendbar – sowohl für einfache Datentypen als auch für Referenztypen – auf
▻ statische Datenkomponenten
▻ nichtstatische Datenkomponenten
▻ lokale Variable (in Funktionen)
◇ Für Referenztypen legt final lediglich fest, dass die Referenz nicht änderbar ist, d.h. das referierte
Objekt kann nicht gewechselt werden.
Ob der Zustand dieses referierten Objekts änderbar ist, wird dadurch nicht bestimmt.
• Symbolische Konstante
◇ Sind objektunabhängig.
Æ Definition als nicht-änderbare statische Datenkomponenten (Klassen-Konstante).
Æ Modifizierer static und final.
Wenn sie allgemein verwendbar sein sollen zusätzlicher Modifizierer public.
◇ Initialisierung mit dem durch sie repräsentierten Wert bei der Definition.
◇ Es ist üblich – aber nicht verpflichtend – , Konstanten-Namen mit Großbuchstaben zu bilden.
◇ Beispiele aus der Java-Standard-Bibliothek
public final class Integer
{
public static final int MAX_VALUE = 0x7fffffff;
public static final int MIN_VALUE = 0x80000000;
// ...
}
public final class Math
{
public static final double PI = 3.14159265358979323846;
..// ...
}
◇ Verwendung ausserhalb ihrer definierenden Klasse mit ihrem vollqualifizierten Namen:
klassenname.KONSTANTENNAME
• Objektspezifische und lokale Konstante
◇ Objektspezifische Konstante : Definition als nichtstatische nichtänderbare Datenkomponenten
Æ Modifizierer final (und meist private)
Initialisierung bei der Definition oder durch den Konstruktor, danach nicht mehr änderbar (Æ Fehler !)
Alle nichtstatischen Datenkomponenten final : Æ Objektzustand nicht änderbar (konstantes Objekt)
◇ Lokale Konstante in Funktionen: Modifizierer final vor der Typangabe
Beispiel :
final int ANZ = 10;
Sofern diese nicht bei ihrer Definition initialisiert werden (blank final), kann ihnen später einmal ein
Wert zugewiesen werden
Jeder Versuch einer weiteren Wertzuweisung führt zu einem Compilerfehler.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/04/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Wrapper-Klassen für die einfachen Datentypen (1)
• Verwendung von Werten einfacher Datentypen wie Objekte
◇ Werte einfacher Datentypen und Objekte werden unterschiedlich dargestellt und referiert.
Dadurch lassen sich Werte einfacher Datentypen nicht direkt in Situationen, in denen Objekte benötigt
werden, verwenden (z.B. als Argument in vielen Methoden, aktueller Typ bei generischen Datentypen)
◇ Um eine derartige Verwendung trotzdem zu ermöglichen, existieren Wrapper-Klassen für alle einfachen
Datentypen. Ein Objekt einer Wrapper-Klasse kapselt einen Wert des korrespondierenden einfachen Datentyps. Dieser Wert wird bei der Objekterzeugung festgelegt (Konstruktor-Parameter) und kann später nicht
mehr geändert werden.
• Die Wrapper-Klassen im Überblick
◇ Die Wrapper-Klassen befinden sich im Package java.lang
◇ Alle Wrapper-Klassen – außer Character – verfügen über mindestens 2 Konstruktoren :
▻ Ein Konstruktor besitzt einen Parameter vom zu kapselnden einfachen Typ.
Er dient zur Umwandlung : Wert Æ Objekt
▻ Der zweite Konstruktor besitzt einen String-Parameter.
Der String muss die textuelle Repräsentation des zu kapselnden Wertes sein.
◇ Zur Ermittlung des von einem Wrapper-Klassen-Objekt gekapselten Wertes stellen die Wrapper-Klassen
sogenannte "Getter"-Methoden zur Verfügung (Umwandlung Objekt Æ Wert):
primitivtyp primitivtypValue()
◇
einfacher Datentyp
Wrapper-Klasse
"Getter"-Methode
char
Character
public char charValue()
byte
Byte
public byte byteValue()
short
Short
public short shortValue()
int
Integer
public int intValue()
long
Long
public long longValue()
float
Float
public float floatValue()
double
Double
public double doubleValue()
boolean
Boolean
public boolean booleanValue()
◇ Beispiele :
Integer iobj
Double dobj
long lval1
Long lobj
=
=
=
=
new Integer(27);
new Double("3.14");
-34567L;
new Long(lval1);
int ival
double dval
long lval2
= iobj.intValue();
= dobj.doubleValue();
= lobj.LongValue();
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/04/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Wrapper-Klassen für die einfachen Datentypen (2)
• Umwandlung von Strings in dargestellte Werte
◇ Die Wrapper-Klassen stellen auch statische Methoden zur Verfügung, die einen String, der die textuelle
Repräsentation eines Werts eines einfachen Datentyps ist, in den dargestellten Wert umwandeln.
("Parser"-Methoden)
Falls der String nicht umwandelbar ist, wird von den Methoden eine NumberFormatException
geworfen.
◇ Überblick über die "Parser"-Methoden :
▻ Klasse Byte
: public static byte
▻ Klasse Short
: public static short parseShort(String str)
▻ Klasse Integer
: public static int
parseInt(String str)
▻ Klasse Long
: public static long
parseLong(String str)
▻ Klasse Float
: public static float parseFloat(String str)
▻ Klasse Double
: public static double parseDouble(String str)
parseByte(String str)
▻ Klasse Boolean
: public static boolean parseBoolean(String str)
Der String "true" (unabhängig von Groß-/Kleinschreibung) liefert true, alle anderen
Strings liefern false (Methode existiert erst ab dem JDK 5.0)
◇ Beispiele :
double dv
String is
int iv
boolean bv
=
=
=
=
Double.parseDouble("55.4321");
"98765";
Integer.parseInt(is);
Boolean.parseBoolean("richtig");
• Grenzwerte der numerischen Datentypen
◇ Für alle numerischen Datentypen sind in den entsprechenden Wrapper-Klassen (Package java.lang)
die folgenden symbolischen Konstanten (als static public) definiert :
größter darstellbarer positiver Wert
kleinster darstellbarer positiver Wert
MAX_VALUE
MIN_VALUE
◇ Für die Datentypen float und double sind in den Klassen Float und Double zusätzlich
definiert :
NaN
NEGATIVE_INFINITY
POSITIVE_INFINITY
Not-a-Number (Repräsentation eines ungültigen Werts, z.B. 0/0)
negativ unendlich
positiv unendlich
◇ Verwendung dieser Konstanten immer nur zusammen mit dem jeweiligen Klassennamen
(voll-qualifizierter Name) :
z.B. : double dv = Double.MIN_VALUE;
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/04/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Wrapper-Klassen für die einfachen Datentypen (3)
• Autoboxing/-unboxing (Implizite Umwandlung zwischen Werten und Objekten)
◇ Bis zum JDK 1.4 mußten Umwandlungen zwischen den Werten einfacher Datentypen und Wrapper-KlassenObjekten explizit mittels Konstruktoren und "Getter"-Methoden durchgeführt werden (s. oben).
◇ Mit dem JDK 5.0 wurde das Konzept des Autoboxing/-unboxing eingeführt.
Dieses ermöglicht eine implizite (automatische) Umwandlung zwischen Werten und Objekten.
Æ Werte einfacher Datentypen und Wrapper-Objekte können völlig kompatibel zueinander
verwendet werden.
◇ Wert Æ Objekt (Autoboxing) :
Beispiel 1 :
Beispiel 2 :
int iVal1 = 12;
Integer iObj;
iObj = iVal1;
// implizite Erzeugung eines neuen Integer-Objekts
Double dObj = 0.75; // implizite Erzeugung eines neuen Double-Objekts
◇ Objekt Æ Wert (Autounboxing) :
Beispiel 1 :
int iVal2 = iObj;
// implizites De-Wrapping
Beispiel 2 :
double dVal = dObj; // implizites De-Wrapping
◇ Autoboxing/-unboxing findet überall statt, wo Werte einfacher Datentypen bzw Wrapper-Objekte benötigt
werden.
Damit können z.B. mit Wrapper-Objekten auch "direkt" arithmetische Operationen vorgenommen
werden.
Beispiele :
Integer iObj1 = 10;
Integer iObj2 = iObj1 + 5;
++iObj1;
◇ Autoboxing findet allerdings nur dann statt, wenn keine andere implizit mögliche Typkonvertierung
anwendbar ist.
Derartige Situationen können z.B. bei überladenen Funktionen auftreten.
Beispiel :
void func(double dv);
void func(Integer io);
. . .
func(5) führt zum Aufruf der ersten Methode (func(5.0)) (int Æ double)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/05/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Strings in Java - Allgemeines
• Darstellung von Strings
◇ Strings in Java bestehen aus Unicode-Zeichen.
Wie in C besteht eine String-Konstante (string literal) aus einer Folge von 0 oder mehr Zeichen, die in
doppelte Hochkommata (double qoutes) eingeschlossen sein müssen.
Die Zeichen können auch durch Escape-Sequenzen dargestellt werden.
Beispiele :
"\n\"Hallo\""
"\u00ea\u0256"
◇ Strings sind in Java Objekte.
String-Konstante werden durch Objekte der Bibliotheks-Klasse String dargestellt.
Der Inhalt derartiger Objekte ist unveränderlich.
Zur Darstellung von veränderlichen Strings dienen die Bibliotheks-Klassen StringBuffer (threadsicher) und StringBuilder (ab JDK 5.0, nicht thread-sicher, aber schneller)
◇ Eine String-Variable ist – wie alle Objekt-Variablen in Java – eine Referenz-Variable. Sie enthält eine
Referenz auf ein String-Objekt.
Eine Zuweisung eines neuen Strings an eine String-Variable ("Variable vom Typ String")
bedeutet nicht, dass das referierte String-Objekt geändert wird, sondern dass die String-Variable
ein anderes String-Objekt referiert.
Beispiel :
String str = "Hausboot";
// ...
str = "Segelyacht";
// str zeigt auf ein anderes Objekt !
• Direkte Sprachunterstützung für Strings
◇ In der Sprache Java selbst sind einige Mechanismen zur Erzeugung und Verwendung von Strings
implementiert, die im Zusammenhang mit der Klasse String zur Anwendung kommen
◇ Beim Auftritt einer String-Konstanten im Quelltext erzeugt der Compiler ein String-Objekt, das mit
der String-Konstanten initialisiert wird.
Beispiele : System.out.println("Schoene Gruesse !");
Der Compiler erzeugt ein String-Objekt mit dem Inhalt "Schoene Gruesse !" und
übergibt eine Referenz (Adresse) auf dieses Objekt der Methode println(...)
String s1 = "Das alte Europa";
Der Compiler erzeugt ein String-Objekt mit dem Inhalt "Das alte Europa" und
weist der Variablen s1 eine Referenz (Adresse) auf dieses Objekt zu
◇ Für String-Objekte ist der Operator + überladen als Konkatenations-Operator.
Er erzeugt ein neues String-Objekt, das aus den beiden Operanden zusammengesetzt ist.
Beispiel :
s1 = s1 + " hatte Recht !";
◇ Der + -Operator wirkt auch dann als Konkatenations-Operator, wenn nur ein Operand vom Typ
String ist. In einem derartigen Fall wird der andere Operand implizit in ein String-Objekt
umgewandelt und mit dem String-Operanden zu einem neuen String-Objekt konkateniert.
Die implizite Konvertierung in ein String-Objekt (string conversion) findet für jeden einfachen Typ
und für jeden Referenz-Typ (Klasse !) statt. Ist die in einer Objekt-Variablen gespeicherte Referenz gleich
null, wird der String "null" erzeugt.
Beispiel :
System.out.println("Heute ist : " + new java.util.Date());
◇ Eine String-Konkatenation kann auch mit dem += -Operator realisiert werden. Wenn hier der rechte
Operand kein String-Objekt ist, wird er implizit in ein solches konvertiert.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/05/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse String in Java (1)
• Allgemeines zur Klasse String
◇ Standard-Klasse zur Darstellung von nicht veränderlichen Strings.
◇ Bestandteil des Package java.lang
◇ Von der Klasse String können keine anderen Klassen abgeleitet werden (Die Klasse ist final)
◇ Die Klasse String implementiert das Interface CharSequence
◇ Die Klasse String enthält zahlreicheKonstruktoren und Methoden zur Verwendung von Strings, u.a.
- zur expliziten Erzeugung von String-Objekten (Konstruktoren),
- zur Ermittlung der Stringlänge
- zum lesenden Zugriff zu String-Elementen,
- zum String-Vergleich
- zum Suchen in Strings
- zur Extraktion von Teilstrings,
- zum Kopieren von Strings mit Umwandlung aller Buchstaben in Großbuchstaben bzw Kleinbuchstaben.
• Konstruktoren der Klasse String (Auswahl)
public String()
Erzeugt ein String-Objekt, das den Leerstring enthält
public String(String str)
Erzeugt ein String-Objekt, das eine Kopie des Inhalts
von str enthält (Copy-Konstruktor)
public String(char[] acs)
Erzeugt ein String-Objekt, das die Zeichenfolge aus
acs enthält.
Die Zeichen werden in das neu erzeugte Objekt kopiert.
public String(byte[] abs)
Erzeugt ein String-Objekt, das mit der Zeichenfolge, die
durch Decodierung der byte-Werte von abs entsteht,
initialisiert ist.
Die Decodierung erfolgt für den Default-Zeichensatz der
Implementierung
public String(StringBuffer buf) Erzeugt ein String-Objekt, das mit der in buf bzw
public String(StringBuilder bld) bld enthaltenen Zeichenfolge initialisiert ist.
Die Zeichen werden in das neu erzeugte Objekt kopiert.
◇ Hinweis :
Die explizite Erzeugung eines String-Objekts bei Initialisierung mit einer String-Konstanten ist
ineffizient :
String str = new String("Wer rastet, der rostet");
Dies führt zunächst zur impliziten Erzeugung eines String-Objektes das mit der String-Konstanten
"Wer rastet, der rostet" initialisiert ist.
Anschliessend wird zur expliziten Erzeugung eines weiteren String-Objekts der Copy-Konstruktor
aufgerufen, dem eine Referenz auf das zuerst erzeugte Objekt übergeben wird.
Eine Referenz auf das explizit erzeugte zweite Objekt wird dann der String-Variablen str zugewiesen.
Vorzuziehen ist daher die direkte "Initialisierung" einer String-Variablen mit einer String-Konstanten.
In diesem Fall wird nur ein String-Objekt – implizit – erzeugt
String str = "Wer rastet, der rostet";
Entsprechendes gilt für die Wertzuweisung an String-Variable.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/05/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse String in Java (2)
• Memberfunktionen Klasse String (Auswahl Teil 1)
public int length()
▻ Gibt die Länge eines String-Objekts (= die Anzahl der enthaltenen Unicode-Zeichen) als Funktionswert
zurück
public char charAt(int index)
▻ Liefert das Zeichen mit dem Index index als Funktionswert zurück.
▻ Der zulässige Indexbereich reicht von 0 (erstes Zeichen) bis length()-1 (letztes Zeichen).
▻ Erzeugung einer IndexOutOfBoundsException, wenn ein unzulässiger Index übergeben wird.
public boolean contains(CharSequence s)
// ab dem JDK 5.0 vorhanden
▻ Überprüfung, ob die Zeichenfolge s (z.B. Inhalt eines String-Objekts) im aktuellen Objekt enthalten ist
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false
public int indexOf(int ch)
▻ Rückgabe des Index des ersten Auftritts des – als int-Wert übergebenen – Zeichens ch als
Funktionswert.
▻ Falls das Zeichen ch nicht enthalten ist, wird der Wert –1 zurückgegeben.
▻ Beispiel : "hamburger".indexOf('r') liefert 5
public int indexOf(int ch, int from)
▻ Funktionalität wie int indexOf(int ch), allerdings beginnt die Suche am Index from
▻ Beispiel : "hamburger".indexOf('r', 6) liefert 8
public int indexOf(String str)
▻ Rückgabe des Index des ersten Auftritts des Teilstrings str.
▻ Der zurückgegebene Funktionswert ist der Index des ersten Zeichens des gefundenen Teilstrings.
▻ Falls der Teilstring str nicht enthalten ist, wird der Wert –1 zurückgegeben.
public int indexOf(String str, int from)
▻ Funktionalität wie int indexOf(String str), allerdings beginnt die Suche am Index from
public
public
public
public
int
int
int
int
lastIndexOf(int ch)
lastIndexOf(int ch, int from)
lastIndexOf(String str)
lastIndexOf(String str, int from)
▻ Ähnlich wie die Funktionen indexOf(...).
▻ Nur Ermittlung des Index des letzten Auftritts des Zeichens ch bzw des Teilsstrings str.
▻ Beispiel : "hamburger".lastIndexOf("rindfleisch") liefert -1
public boolean isEmpty()
// ab dem JDK 6.0 vorhanden
▻ Gibt true zurück, wenn das aktuelle String-Objekt leer (d.h. seine Länge==0) ist,
andernfalls false
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/05/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse String in Java (3)
• Memberfunktionen Klasse String (Auswahl Teil 2)
public boolean endsWith(String suffix)
▻ Überprüfung, ob das aktuelle Objekt mit dem String suffix endet.
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false
public boolean startsWith(String prefix)
▻ Überprüfung, ob das aktuelle Objekt mit dem String prefix beginnt.
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false
public boolean equals(Object obj)
▻ Überprüfung, ob das übergebene Objekt ein String-Objekt ist und gleiche Länge und gleichen Inhalt wie
das aktuelle Objekt hat.
▻ Falls ja, wird true als Funktionswert zurückgegeben, andernfalls false
public int compareTo(String str)
▻ Durchführung eines lexikographischen Vergleichs zwischen dem aktuellen String-Objekt und dem
String-Objekt str
▻ Der Vergleich wird mit den Codewerten der einzelnen Zeichen bzw der Stringlänge ausgeführt
▻ Funktionswert : - 0, wenn beide String-Objekte gleich sind
- <0, wenn das aktuelle Objekt "kleiner" als str ist
- >0, wenn das aktuelle Objekt "größer" als str ist
▻ Beispiel : "haben".compareTo("hat") liefert –18
public String substring(int beg, int end)
▻ Rückgabe des Teilstrings, der am Index beg beginnt und am Index end-1 endet, als neues StringObjekt (genauer : als Referenz auf ein neu erzeugtes String-Objekt mit dem entsprechenden Inhalt des
Teilstrings).
▻ Erzeugung einer IndexOutOfBoundsException, falls wenigstens einer der übergebenen Indizees
unzulässig ist oder beg>end ist.
▻ Beispiel : "hamburger".substring(4,8) liefert "urge"
public String toUpperCase()
▻ Rückgabe eines neuen String-Objekts, in dem alle Buchstaben in Großbuchstaben konvertiert sind
public String replace(char alt, char neu)
▻ Rückgabe eines neuen String-Objekts, das aus dem aktuellen Objekt durch Ersatz aller Auftritte des
Zeichens alt durch das Zeichen neu und der Übernahme alle übrigen Zeichen entsteht.
▻ Ist das Zeichen alt überhaupt nicht im aktuellen Objekt enthalten, wird kein neues Objekt erzeugt,
sondern das aktuelle Objekt zurückgegeben.
public String trim()
▻ Rückgabe einer neu erzeugten Kopie des aktuellen Objekts, bei der alle führenden und endenden Blanks
sowie ASCII-Steuerzeichen (Zeichencode <= '\u0020') entfernt sind
▻ Falls sowohl das erste als auch das letzte Zeichen des aktuellen String-Objekts einen Zeichencode
> '\u0020' besitzen, wird keine Kopie erzeugt, sondern das aktuelle Objekt zurückgegeben
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/05/5 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse String in Java (4)
• Explizite Umwandlung in eine String-Darstellung
◇ In der Klasse String existiert eine mehrfach überladene statische Memberfunktion zur Umwandlung von
Werten der einfachen Datentypen sowie von Objekten beliebiger Klassen in eine String-Darstellung :
Beispiel für die Umwandlung von double-Werten :
public static String valueOf(double d)
◇ Für jede Klasse ist in Java die folgende Memberfunktion definiert, mit der ein Objekt der jeweiligen Klasse
in ein String-Objekt (textuelle Repräsentation des Objekts !) umgewandelt wird :
public String toString()
• Demonstrationsbeispiel zur Klasse String
// StringDemo.java
public class StringDemo
{
public static void main(String[] args)
{ System.out.println("Heute ist : " + new java.util.Date());
String str = "Aller Anfang";
str = str + " ist";
str += " schwer";
System.out.println(str);
int len = str.length();
System.out.println("Laenge des Strings : " + len);
int idx = 6;
System.out.println(idx+1 + ". Zeichen : " + str.charAt(idx));
System.out.println("Index von \"ist\" : " + str.indexOf("ist"));
char ch = 'r';
System.out.println("letzter Index von " + ch + " : " + str.lastIndexOf(ch));
int ie = idx+6;
System.out.print("Teilstring (" + idx + ',' + ie + ") : ");
System.out.println(str.substring(idx, ie));
System.out.println(str.toUpperCase());
if (str.equals("Aller Anfang ist schwer"))
System.out.println("Strings sind gleich !");
else
System.out.println("Strings sind ungleich !");
int diff = "haben".compareTo("hat");
System.out.println("Vergleich von \"haben\" und \"hat\" liefert : "+diff);
}
}
Ausgabe des Programms
Heute ist : Thu Sep 04 10:38:41 CEST 2003
Aller Anfang ist schwer
Laenge des Strings : 23
7. Zeichen : A
Index von "ist" : 13
letzter Index von r : 22
Teilstring (6,12) : Anfang
ALLER ANFANG IST SCHWER
Strings sind gleich !
Vergleich von "haben" und "hat" liefert : -18
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/06/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Arrays in Java (1)
• Allgemeine Eigenschaften
◇ Arrays sind in Java Objekte.
Æ Array-Typen sind – namenlose – Klassen.
Von einer Array-Klasse können keine weiteren Klassen abgeleitet werden.
◇ Als Element-Typ ist jeder beliebige Typ (einfacher Datentyp oder Referenz-Typ) zulässig.
◇ Die Auswahl eines Array-Elements erfolgt wie in C :
Ein Array-Element wird über einen Index, der vom Typ int sein muß, ausgewählt.
Der Index des ersten Elements hat den Wert 0.
◇ Array-Variable sind Referenz-Variable. Sie verweisen auf Array-Objekte.
Æ Die Definition einer Array-Variablen erzeugt noch kein Array-Objekt, d.h. sie alloziert keinen
Speicherplatz für die Array-Elemente.
◇ Eine Array-Variable legt nur den Element-Typ , nicht aber die Länge eines Arrays (d.h. die Anzahl
seiner Elemente) fest. Sie kann daher auf Arrays beliebiger Länge zeigen.
◇ Die Länge eines Arrays wird dynamisch bei seiner Erzeugung (z.B. mittels eines new-Ausdrucks)
festgelegt. Anschließend ist sie nicht mehr veränderbar.
◇ Ein Array kann auch die Länge 0 besitzen. Ein derartiges Array ist ein echtes Array-Objekt.
Sinnvoll können derartige Arrays beispielsweise als Rückgabewert von Funktionen (genauer : Referenz
darauf) auftreten.
◇ Jedes Array besitzt die öffentliche Datenkomponente
public final int length;
Sie enthält die Länge des Arrays.
◇ Ein Array-Zugriff wird zur Laufzeit auf Zulässigkeit überprüft.
Der Versuch des Zugriffs zu einer nicht existierenden Array-Komponente (ungültiger Index) führt zum
Werfen der Exception ArrayIndexOutOfBoundsException.
• Vereinbarung von Array-Variablen
◇ Angabe eines Array-Typs :
Element-Typ
[]
◇ Diese Typangabe ist bei der Vereinbarung von Array-Variablen zu verwenden.
Beispiele : int[] ia;
// ia kann auf Array-Objekte zeigen, deren Elemente int-Werte sind
String[] names;
// names kann auf Array-Objekte zeigen, deren Elemente
// Referenzen auf String-Objekte sind
◇ Element-Typ eines Arrays kann wiederum ein Array sein Æ mehrdimensionale Arrays.
Die Vereinbarung mehrdimensionaler Arrays erfolgt analog zu eindimensionalen Arrays.
Beispiele : double[][] kmat; // kmat kann auf Array-Objekte zeigen, deren Elemente Referenzen
// auf Array-Objekte sind, die double-Werte enthalten
String[][] seite;
// seite kann auf Array-Objekte zeigen, deren Elemente
// Referenzen auf Array-Objekte sind, die Referenzen auf
// String-Objekte enthalten.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/06/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Arrays in Java (2)
• Definition von Array-Objekten mittels new-Ausdruck
◇ Andere Syntax als bei Nicht-Array-Objekten : kein Konstruktoraufruf !
Stattdessen ist der Elementtyp zusammem mit der Länge des Arrays anzugeben.
Die einzelnen Elemente werden mit ihrem Defaultwert initialisiert.
Beispiele : ia = new int[10];
// Speicherallokation für ein Array-Objekt, das 10 int// Elemente hat.
// Alle Elemente sind mit 0 initialisiert.
names = new String[3]; //
//
//
//
Speicherallokation für ein Array-Objekt, das
3 Elemente hat, die Referenzen auf String-Objekte
sind.
Alle Elemente sind mit null initialisiert.
◇ Die Definition eines Array-Objekts mittels eines new-Ausdrucks kann natürlich auch zusammen mit der
Vereinbarung einer Array-Variablen erfolgen.
Beispiel :
float[] pol = new float[6];
// pol zeigt auf ein alloziertes float-Array mit
// 6 Elementen (alle mit 0.0 initialisiert)
◇ Bei mehrdimensionalen Arrays kann im new-Ausdruck die Länge aller Dimensionen angegeben werden.
Es reicht aber aus, nur die Länge der ersten (am weitesten links stehenden) Dimension festzulegen.
Die Längen der übrigen Dimensionen müssen dann später festgelegt werden.
Beispiel :
kmat = new double[5][4]; //
//
//
//
//
//
Speicherallokation für ein Array-Objekt, das
5 Elemente hat,
die auf gleichzeitig allozierte double-Arrays, die alle
4 Elemente haben, zeigen.
Die Elemente der double-Arrays sind mit 0.0
initialisiert
Das obige Beispiel ist eine abkürzende Schreibweise für die folgende ausführlichere Formulierung :
kmat = new double[5][];
//
//
//
//
Speicherallokation für ein Array-Objekt, das
5 Elemente hat,
die auf double-Arrays zeigen können, aber alle mit
null initialisiert sind.
for (int i=0; i<kmat.length; i++)
kmat[i] = new double[4];
// Speicherallokation für 5 double-Arrays der
// Länge 4.
// Alle Elemente dieser Arrays sind mit 0.0
// initialisiert.
◇ Als Vorteil der Java-Implementierung von mehrdimensionalen Arrays ergibt sich, dass die Element-Arrays
(Arrays in zweiter (und gegebenenfalls höherer) Dimension eine unterschiedliche Länge besitzen können.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/06/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Arrays in Java (3)
• Definition von Array-Objekten mittels Array-Initialisierer (array initializer)
◇ Syntax :
{
Initialisierungs-Ausdruck
}
,
◇ Bei der Vereinbarung einer Array-Variablen kann ein Array-Initialisierer kann angegeben werden.
Dieser bewirkt die Allokation von Speicherplatz für ein Array-Objekt und initialisiert die einzelnen
Elemente mit den angegebenen Initialisierungs-Ausdrücken.
Die Länge des Arrays wird nicht angegeben .Sie ergibt sich aus der Anzahl der Initialisierungswerte
Beispiel :
String[] farben = { "rot", "gruen", "blau", "gelb", "weiss" };
// Vereinbarung der Array-Variablen farben. Diese zeigt auf ein gleichzeitig alloziertes
// Array-Objekt, dessen 5 Elemente mit den Referenzen auf die angegebenen Farb-Strings,
// für die ebenfalls Speicher alloziert wird, initialisiert werden.
◇ Bei mehrdimensionalen Arrays können Array-Initialisierer geschachtelt werden (InitialisierungsAusdrücke sind wiederum Array-Initialisierer)
◇ Array-Initialisierer können auch zusammen mit einem new-Ausdruck verwendet werden. Sie sind dem
new-Ausdruck nachzustellen, eine Array-Länge darf nicht angegeben werden. (sinnvoll zur Erzeugung
anonymer Arrays)
• Unterstützende Klassen der Standard-Bibliothek
◇ In der Java-Standardbibliothek sind zwei Klassen definiert, die statische Memberfunktionen zur
Unterstützung der Verwendung von Arrays zur Verfügung stellen
Beide Klassen können nicht instanziiert werden.
◇ Klasse java.lang.reflect.Array
Sie stellt statische Methoden zur dynamischen Erzeugung von und zum Zugriff zu Arrays zur Verfügung.
◇ Klasse java.util.Arrays
Sie stellt statische Methoden zur Bearbeitung von Arrays zur Verfügung.
Im wesentlichen handelt es sich um Methoden
- zum Suchen in Arrays
- zum Sortieren von Array-Komponenten
- zum Vergleich von Arrays
- zur Zuweisung an Array-Bereiche
◇ Die Klasse java.lang.System definiert zum Kopieren von Arraybereichen die statische Methode
public static void arraycopy(Object src, int sPos, Object dest, int dPos, int len)
Quell-Objekt (src) und Ziel-Objekt (dest) müssen Arrays sein
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/06/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Demonstrationsprogramm zu Arrays in Java
• Quellcode des Programms (Klasse ArrayDemo)
public class ArrayDemo
{
public static void main(String[] args)
{
int[] ia;
ia = new int[6];
System.out.println("int-Array : " + ia);
for (int i=0; i<ia.length; i++)
System.out.println(i + " : " + ia[i]);
String[] names = /* new String[]*/ { "Walter", "Franz", "Ilka" };
System.out.println("String-Array :" + names);
for (int i=0; i<names.length; i++)
System.out.println(i + " : " + names[i]);
double[][] kmat = new double[4][3];
System.out.println("2-dimensionales double-Array : " + kmat);
for (int i=0; i<kmat.length; i++)
System.out.println(i + " : " + kmat[i]);
System.out.println("erstes Zeilen-Array :");
for (int i=0; i<kmat[0].length; i++)
System.out.println(i + " : " + kmat[0][i]);
System.out.println("weiteres 2-dimensionales double-Array :");
double[][] gmat = new double[4][];
for (int i=0; i<gmat.length; i++)
gmat[i] = new double[i+1];
for (int i=0; i<gmat.length; i++)
{ System.out.print(i + " : ");
for (int j=0; j<gmat[i].length; j++)
System.out.print(gmat[i][j]+ " ");
System.out.println();
}
}
}
• Ausgabe des Programms
int-Array : [I@108786b
0 : 0
1 : 0
2 : 0
3 : 0
4 : 0
5 : 0
String-Array :[Ljava.lang.String;@119c082
0 : Walter
1 : Franz
2 : Ilka
2-dimensionales double-Array : [[D@1add2dd
0 : [D@eee36c
1 : [D@194df86
2 : [D@defa1a
3 : [D@f5da06
erstes Zeilen-Array :
0 : 0.0
1 : 0.0
2 : 0.0
weiteres 2-dimensionales double-Array :
0 : 0.0
1 : 0.0 0.0
2 : 0.0 0.0 0.0
3 : 0.0 0.0 0.0 0.0
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/06/5 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die vereinfachte for-Anweisung in Java
• Iteration über alle Elemente eines Arrays (und eines Containers)
◇ Zum sequentiellen Durchlaufen der Elemente eines Arrays wird üblicherweise die – auch aus C bekannte –
(Standard-) for-Anweisung eingesetzt.
Zum Zugriff zu den Elementen erfordert sie die explizite Definition und Verwendung einer "Laufvariablen".
◇ Beispiel :
double[] da;
// ...
for (int i=0; i<da.length; i++)
System.out.println(da[i]);
◇ Analoges gilt für das Durchlaufen eines Containers (in Java Collection genannt).
Anstelle der Laufvariablen tritt hier ein Iterator-Objekt.
• Vereinfachte for-Anweisung (Enhanced for Loop, For-Each-Schleife)
◇ Sie wurde mit dem JDK 5.0 zum sequentiellen Durchlaufen aller Elemente eines Arrays (bzw einer
Collection) eingeführt
◇ Bei ihr wird auf die explizite Definition einer Laufvariablen (bzw eines Iterator-Objekts) verzichtet.
◇ Syntax :
Array-Objekt
for
(
Element-Typ
Var-Name
:
)
Anweisung
Collection-Objekt
◇ Beispiel :
double[] da;
// ...
for(double el : da)
System.out.println(el);
◇ Wirkung : "Für jedes Element el in da "
Der Element-Typ-Variablen el wird in jedem Schleifendurchlauf das jeweils nächste Element des Arrays
da zugewiesen.
◇ Die Gültigkeit der Element-Typ-Variablen el ist auf den Schleifenrumpf begrenzt.
◇ Der vom Compiler erzeugte Code benötigt und verwaltet auch hier für den Elementzugriff eine Laufvariable
(bzw ein Iterator-Objekt). Diese wird vom Compiler implizit erzeugt.
• Anwendbarkeit der vereinfachten for-Anweisung
◇ Sie ist kein allgemeiner Ersatz für die (Standard-) for-Anweisung
◇ Sie kann nur zum sequentiellen Durchlaufen aller Elemente eines Arrays (bzw einer Collection) in Vorwärtsrichtung eingesetzt werden (vom ersten zum letzten Element, ohne Überspringen einzelner Elemente)
◇ Sie kann nicht eingesetzt werden, wenn
▻ ein Element aus dem Array (der Collection) entfernt oder modifiziert werden soll
▻ innerhalb einer Schleife mehrere Arrays (Collections) parallel bearbeitet werden sollen
◇ Ihr Einsatz in geschachtelten Schleifen ist jedoch möglich
Beispiel : Durchlaufen eines zweidimensionalen Arrays
double[][] gmat;
// ...
for (double[] row : gmat)
for (double el : row)
System.out.println(el);
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/06/6 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Demonstrationsprogramm zur vereinfachten for-Anweisung in Java
• Quellcode des Programms (Klasse ForEachDemo)
// ForEachDemo.java
public class ForEachDemo
{
public static void main(String[] args)
{
double[] da;
da = new double[6];
for (int i=0; i<da.length; i++)
da[i] = i;
System.out.println("\ndouble-Array (eindimensional) : ");
for(double el : da)
System.out.println(el);
String[] names = { "Walter", "Franz", "Ilka" };
System.out.println("\nString-Array : ");
for (String str : names)
System.out.println(str);
System.out.println("\ndouble-Array (zweidimensional) :");
double[][] gmat = new double[4][];
for (int i=0; i<gmat.length; i++)
gmat[i] = new double[i+1];
for (double[] row : gmat)
{ for (double el : row)
System.out.print(el + "
");
System.out.println();
}
}
}
• Ausgabe des Programms
double-Array (eindimensional) :
0.0
1.0
2.0
3.0
4.0
5.0
String-Array :
Walter
Franz
Ilka
double-Array (zweidimensional) :
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/07/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse Object in Java (1)
• "Mutter" aller Klassen
◇ In Java existiert nur eine Klassenhierarchie.
Wurzel dieser Hierarchie ist die Klasse Object.
Æ Alle Klassen haben – direkt oder indirekt – diese Klasse als Basisklasse.
Auch Klassen, die scheinbar nicht abgeleitet sind, d.h. die ohne Angabe einer Basisklasse definiert sind,
sind tatsächlich implizit von Object abgeleitet.
◇ Da eine Variable eines Klassen-Typs auch auf Objekte abgeleiteter Klassen zeigen kann (Polymorphie !),
kann eine Variable vom Typ Object Objekte eines beliebigen Klassen-Typs (einschliesslich ArrayTyps) referieren.
◇ Die Klasse Object ist im Package java.lang enthalten.
• Memberfunktionen der Klasse Object, Allgemeines
◇ Die Klasse Object definiert insgesamt elf Memberfunktionen, die wegen der Vererbung in allen Klassen
zur Verfügung stehen.
◇ Sechs dieser Memberfunktionen sind nicht überschreibbar.
Die übrigen lassen sich in abgeleiteten Klassen überschreiben. In Abhängigkeit von der jeweiligen Klasse
kann für eine sinnvolle Funktionalität ein Überschreiben notwendig sein.
◇ Die Memberfunktionen von Object zerfallen in zwei Kategorien :
- Allgemeine Utility-Funktionen (6)
- Methoden zur Thread-Unterstützung (5)
Hier werden nur 3 der 6 Utilility-Funktionen vorgestellt.
Æ siehe nächste Seite
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/07/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse Object in Java (2)
• Memberfunktionen der Klasse Object, Auswahl
public boolean equals(Object obj)
▻ Die Funktion vergleicht das aktuelle Objekt mit dem durch obj referierten Objekt.
Sie liefert true als Funktionswert, wenn Gleichheit vorliegt, andernfalls false.
▻ Grundsätzlich ist die Funktion für eine Überprüfung auf Wert-Gleichheit der Objekte vorgesehen.
▻ Die Default-Implementierung in der Klasse Object geht davon aus, dass ein Objekt nur zu sich
selbst gleich sein kann, d.h. sie setzt Wert-Gleichheit mit Referenz-Gleichheit (Identität) gleich.
Sie liefert genau dann true, wenn obj das aktuelle Objekt referiert (obj==this).
▻ Für die Implementierung einer echten Wert-Gleichheit, die sich auf den Inhalt (Zustand) der referierten
Objekte bezieht, muss die Methode in abgeleiteten Klassen geeignet überschrieben werden.
Dies ist für zahlreiche Klassen der Standard-Bibliothek, u.a. auch für die Klasse String, erfolgt.
public String toString()
▻ Diese Funktion ermöglicht es, dass jedes Objekt jeder beliebigen Klasse in einen String "umgewandelt" werden
kann (z.B. bei der Konkatenation eines Objekts mit einem String)
Æ Sie liefert eine String-Repräsentation des aktuellen Objekts.
▻ Die Default-Implementierung in der Klasse Object erzeugt ein String-Objekt, dessen Inhalt aus dem
Klassennamen des aktuellen Objekts, dem Zeichen '@' und der sedezimalen Darstellung eines dem Objekt
zugeordneten Codes (Hash-Code) zusammengesetzt ist. Typischerweise ist dieser Code gleich der
Speicheradresse des Objekts.
▻ Soll eine andere das Objekt kennzeichnende String-Darstellung erzeugt werden, muss die Methode
toString() geeignet überschrieben werden
▻ Die Methode toString() wird immer dann implizit aufgerufen, wenn eine Objekt-Referenz in einem
String-Konkatenations-Ausdruck auftritt.
protected Object clone() throws CloneNotSupportedException
▻ Die Funktion liefert ein neues Objekt, dass ein Clone (eine Kopie) des aktuellen Objekts ist.
▻ Die tatsächliche Klasse des aktuellen Objekts muß das Interface Cloneable implementieren.
▻ Die Default-Implementierung in der Klasse Object prüft, ob für das aktuelle Objekt das Interface
Cloneable implementiert ist.
Ist das nicht der Fall, wird die Exception CloneNotSupportedException geworfen.
Falls es implementiert ist, wird ein neues Objekt der Klasse erzeugt, dessen Datenkomponenten mit den Werten
der entsprechenden Datenkomponenten des aktuellen Objekts initialisiert werden. ("flache" Kopie, shallow
copy)
▻ Soll das neue Objekt als "tiefe" Kopie (deep copy) erzeugt werden, muss clone() geeignet überschrieben
werden.
▻ Die Klasse Object selbst implementiert das Interface Cloneable nicht.
Das bedeutet, dass der Aufruf von clone() für ein Objekt der Klasse Object zum Werfen der Exception
CloneNotSupportedException führt.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/07/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Die Klasse Object in Java (3)
• Demonstrationsprogramm zu Memberfunktionen der Klasse Object
// ObjDemo.java
public class ObjDemo implements Cloneable
{
private String name;
public ObjDemo(String str)
{
name=str;
}
public String toString()
{
return super.toString()+" ("+name+")";
}
public static void main(String[] args)
{
ObjDemo o1 = new ObjDemo("Test1");
System.out.println("o1.toString() : " + o1.toString());
Object o2 = new ObjDemo("Test2");
System.out.println("o2
: " + o2);
System.out.println("o2.equals(o1) : " + o2.equals(o1));
o2=o1;
System.out.println("\nnach o2=o1 :");
System.out.println("o2
: " + o2);
System.out.println("o2.equals(o1) : " + o2.equals(o1));
o2=o1.clone();
System.out.println("\nnach o2=o1.clone() :");
System.out.println("o2
: " + o2);
System.out.println("o2.equals(o1) : " + o2.equals(o1));
}
}
Ausgabe des Programms
o1.toString() : ObjDemo@3e25a5 (Test1)
o2
: ObjDemo@19821f (Test2)
o2.equals(o1) : false
nach o2=o1 :
o2
: ObjDemo@3e25a5 (Test1)
o2.equals(o1) : true
nach o2=o1.clone() :
o2
: ObjDemo@addbf1 (Test1)
o2.equals(o1) : false
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/08/1 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Beispiel : Klasse Ratio (1)
• Klasse zur Darstellung rationaler Zahlen (hier nur Implementierung einer Teilfunktionalität)
• Definition der Klasse Ratio :
// Ratio.java
public class Ratio
{
final private int iZaehl;
final private int iNenn;
public Ratio(int iZ, int iN)
{ if(iN>0)
{ iZaehl = iZ;
iNenn = iN;
}
else if (iN<0)
{ iZaehl = -iZ;
iNenn = -iN;
}
else
{ iNenn = 1;
iZaehl = 0;
}
}
// Konstruktor 1
public Ratio(int iZ)
{ this(iZ,1);
}
// Konstruktor 2 - ganze Zahl
public Ratio()
{ this(0);
}
// Konstruktor 3 - ohne Parameter
// Vorzeichen nur im Zaehler
// Throw exception !! spaeter
public Ratio add(Ratio sP)
{ int iZ = sP.iZaehl*iNenn + sP.iNenn*iZaehl;
int iN = sP.iNenn*iNenn;
return new Ratio(iZ, iN);
}
private int iGgTeil()
{ int iP,iQ,iS;
int iGgt;
int locZ;
if(iZaehl >= 0)
locZ = iZaehl;
else
locZ = -iZaehl;
if(locZ > iNenn)
{ iP = locZ; iQ = iNenn;
}
else
{ iP = iNenn; iQ = locZ;
}
do
{ iS = iP%iQ;
iP = iQ;
iQ = iS;
} while(iS>0);
iGgt = iP;
return iGgt;
}
// groesster gemeinsamer Teiler
// Zaehler und Nenner positiv - Vorzeichen !
// groessere der beiden Zahlen ermitteln
// Fortgesetzte Division bis Rest gleich 0
// ergibt ggT
// int iKgViel(Ratio rA)
// kleinstes gem Vielfaches - nicht benoetigt
// { return (rA.iZaehl * rA.iNenn / iGgTeil(rA));
// }
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 12/08/2 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Beispiel : Klasse Ratio (2)
• Definition der Klasse Ratio, Forts.:
Ratio kuerze()
{ int iZw,iZ,iN;
iZw = iGgTeil();
iZ = iZaehl / iZw;
iN = iNenn / iZw;
return new Ratio(iZ,iN);
}
public String toString()
{ return new String(iZaehl + "/" + iNenn);
}
public String toMixedString()
{ int iGanz = iZaehl/iNenn;
int iBruch = Math.abs(iZaehl)%iNenn;
//Achtung Vorzeichen
Ratio lRat = new Ratio(iBruch,iNenn);
return new String (iGanz + " " + lRat);
}
}
● Definition der Demonstrations- und Test-Klasse RatioDemo :
// RatioDemo.java
// Test der Klasse Ratio
public class RatioDemo
{
public static void main(String[] args)
{
Ratio rFirst = new Ratio(150,60);
Ratio rSecnd = new Ratio(28,84);
Ratio rThird;
System.out.println("First: "+rFirst);
System.out.println("Secnd: "+rSecnd);
rFirst = rFirst.kuerze();
rSecnd = rSecnd.kuerze();
System.out.println("First: "+rFirst);
System.out.println("Secnd: "+rSecnd);
rThird = rFirst.add(rSecnd);
System.out.print(rFirst+" + "+rSecnd+" = "+rThird);
System.out.println(" = " + rThird.toMixedString());
}
}
Programmausgabe :
First: 150/60
Secnd: 28/84
First: 5/2
Secnd: 1/3
5/2 + 1/3 = 17/6 = 2 5/6
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/00/0 – TH – 01
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Programmieren (4. Sem.)
Kapitelüberblick
12. Elementare Programmfunktionalitäten
12.1. Zugriff zu Programmparametern
12.2. Standard-Ein-und-Ausgabe (Konsolen-E/A)
12.3. Exceptions
12.4. Dateizugriff
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/01/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Zugriff zu Programmparametern in Java
• Programmparameter (Kommandozeilenparameter)
◇ Einem Programm können i.a. beim Aufruf Parameter übergeben werden. Æ Programmparameter
◇ Diese werden beim Aufruf aus der Kommandozeile durch Blanks getrennt an den eigentlichen Programmaufruf angehängt. Æ Kommandozeilenparameter
Bei Java-Programmen werden sie nach dem Namen der Start-Klasse angegeben.
◇ Beispiel :
java Echo Sie tanzte nur einen Sommer
Kommandozeilenparameter sind :
Sie tanzte nur einen Sommer
• Zugriff im Programm
◇ Die Programmparameter (ohne Namen der Startklasse !) werden in einem String-Array zusammengefasst.
Eine Referenz auf dieses Array wird der main()-Methode der Startklasse als Parameter übergeben.
◇ Die main()-Methode der Startklasse muß daher mit einem Parameter (Argument) vom Typ String[]
definiert werden :
public static void main(String[] args)
{
// ...
}
◇ Innerhalb der main()-Methode stehen damit die Programmparameter als Komponenten des StringArrays args zur Verfügung.
◇ Die Anzahl der Programmparameter (= Länge des String-Arrays) ist ermittelbar mittels
args.length.
• Beispiel :
// Echo.java
class Echo
{
public static void main(String[] args)
{
for (int i=0; i<args.length; i++)
System.out.println("Parameter "+ i + " : " + args[i]);
}
}
Beispiel eines Programm-Aufrufs :
E:\java\fhm\ee\vorl>java Echo Sie tanzte nur einen Sommer
Parameter
Parameter
Parameter
Parameter
Parameter
0
1
2
3
4
:
:
:
:
:
Sie
tanzte
nur
einen
Sommer
E:\java\fhm\ee\vorl>
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (1)
• Grundsätzliches zum I/O-Model von Java
◇ Eine Programm-Ein- und Ausgabe findet üblicherweise über Dateien und/oder Geräte statt.
◇ Java betrachtet sowohl Geräte als auch Dateien grundsätzlich als sequentielle Folge von Bytes (Byte-Stream).
Da Java Zeichen und Strings im Unicode darstellt, bietet die Sprache auch die Möglichkeit Textdateien/
Text-Geräte als sequentielle Folge von Unicode-Zeichen (Unicode-Stream) zu interpretieren.
◇ Programmintern wird eine Datei bzw ein Gerät durch ein Objekt einer Stream-Klasse repräsentiert.
◇ Es gibt zahlreiche verschiedene Stream-Klassen, die jeweils unterschiedliche Eigenschaften modellieren.
Alle Stream-Klassen sind im Package java.io enthalten.
• Standard-Ein- und Ausgabe-Objekte
◇ In den Programmen der meisten Programmiersprachen (z.B. auch in C-Programmen) werden automatisch
Zugriffsmöglichkeiten zu den Standard-Ein- und Ausgabegeräten (üblicherweise Tastatur und Bildschirm
des Konsolengeräts) bereitgestellt.. Diese können sofort nach Programmstart ohne weitere Maßnahmen
eingesetzt werden.
◇ Auch in Java ist dies der Fall :
In jedem Java-Programm werden automatisch Stream-Objekte angelegt, die einen Zugriff zur StandardEingabe, Standard-Ausgabe und Standard-Fehlerausgabe ermöglichen.
Die entsprechenden Streams sind implizit geöffnet.
Aus historischen Gründen handelt es sich bei diesen Stream-Objekten um Byte-Stream-Objekte.
◇ Referenzen auf diese Stream-Objekte stehen als öffentliche statische Datenkomponenten der – nicht
instanzierbaren – Klasse System (im Package java.lang) zur Verfügung .
Es handelt sich um Referenz-Konstante.
Sie müssen zusammen mit dem Klassennamen System verwendet werden.
▻ public static final InputStream in
Æ Standard-Eingabe-Objekt
Æ Referierung mittels System.in
▻ public static final PrintStream out
Æ Standard-Ausgabe-Objekt
Æ Referierung mittels System.out
▻ public static final PrintStream err
Æ Standard-Fehlerausgabe-Objekt
Æ Referierung mittels System.err
◇ Ab den JDK 6.0 existiert eine – allerdings nicht immer verfügbare – alternative Möglichkeit zum Zugriff
zur Standard-Ein- und Ausgabe zur Verfügung :
Wenn ein Java-Programm aus der Kommandozeile (ohne Ein-/Ausgabe-Umleitung) gestartet wird, wird
implizit durch die JVM ein Objekt der Klasse Console erzeugt. (nicht jedoch beim Start aus einer IDE).
Eine Referenz auf dieses Objekt kann mit einer statischen Methode der Klasse System ermittelt werden :
public static Console console()
Die Klasse Console (Package java.io) stellt u.a. Methoden zum Schreiben in das sowie Lesen aus
dem Konsolengerät (== Standard-Eingabe + Standard-Ausgabe) zur Verfügung.
Genaueres s. API-Dokumentation.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (2)
• Schreiben in die Standard-Ausgabe und Standard-Fehlerausgabe
◇ Die durch system.out (Standard-Ausgabe) und system.err (Standard-Fehlerausgabe) referierten
Stream-Objekte sind Instanzen der Klasse PrintStream.
Diese Klasse stellt die folgenden Methoden zum Schreiben zur Verfügung :
public void print(...)
public void println(...)
▻ Beide Methoden sind mehrfach überladen und haben jeweils einen Parameter, der dem jeweiligen Typ
des auszugebenden Werts bzw Objekts entspricht.
Sie ermöglichen die – nicht explizit formatierbare – Ausgabe von
-
von boolean-, char-, double-, float-, int- und long-Werten
-
von char-Arrays
-
von Strings (Objekte der Klasse String)
-
sowie der String-Repräsentation von Objekten beliebiger Klassen
(impliziter Aufruf der Objekt-Methode toString())
▻ Die Anwendung der String-Konkatenation in Verbindung mit der automatischen Umwandlung von
beliebigen Datenwerten und Objekten in eine String-Repräsentation bei ihrem Auftritt in KonkatenationsAusdrücken (Methode toString()) erlaubt die Ausgabe mehrerer Werte/Objekte mit einem
Methodenaufruf.
▻ Die Methode println() ergänzt die Ausgabe um ein Zeilenendezeichen.
Sie lässt sich auch ohne Parameter aufrufen. In diesem Fall bewirkt sie lediglich einen Übergang in eine
neue Zeile.
public PrintStream printf(String form, Object... args) (ab dem JDK 5.0)
▻ Diese Methode ermöglicht eine – C-ähnliche – formatierte Ausgabe (s. gesonderte Beschreibung)
▻ Ihr Rückgabewert ist eine Referenz auf das aktuelle PrintStream-Objekt, für das sie aufgerufen wird.
◇ Beispiel zur Anwendung von print(…) und println(…´) :
class StdOutDemo1
{
public static void main(String[] args)
{ boolean b = true;
char
c = 'Z';
int
i = 399127;
long
l = 124L;
float
f = 2.25E-2f;
double d = 0.0/0.0;
String s = "Hallo !";
StdOutDemo1 sod = new StdOutDemo1();
System.out.print(b);
System.out.println();
System.out.println("Zeichen : " +c);
System.out.println(i);
System.out.println(i + " " + l);
System.out.println(f);
System.out.println(d);
System.out.println(s);
System.out.println(sod);
}
}
Ausgabe :
true
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (3)
• Formatierte Ausgabe (ab dem JDK 5.0)
◇ Mittels der PrintStream-Methode
public PrintStream printf(String form, Object... args);
◇ Die Methode ermöglicht eine C-ähnliche formatierte Ausgabe
◇ Der erste Parameter form ist der Format-String. Er enthält – analog zum Format-String der C-Funktion
printf() – die einzelnen Formatangaben (format specifier) für die auszugebenden Werte/Objekte.
Durch die Formatangaben wird auch der Typ bzw die Darstellungsart der Ausgabe-Werte festgelegt
Zusätzlich kann der Format-String weiteren Text enthalten, der direkt ausgegeben wird.
◇ Die zweite Parameter-Angabe Object... args bedeutet, dass eine beliebige Anzahl (auch keine)
weiterer Parameter beliebigen Referenz-Typs folgen darf. Diese Parameter (Argumente) legen die Werte
fest, die entsprechend des jeweils spezifizierten Formats auszugeben sind.
Für jede Formatangabe muss ein passendes Argument übergeben werden. Die Typen dieser Argumente
müssen zu den entsprechenden Angaben im Format-String passen. Überflüssige Argumente werden ignoriert
Als Parameter können auch Werte einfacher Datentypen auftreten, da sie mittels Autoboxing automatisch in
Objekte der zugehörigen Wrapper-Klassen umgewandelt werden.
◇ Syntax der Formatangaben (vereinfacht) :
% [flags][width][.precision]conversion
▻ conversion (Konvertierungszeichen)
legt die Formatierungsart und/oder den Typ der Ausgabe fest und schließt eine Formatangabe ab
Die wichtigsten Konvertierungszeichen sind :
b
d
o
x
c
e
f
g
oder B
oder X
oder C
oder E
oder G
s oder S
n
logischer Wert
ganzzahliger Wert in Dezimaldarstellung
ganzzahliger Wert in Oktaldarstellung
ganzzahliger Wert in Sedezimaldarstellung
Unicode-Zeichen
Gleitpunkt-Wert in Exponentialdarstellung
Gleitpunkt-Wert in Dezimalbruchdarstellung
Gleitpunkt-Wert in Dezimalbruchdarstellung oder Exponentialdarstellung
(abhängig von Wert und Genauigkeit)
String (der String, der durch die jeweilige Methode toString() erzeugt wird)
Zeilenendezeichen
Bei einem Großbuchstaben als Konvertierungszeichen : Ausgabe aller Buchstaben als Großbuchstaben
▻ flags (Steuerflags)
modifizieren das Ausgabeformat, sie können gegebenenfalls miteinander kombiniert werden
Die wichtigsten Steuerflags sind :
+
0
' ' (Blank)
linksbündige Ausgabe
auch positive Werte werden mit Vorzeichen ausgegeben (nur für Zahlen anwendbar)
Ausgabe führender Nullen (nur für Zahlen anwendbar)
Ausgabe positiver Werte mit führendem Blank (nur für Zahlen anwendbar)
▻ width (Ausgabefeldbreite)
legt die minimale Ausgabefeldbreite fest
▻ precision (Genauigkeit)
legt i.a. die maximale Ausgabefeldbreite fest, bei Gleitpunktzahlen jedoch die Anzahl der Nachpunktstellen
(Ausnahme : beim Konvertierungszeichen g bzw G wird die Gesamtzahl der Ziffern festgelegt),
bei Strings : Anzahl der auszugebenden Zeichen des Strings
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (4)
• Formatierte Ausgabe (ab dem JDK 5.0), Forts.
◇ Nichtzulässige Zeichen in einer Formatangabe sowie fehlende oder zu einer Formatangabe nichtkompatible Argumente führen zum Werfen einer IllegalFormatException.
• Demonstrationsprogramm zur formatierten Ausgabe :
// FormOutpDemo.java
// Demonstrationsprogramm zur formatierten Ausgabe
public class FormOutpDemo
{
void show()
{ int anz = 10;
double summe = 99.98765;
float anteil = 0.00005432f;
String type = "Airbus A-380";
System.out.println("0123456789012345678901234567890123456789");
System.out.printf("Anzahl : %5d Summe : %8.3e\n", anz, summe);
System.out.printf("Anzahl : %-5d Summe : %8.3f\n", anz, summe);
System.out.printf("Anzahl : %0+5d Summe : %08.3f\n", anz, summe);
System.out.printf("Anteil : % .4g\n", anteil);
System.out.printf("Anteil : %.4E\n", anteil);
System.out.printf("Anteil : %.4f\n", anteil);
System.out.printf("Typ : %s\n", type);
System.out.printf("Typ : %15s\n", type);
System.out.printf("Typ : %5s\n", type);
System.out.printf("Typ : %5.6S\n", type);
System.out.printf("Typ : %8.6s\n", type);
System.out.printf("%B\n", true);
}
public static void main(String[] args)
{ FormOutpDemo demo = new FormOutpDemo();
demo.show();
}
}
Ausgabe des Programms :
0123456789012345678901234567890123456789
Anzahl :
10 Summe : 9.999e+01
Anzahl : 10
Summe :
99,988
Anzahl : +0010 Summe : 0099,988
Anteil : 5.432e-05
Anteil : 5.4320E-05
Anteil : 0,0001
Typ : Airbus A-380
Typ :
Airbus A-380
Typ : Airbus A-380
Typ : AIRBUS
Typ :
Airbus
TRUE
• Ergänzende Anmerkung zur formatierten Ausgabe
◇ Zur Erzeugung von formatierten Ausgaben kann auch die Klasse Formatter eingesetzt werden
(s. API-Dokumentation)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/5 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (5)
• Lesen aus der Standard-Eingabe
◇ Das durch system.in referierte Stream-Objekt für die Standard-Eingabe steht als Instanz der Klasse
InputStream zur Verfügung.
Diese Klasse besitzt zum Einlesen lediglich die mehrfach überladene Methode read(), mit der nur
einzelne Bytes oder eine Gruppe von Bytes (Byte-Array) eingelesen werden können.
public int read() throws IOEception
▻ Einlesen eines Bytes
▻ Rückgabewert : gelesenes Byte zu int ergänzt, bzw -1 falls Eingabeende erreicht ist
public int read(byte[] b) throws IOEception
▻ Einlesen einer Bytefolge in das als Parameter übergebene Array b
Es werden maximal b.length Bytes gelesen
▻ Rückgabewert : Anzahl der gelesenen Bytes, bzw -1 falls Eingabeende erreicht ist
◇ Sofern die über die Standard-Eingabe (Tastatur) eingegebenen Zeichen jeweils nur aus einem Byte bestehen
– was bei dem bei uns üblichen Zeichensatz i.a. der Fall ist – können mit diesen Methoden einzelne Zeichen
eingelesen werden.
◇ Üblicherweise soll von der Standard-Eingabe aber aus mehreren Zeichen bestehender Text eingelesen werden,
der vom Programm entweder als Wert eines einfachen Datentyps oder direkt als String interpretiert und
verwendet werden soll.
D.h. also, es müssen Zeichenfolgen (Datentyp char) und nicht Bytefolgen (Datentyp Byte) eingelesen
und in interne Wertdarstellungen umgewandelt werden.
◇ Um dies effektiv zu realisieren, muß das Objekt System.in mit Objekten anderer Klassen zusammenarbeiten. Hierfür existieren mehrere Möglichkeiten.
Die einfachste – allerdings erst ab dem JDK 5.0 vorhandene – Möglichkeit besteht im Einsatz eines Objekts
der Klasse Scanner (Package java.util).
• Allgemeines zur Klasse Scanner
◇ Objekte der Klasse Scanner dienen zum Zergliedern und Interpretieren von Zeichenfolgen.
◇ Die von Scanner-Objekten bearbeitbaren Zeichenfolgen können aus unterschiedlichen Eingabe-Quellen
– auch aus Bytestreams – stammen. (Dateien, sonstige Eingabe-Streams wie z.B. die Standard-Eingabe,
Strings). Das jeweilige Quell-Objekt muss beim Erzeugen eines Scanner-Objekts festgelegt werden
(Æ Konstruktor-Parameter).
◇ Scanner-Objekte zerlegen ihre Eingabe-Zeichenfolge in Teil-Abschnitte (token). Die Zeichen(-muster),
die alsTrennzeichen zwischen den Abschnitten interpretiert werden (delimiter pattern), lassen sich
konfigurieren. Defaultmässig werden Whitespace-Character verwendet.
◇ Die einzelnen Teil-Abschnitte stehen als Strings zur Verfügung und können als Werte eines einfachen
Datentyps interpretiert und in die dem jeweiligen Typ entsprechende interne Darstellung umgewandelt
werden.
Damit lassen sich Scanner-Objekte sehr elegant zum Einlesen von Werten der einfachen Datentypen aus
der Standard-Eingabe einsetzen, insbesondere auch dann, wenn in einer Eingabezeile mehrere einzulesende
Werte enthalten sind.
◇ Scanner-Objekte ermöglichen auch das zeilenweise Lesen.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/6 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (6)
• Konstruktoren der Klasse Scanner (Auswahl)
public Scanner(InputStream source) Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle das
durch source spezifizierte InputStream-Objekt ist
public Scanner(File source)
Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle die
durch source spezifizierte Datei ist
public Scanner(String source)
Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle der
durch source spezifizierte String ist.
• Erzeugung eines Scanner-Objekts für die Standard-Eingabe
Scanner stdinscan = new Scanner(System.in);
• Memberfunktionen der Klasse Scanner (Auswahl)
public String nextLine()
Rückgabe des Rests der aktuellen Eingabe-Zeile
Wenn die Bearbeitungsposition sich unmittelbar vor dem Anfang der nächsten
Zeile befindet, wird die gesamte nächste Zeile zurückgegeben
public boolean hasNextLine()
Überprüfung, ob eine weitere Eingabe-Zeile vorhanden ist
Rückgabe von true wenn ja, sonst von false
public String next()
Rückgabe des nächsten Teil-Abschnitts (token) der Eingabe-Zeichenfolge
public boolean hasNext()
Überprüfung ob ein weiterer Teil-Abschnitt vorhanden ist
Rückgabe von true wenn ja, sonst von false
public boolean hasNextByte()
public boolean hasNextShort()
public boolean hasNextInt()
public boolean hasNextLong()
Überprüfung, ob der nächste Teilabschnitt sich als Wert des jeweiligen
Typs interpretieren lässt. (boolean-Werten können mit Groß- und/oder
Kleinbuchstaben dargestellt werden)
Rückgabe von true wenn ja, sonst von false
Die Methoden geben auch false zurück, wenn kein weiterer Teil-Abschnitt
mehr vorhanden ist (d.h. das Eingabe-Ende erreicht ist)
public boolean hasNextFloat()
public boolean hasNextDouble()
Achtung : Der Dezimal-Punkt bei Float- und Double-Werten
muß bei der Eingabe durch ein Dezimal-Komma ersetzt werden
public boolean hasNextBoolean()
public byte nextByte()
public short nextShort()
public int nextInt()
public long nextLong()
public float nextFloat()
public double nextDouble()
public boolean nextBoolean()
Interpretation des nächsten Teil-Abschnitts der Eingabe-Zeichenfolge als
Wert des jeweiligen Typs und Rückgabe der internen Darstellung dieses
Wertes
Jede der Funktionen wirft eine Exception vom Typ
InputMismatchException,
wenn der Teil-Abschnitt sich nicht als Wert des jeweiligen Typs interpretieren
lässt (boolean-Werte können mit Groß- und/oder Kleinbuchstaben dargestellt werden)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/02/7 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Standard-Ein- und Ausgabe in Java (7)
• Demonstrationsbeispiele zur Klasse Scanner
◇ Programm EchoLinesScanDemo
// EchoLinesScanDemo.java
// Echo der von der Standard-Eingabe eingelesenen Zeilen in die Standard-Ausgabe
// Verwendung der Klase Scanner
import java.util.*;
public class EchoLinesScanDemo
{
public static void main(String[] args)
{
Scanner stdinscan = new Scanner(System.in);
while (stdinscan.hasNextLine())
System.out.println(stdinscan.nextLine());
}
}
◇ Programm StdInpScanDemo
// StdInpScanDemo.java
// Demonstrationsprogramm zum Einlesen von der Standard-Eingabe
// unter Verwendung der Klasse Scanner
import java.util.*;
public class StdInpScanDemo
{
public static void main(String[] args)
{
int a, b;
Scanner stdinscan = new Scanner(System.in);
System.out.print("Zwei Integer-Werte a und b ? ");
a = stdinscan.nextInt();
b = stdinscan.nextInt();
System.out.println("a+b = " + (a + b));
System.out.print("Boolean-Wert ? ");
boolean bw = stdinscan.nextBoolean();
System.out.println("Eingabe war : " + bw);
System.out.print("Double-Wert ? ");
if (stdinscan.hasNextDouble())
{ double d = stdinscan.nextDouble();
System.out.println("Double-Wert : " + d);
}
else
System.out.printf("keine oder falsche Eingabe");
}
◇ Beispiel für die Ein- und Ausgabe des Programms StdInpScanDemo
Zwei Integer-Werte a und b ? 12 25
a+b = 37
Boolean-Wert ? FalsE
Eingabe war : false
Double-Wert ? 4,5
Double-Wert : 4.5
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/03/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Exceptions in Java (1)
• Prinzip des Exception Handlings
◇ Java stellt – wie auch z.B. C++ – einen speziellen Mechanismus zur Behandlung von Ausnahmesituationen
(Fehlerfällen, Exceptions), die während der Programmausführung auftreten können, zur Verfügung
⇒ Exception Handling
◇ Ausnahmesituationen in diesem Sinne sind Fehler oder sonstige unerwünschte Sonderfälle (z.B. Dateizugriffsfehler, Verletzung von Array-Grenzen, Datenformatfehler usw), die im normalen Programmablauf
nicht auftreten sollten, aber auftreten können.
Exception Handling ist kein Mechanismus zur Behandlung von externen oder internen Interrupts.
◇ Exception Handling trennt den Code, der Fehler verursachen kann, von dem Code, der einen aufgetretenen
Fehler behandelt.
Dadurch kann der eigentliche den normalen Programmablauf steuernde (produktive) Code frei gehalten
werden von einer ständigen Überprüfung auf den Auftritt von Fehlern und Sonderfällen sowie der Reaktion
auf diese. Dies trägt erheblich zur Klarheit und Übersichtlichkeit des Codes bei.
◇ Code (z.B. eine Methode einer Bibliotheksklasse), der eine Ausnahmesituation entdeckt, wirft eine
Exception, die dann von einem anderen Code-Teil, dem Exception-Handler gefangen wird.
Im Exception-Handler findet die Reaktion auf die (Bearbeitung der) Ausnahmesituation statt. Diese kann
der Fehlerart sowie der jeweiligen spezifischen Programmsituation angepasst werden. Z.B. kann eine
Fehlermeldung ausgegeben werden und anschliessend das Programm fortgesetzt oder beendet werden. Oder
es kann versucht werden, die Fehlerursache zu beseitigen und das Programm dann fortzusetzen.
◇ Exceptions werden als Objekte behandelt. Sie enthalten Informationen über die Fehlerursache und stellen
Methoden zum Zugriff zu diesen zur Verfügung.
Werfen einer Exception (throwing) bedeutet das Erzeugen eines Objekts einer Exception-Klasse und die
anschliessende Suche eines passenden Exception-Handlers.
Wird ein derartiger Handler gefunden, wird ihm das Exception-Objekt (genauer eine Referenz darauf)
übergeben (Æ Fangen der Exception, catching).
Dem Handler stehen damit die im Exception-Objekt enthaltenen Informationen zur Auswertung zur
Verfügung.
◇ Exception Handling wird in Java sehr umfangreich und strikt angewendet :
▻ In der Standard-Bibliothek sind zahlreiche Exception-Klassen definiert.
Sie bilden eine über mehrere Pakete verteilte Klassenhierarchie, die die Klasse Throwable (von
Object abgeleitet, Paket java.lang) als Wurzelklasse besitzt.
Im Konstruktor einer derartigen Klasse wird i.a. die Exception-Ursache bzw eine Kurzbeschreibung
der Exception durch einen String (fest codiert oder als Parameter übergeben) festgelegt.
▻ Methoden vieler Bibliotheksklassen werfen Exceptions.
▻ Java erzwingt, dass geworfene Exceptions gefangen werden müssen. Existiert in einem Benutzerprogramm kein geeigneter Exception-Handler, so werden sie von einem in der JVM angesiedelten
Standard-Handler behandelt, der Informationen über die Exception in die Standard-Ausgabe ausgibt
und anschliessend das Programm (genauer den aktuellen Thread) beendet.
▻ Ein Benutzer kann jederzeit eigene Exception-Klassen definieren. Dies kann sinnvoll sein, wenn spezielle
Fehlerfälle gesondert von anderen behandelt werden sollen (z.B. "Division durch Null" als Spezialfall einer
ArithmeticException).
Eine beutzerdefinierte Exception-Klasse muß von einer der Standard-Bibliotheks-Exception-Klassen
abgeleitet sein.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/03/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Exceptions in Java (2)
• Hierarchie der Bibliotheks-Exception-Klassen
◇ Alle Exception-Klassen sind – direkt oder indirekt – von der Klasse Throwable abgeleitet.
◇ Die Klasse Throwable (Paket java.lang) ist eine direkte Unterklasse von Object.
◇ Überblick über den Anfang der Hierarchie :
Throwable
Error
VirtualMachineError
weitere
Error-Klassen
ArithmeticException
Exception
RuntimeException
IOException
weitere
RuntimeExceptionKlassen
FileNotFoundException
weitere
ExceptionKlassen
weitere
IOExceptionKlassen
◇ Exceptions der Klasse Error sowie der davon abgeleiteten Klassen kennzeichnen ernsthafte
Systemfehler, die normalerweise nicht auftreten sollten, aber prinzipiell jederzeit auftreten können.
Ein normales Benutzerprogramm kann auf derartige Exceptions i.a. nicht sinnvoll reagieren und sollte sie
deswegen auch nicht fangen. Vielmehr sollten sie immer vom Default-Exception-Handler der JVM behandelt
werden.
◇ Exceptions der Klasse RuntimeException sowie der davon abgeleiteten Klassen können ebenfalls
prinzipiell an beliebiger Stelle während des Programmablaufs auftreten. I.a. liegt ihre Ursache in einem
logischen Programmierfehler (z.B. Division durch 0 oder unzulässiger Array-Index). Eine vernünftige
Reaktion zur Laufzeit ist i.a. nicht möglich. Derartige Fehler sollten i.a. im Programm-Code korrigiert werden.
Ein Benutzerprogramm kann diese Exceptions behandeln (d.h. geeignete Exception-Handler bereitstellen),
muß es aber nicht. Im letzteren Fall erfolgt wiederum eine Behandlung durch den Default-Handler der JVM.
◇ Exceptions aller übrigen Klassen (z.B. IOException) repräsentieren Fehler, mit denen man prinzipiell
rechnen muß (z.B. Datei ist nicht vorhanden) und die deswegen auch in irgendeiner Weise behandelt werden
müssen. Für diese Exceptions schreibt Java eine "catch-or-declare"-Erfordernis vor. Sie müssen von der
Funktion, in der sie geworfen werden, entweder gefangen oder von ihr als weiter-werfbar deklariert werden.
Andererseits darf eine Funktion nur solche Exceptions dieser Klassen werfen, die sie auch deklariert hat.
Das Einhalten dieser Erfordernis kann vom Compiler überprüft werden. Sie werden daher als geprüfte
(checked) Exceptions bezeichnet.
◇ Exceptions der Klassen Error und RuntimeException sowie der davon abgeleiteten Klassen sind
dagegen ungeprüfte (unchecked) Exceptions. Sie können jederzeit geworfen werden, ohne dass sie von der
entsprechenden Funktion deklariert werden müssen. Für sie gilt die "catch-or-declare"-Erfordernis nicht, sie
dürfen aber deklariert werden
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/03/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Exceptions in Java (3)
• Die Klasse Throwable
◇ Die direkt von der Klasse Object abgeleitete Klasse Throwable (Paket java.lang) ist Basisklasse
aller Exception-Klassen.
◇ Sie definiert ein allgemeines Interface für den Zugriff zu den Exception-Objekten aller Exception-Klassen
Die vier wichtigsten Methoden dieses Interfaces sind :
public String getMessage()
▻ Diese Methode gibt den bei der Exception-Objekt-Erzeugung gespeicherten Ursachen- bzw KurzbeschreibungsString als Funktionswert zurück, bzw null, falls kein derartiger String gespeichert wurde.
public String toString()
▻ Diese Methode erzeugt einen String, der aus dem vollqualifizierten Namen der tatsächlichen Klasse des ExceptionObjekts besteht, gegebenenfalls (falls getMessage() einen Wert !=null zurückgibt) gefolgt von ": " und
dem Rückgabewert von getMessage().
public void printStackTrace()
▻ Diese Methode gibt den Funktionswert von toString() gefolgt von dem Aufruf-Stack der Funktion, in der die
Exception ursprünglich geworfen wurde, in die Standard-Fehler-Ausgabe (System.err) aus.
public void printStackTrace(PrintStream s)
▻ Diese Methode gibt den Funktionswert von toString() gefolgt von dem Aufruf-Stack der Funktion, in der die
Exception ursprünglich geworfen wurde, in den durch s referierten Print-Stream aus.
• Deklaration werfbarer Exceptions (throws-Klausel)
◇ Die von einer Funktion werfbaren geprüften Exceptions müssen von dieser deklariert werden.
Werfbare ungeprüfte Exceptions können, müssen aber nicht deklariert werden.
◇ Die Deklaration erfolgt durch eine im Funktionskopf nach der Parameterliste anzugebende throwsKlausel. Die throws-Klausel besteht aus dem Schlüsselwort throws, gefolgt von einer durch
Kommata getrennten Auflistung von Exception-Klassen
◇ Syntax :
throws
Exception-Klasse
,
◇ Beispiel :
public String liesEtwas(String dname)
throws FileNotFoundException, EOFException
{
// ...
}
• Werfen einer Exception – throw-Anweisung
throw
Exception-Objekt-Referenz
;
◇ Nach dem Schlüsselwort throw ist eine Referenz auf das zu werfende Exception-Objekt anzugeben.
Diese Referenz kann
▻ der Wert eines new-Ausdrucks sein (neu erzeugtes Exception-Objekt)
▻ die einem Exception-Handler übergebene Objekt-Referenz sein ("Weiterwerfen" der Exception)
◇ Beispiel :
throw new ArithmeticException("Nenner ist Null");
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/03/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Exceptions in Java (4)
• Die try-Anweisung
◇ Sie ermöglicht das Überwachen und das Fangen von Exceptions.
◇ Eine try-Anweisung besteht i.a. aus drei Teilen :
▻ dem try-Block
▻ einem oder mehreren catch-Blöcken
▻ einem finally-Block
Entweder die catch-Blöcke oder der finally-Block dürfen auch fehlen, aber nicht beides.
◇ Syntax :
try
{
catch
(
finally
Anweisung
Exception-Klasse
}
Name
{
Anweisung
}
{
Anweisung
}
)
◇ Der try-Block enthält den eigentlichen produktiven Code, der auf den Auftritt von Exceptions überwacht wird. Er wird solange ausgeführt, bis entweder durch eine der Anweisungen eine Exception (direkt
durch eine throw-Anweisung oder indirekt durch eine aufgerufene Funktion) geworfen wird oder alle
Anweisungen erfolgreich abgearbeitet worden sind.
Beim Auftritt einer Exception wird der try-Block sofort verlassen und nach einem Exception-Handler
gesucht, der die Exception fangen kann.
◇ Die catch-Blöcke bilden die Exception-Handler.
Jeder catch-Block ist zuständig für das Fangen von Exceptions einer bestimmten Klasse und deren
Unterklassen. Die von einem catch-Block fangbare Exception-Klasse ist in seinem Kopf – analog zur
Parameter-Deklaration von Funktionen – angegeben. Da Objekte (genauer Objekt-Referenzen) einer Klasse
zuweisungskompatibel zu Variablen einer Basisklasse sind, können auch Exceptions aller Klassen, die von der
deklarierten Klasse abgeleitet sind, gefangen werden.
Die Suche nach einem "passenden" Exception-Handler erfolgt in der Reihenfolge seiner Angabe im Quellcode. Wird ein Exception-Handler gefunden, der die geworfene Exception fangen kann, wird das Programm mit dessen Abarbeitung fortgesetzt. Dabei wird die Exception wie ein formaler Funktionsparameter
an den Handler übergeben. Wird kein "passender" Exception-Handler gefunden, wird die Suche in der
jeweils nächsten umfassenden try-Anweisung (gegebenenfalls in der aufrufenden Funktion) fortgesetzt.
Bleibt auch das erfolglos, wird der Default-Exception-Handler der JVM ausgeführt und das Programm
beendet.
◇ Der finally-Block enthält Code, der immer ausgeführt wird, unabhängig davon, wie die try-Anweisung verlassen wird, ob durch reguläre Beendigung des try-Blocks oder durch Werfen einer gefangenen
oder nicht gefangenen Exception.
Die Ausführung des finally-Blocks erfolgt unmittelbar vor Verlassen des try-Blocks bzw – beim
Fangen einer Exception – vor Verlassen des entsprechenden catch-Blocks. Die Ausführung erfolgt auch
dann, wenn try- bzw catch-Block mit einer return-Anweisung verlassen werden.
Der finally-Block wird insbesondere verwendet, um Aufräumarbeiten durchzuführen und sicherzustellen, dass belegte System-Resourcen (z.B. geöffnete Dateien) freigegeben werden
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/03/5 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Exceptions in Java (5)
• Demonstrationsprogramm zu Exceptions
// ExceptDemo.java
import java.io.*;
class ExceptDemo
{
public void func1()
{ try
{ System.out.println("in func1() : Aufruf von func2()");
func2();
System.out.println("normales Ende von try in func1()!");
return;
}
finally
{ System.out.println("func1() verlassen !");
}
}
public void func2()
{ try
{ System.out.println("in func2() : Aufruf von func3()");
func3();
System.out.println("normales Ende von try in func2()!");
return;
}
catch (RuntimeException e)
{ System.out.print("Exception-Handler in func2() : ");
System.out.println(e.getMessage());
}
finally
{ System.out.println("func2() verlassen !");
}
}
public void func3()
{ try
{ System.out.println("in func3() : Exception wird geworfen");
throw new RuntimeException("Demo-Exception !");
}
catch (ArithmeticException e)
{ System.out.print("Exception-Handler in func3() : ");
System.out.println(e.getMessage());
}
finally
{ System.out.println("func3() verlassen !");
}
}
public static void main(String[] args)
{ ExceptDemo ed = new ExceptDemo();
ed.func1();
}
}
in func1() : Aufruf von func2()
in func2() : Aufruf von func3()
in func3() : Exception wird geworfen
func3() verlassen !
Exception-Handler in func2() : Demo-Exception !
func2() verlassen !
normales Ende von try in func1()!
func1() verlassen !
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (1)
• Überblick
◇ Java behandelt Dateien als sequentielle Folge von Bytes (Byte-Streams).
◇ In der IO-Bibliothek (Package java.io) sind zahlreiche Klassen definiert, die das Arbeiten mit Dateien
unterstützen.
Die wichtigsten dieser Klassen sind :
▻ die File-Stream-Klassen zum sequentiellen Zugriff
• FileInputStream (byteweises Lesen)
• FileOutputStream (byteweises Schreiben)
• FileReader (zeichenweises Lesen)
• FileWriter (zeichenweises Schreiben)
▻ eine Klasse zum wahlfreien Zugriff (Lesen und Schreiben)
• RandomAccessFile
▻ Klassen für den Zugriff zum Dateisystem
• FileDescriptor (Handle zur Datei-Verwaltungsstruktur des Betriebssystems, hier nicht betrachtet)
• File
▻ Zahlreiche weitere Stream-Klassen (meist Filter-Klassen) ermöglichen einen spezialisierten Dateizugriff
◇ Auszugsweises Klassendiagramm :
Anmerkungen :
▻ Das Diagramm beschränkt sich auf die Datei-Eingabe-Stream-Klassen (FileInputStream,
FileReader).
▻ Für die Datei-Ausgabe-Stream-Klassen (FileOutputStream, FileWriter) bestehen analoge
Ableitungs-und Nutzungsbeziehungen.
Deren – direkte bzw indirekte – Basisklassen sind OutputStream bzw Writer.
▻ Die IO-Bibliothek enthält eine Reihe weiterer – im Diagramm nicht aufgeführter – Stream-Klassen, die
zumeist von InputStream oder Reader (bzw OutputStream oder Writer) direkt oder
indirekt abgeleitet sind.
InputStream
Reader
FilterInputStream
BufferedInputStream
DataInputStream
InputStreamReader
FileInputStream
FileReader
FileDescriptor
File
BufferedReader
RandomAccessFile
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (2)
• Die Klasse File
◇ Objekte dieser Klasse repräsentieren Zugriffspfade (zu Dateien bzw Directories) im Dateisystem.
◇ Wesentliche Funktionalitäten :
▻ Speicherung eines Datei- bzw Directory-Zugriffspfades in einer abstrakten system-unabhängigen
Darstellung, sowie Bereitstellung von Informationen über denselben
▻ Ermittlung diverser Eigenschaften einer repräsentierten Datei (bzw eines repräsentierten Directories)
▻ Manipulation von Dateisystem-Einträgen (Erzeugen, Löschen, Änderung bestimmter Eigenschaften)
◇ Der durch ein File-Objekt repräsentierte Zugriffspfad muß nicht einen tatsächlich existierenden Dateisystem-Eintrag referieren.
◇ Konstruktoren der Klasse File (Auswahl) :
public File(String path)
▻ Erzeugung eines neuen File-Objekts, das den Zugriffspfad path repräsentiert.
▻ Falls path==null ist, wird eine NullPointerException geworfen.
public File(String dirName, String name)
▻ Erzeugung eines neuen File-Objekts, das den aus dirName und name gebildeten Zugriffspfad
repräsentiert. (Eintrag name im Directory dirName).
▻ Äquivalent zu : File(dirName + File.separator + name)
▻ Falls name==null ist, wird eine NullPointerException geworfen.
public File(File fileDir, String name)
▻ Erzeugung eines neuen File-Objekts, das den Zugriffspfad repräsentiert, der aus dem Eintrag
name in dem durch fileDir repräsentierten Directory gebildet wird,
▻ Äquivalent zu : File(fileDir.getPath(), name)
▻ Falls name==null ist, wird eine NullPointerException geworfen.
◇ Methoden zum Erzeugen neuer Dateisystem-Einträge (Auswahl)
public boolean createNewFile() throws IOException
▻ Diese Methode erzeugt eine neue leere Datei mit dem vom aktuellen File-Objekt repräsentierten
Zugriffspfad, falls noch keine Datei mit diesem Zugriffspfad existiert.
▻ Funktionswert : true, falls die Datei erzeugt werden konnte
false,falls eine Datei mit dem Zugriffspfad bereits existiert hat.
▻ Falls ein I/O-Fehler auftritt, wird eine IOException geworfen.
public boolean mkdir()
▻ Diese Methode erzeugt ein neues Directory mit dem vom aktuellen File-Objekt repräsentierten
Zugriffspfad
▻ Funktionswert : true, falls das Directory erzeugt werden konnte, andernfalls false
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (3)
• Die Klasse File, Forts
◇ Methoden zur Veränderung von Dateisystem-Einträgen
public boolean renameTo(File newPath)
▻ Umbenennen / Verschieben des aktuell repräsentierten Dateisystem-Eintrags.
▻ Der Dateisystem-Eintrag wird anschliessend durch das File-Objekt newPath repräsentiert.
Der vom aktuellen Objekt bisher repräsentierte Eintrag existiert anschliessend nicht mehr.
▻ Funktionswert : true, falls Umbenennen / Verschieben erfolgreich war, andernfalls false
▻ Falls newPath==null ist, wird eine NullPointerException geworfen.
public boolean delete()
▻ Löschen des aktuell repräsentierten Dateisystem-Eintrags. Ein zu löschendes Directory muss leer sein.
▻ Funktionswert : true, falls erfolgreich gelöscht werden konnte, andernfalls false
◇ Methoden zur Ermittlung von Informationen über Dateisystem-Einträge (Auswahl)
public boolean exists()
▻ Überprüfung, ob durch das File-Objekt ein tatsächlich existierender Eintrag repräsentiert wird
▻ Funktionswert : true, wenn der Eintrag existiert, sonst false
public boolean isDirectory()
▻ Funktionswert : true, wenn der Eintrag existiert und ein Directory ist, sonst false
public boolean isFile()
▻ Funktionswert : true, wenn der Eintrag existiert und eine normale Datei ist, sonst false
public boolean canWrite()
▻ Funktionswert : true, wenn Eintrag existiert und geändert werden kann, sonst false
public boolean canRead()
▻ Funktionswert : true, wenn Eintrag existiert und gelesen werden kann, sonst false
public String[] list()
▻ Funktionswert : Wenn Eintrag ein Directory ist : Rückgabe einer Auflistung aller in ihm
enthaltenen Einträge als String-Array (ausser "." und "..")
Wenn Eintrag kein Directory ist : null
public long length()
▻ Funktionswert : Dateilänge, wenn Eintrag Datei ist, bzw. undefiniert, wenn Eintrag Directory ist
public String getPath()
public String getAbsolutePath()
▻ Funktionswert : Zugriffspfad des repräsentierten Dateisystem-Eintrags (wie im Konstruktor angegeben)
bzw absoluter Zugriffspfad (gegebenenfalls mittels aktuellem Arbeitsdir. ermittelt)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (4)
• Demoprogramm zur Klasse File
// ListDir.java
import java.io.*;
public class ListDir
{
public static void main(String[] args)
{
try
{ if (args.length<=0)
throw new IOException("Programmparameter (Directory-Pfad) fehlt !");
File dir = new File(args[0]);
if (!dir.exists())
throw new IOException("\"" + args[0] + "\" existiert nicht !");
if (!dir.isDirectory())
throw new IOException("\"" + dir.getPath() + "\" ist kein Directory !");
String[] entries = dir.list();
System.out.println("Inhalt des Directories \"" + dir.getAbsolutePath() + "\" :");
for (int i=0; i<entries.length; i++)
System.out.println(entries[i]);
}
catch (IOException ex)
{
System.out.println(ex.getMessage());
}
}
}
Beispiele für Programmaufruf und -ausgabe
E:\Java\fhm\ee\vorl\fileacc>java ListDir
Programmparameter (Directory-Pfad) fehlt !
E:\Java\fhm\ee\vorl\fileacc>java ListDir meindir
"meindir" existiert nicht !
E:\Java\fhm\ee\vorl\fileacc>java ListDir ftestdir
"ftestdir" ist kein Directory !
Inhalt des Directories "E:\Java\Vorl_Prog\elemprogfunc\." :
FormOutpDemo.java
Echo.java
StdOutDemo1.java
EchoLinesScanDemo.java
StdInpScanDemo.java
package cache
StdOutDemo1.class
FormOutpDemo.class
Echo.class
formoutpdemo.txt
EchoLinesScanDemo.class
StdInpScanDemo.class
ExceptDemo.java
ExceptDemo.class
StdInpCharDemo.class
ListDir.java
ftestdir
ListDir.class
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/5 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (5)
• Sequentieller Dateizugriff mittels der File-Stream-Klassen
◇ Klassen für den byteweisen sequentiellen Dateizugriff :
▻ FileInputStream (byteweises Lesen)
▻ FileOutputStream (byteweises Schreiben)
◇ Klassen für den zeichenweisen sequentiellen Dateizugriff :
▻ FileReader (zeichenweises Lesen)
▻ FileWriter (zeichenweises Schreiben)
◇ Überblick über die Konstruktoren (Auswahl) :
1.Parameter
2. Parameter
String path
Dateizugriffspfad
------File fil
repräsentiert Dateizugriffspfad
String path
Dateizugriffspfad
File fil
repräsentiert Dateizugriffspfad
boolean app
wenn true : Anhängen an Datei (append)
wenn false : Schreiben am Dateianfang
existiert für Klasse
FileInputStream
FileOutputStream
FileReader
FileWriter
FileOutputStream
FileWriter
Beispiele :
public FileInputStream(File fil) throws FileNotFoundException
public FileWriter(String path, boolean app) throws IOException
● Bei der Erzeugung eines File-Stream-Objekts wird die referierte Datei – falls sie vorhanden und die
jeweilige Zugriffsart zulässig ist – geöffnet
● Die Konstruktoren der Datei-Ausgabe-Stream-Klassen versuchen die referierte Datei neu anzulegen,
falls sie nicht existiert.
● Kann eine Datei nicht geöffnet werden (z.B. weil der Zugriffspfad ein Directory referiert), wird eine
FileNotFoundException (bzw bei der Klasse FileWriter eine IOException) geworfen.
◇ Schliessen eines File-Streams
mittels der für alle File-Stream-Klassen existierenden Methode :
public void close() throws IOException
▻ Die Methode schliesst den File-Stream und damit die referierte Datei und gibt alle sonstigen mit dem
Stream assoziierten System-Resourcen frei.
▻ Beim Auftritt eines I/O-Fehlers wird eine IOException geworfen.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/6 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (6)
• Sequentieller Dateizugriff mittels der File-Stream-Klassen, Forts.
◇ Methoden zum Dateizugriff (Auswahl)
● Alle folgenden Methoden werfen eine IOException falls ein I/O-Fehler auftritt
● Schreiben in Dateien (Klassen FileOutputStream / FileWriter)
public void write(int bc) throws IOException
▻ Schreiben des Bytes bc (FileOutputStream) bzw des Zeichens bc (FileWriter)
public void write(byte[] buff, int pos, int len) throws IOException
public void write(char[] buff, int pos, int len) throws IOException
▻ Schreiben von len Bytes (FileOutputStream) bzw von len Zeichen (FileWriter) aus buff
ab Position pos
public void write(String str) throws IOException
// nur FileWriter
▻ Schreiben des Strings str
public void flush() throws IOException
▻ Herausschreiben aller Schreib-Buffer (Übergabe an das Betriebssystem)
● Lesen aus Dateien (Klassen FileInputStream / FileReader)
public int read() throws IOException
▻ Lesen eines Bytes (FileInputStream) bzw eines Zeichens (FileReader)
▻ Funktionswert : gelesenes Byte bzw gelesenes Zeichen
bzw -1 falls das Dateiende erreicht ist
public int read(byte[] buff) throws IOException
public int read(char[] buff) throws IOException
▻ Lesen einer Byte-Folge (FileInputStream) bzw einer Zeichen-Folge (FileReader)
▻ Ablage der gelesenen Byte- bzw Zeichen-Folge im Buffer buff
▻ Funktionswert : Anzahl gelesener Bytes bzw Anzahl gelesener Zeichen
bzw -1 falls das Dateiende erreicht ist
public long skip(long n) throws IOException
▻ Überlesen der nächsten n Bytes (FileInputStream) bzw der nächsten n Zeichen (FileReader)
● Es existieren noch weitere Methoden, mit denen auch Teile eines Byte- bzw Zeichen-Arrays gelesen
bzw Teile eines Strings geschrieben werden können.
◇ Durch die Zusammenarbeit mit geeigneten Filterklassen lassen sich spezialisiertere Formen der DateiEin-/Ausgabe realisieren.
Beispiel : Die Zusammenarbeit von FileInputStream mit DataInputStream sowie
FileOutputStream mit DataOutputStream ermöglicht das Lesen und Schreiben von
Daten in Binärdarstellung.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/7 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (7)
• Demoprogramm zum sequentiellen Dateizugriff (Kopieren einer Datei)
// FileCopy.java
import java.io.*;
public class FileCopy
{
public static void main(String[] args)
{
if (args.length <2)
System.out.println("Aufruf : \"java FileCopy quelldatei zieldatei\"");
else
{
try
{
File ifile = new File(args[0]);
FileInputStream in = new FileInputStream(ifile);
FileOutputStream out = new FileOutputStream(args[1]);
long fsize = ifile.length();
System.out.print("Kopiert wird \"" + args[0]+ "\" (Laenge : ");
System.out.println(fsize + " Bytes) nach \"" + args[1]+ "\"");
byte[] buff = new byte[512];
int len;
while ((len=in.read(buff))>=0)
{
out.write(buff, 0, len);
}
out.close();
in.close();
System.out.println("Kopieren der Dateien erfolgreich");
}
catch(IOException ex)
{
System.out.println("Exception : " + ex.getMessage());
}
}
}
}
Beispiel für Programmaufruf und -ausgabe
E:\Java\fhm\ee\vorl\fileacc>java FileCopy ListDir.class ListDir.bin
Kopiert wird "ListDir.class" (Laenge : 1100 Bytes) nach "ListDir.bin"
Kopieren der Dateien erfolgreich
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/8 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (8)
• Wahlfreier Zugriff zu Dateien – Klasse RandomAccessFile
◇ Den wahlfreien Zugriff zu Dateien ermöglicht die Klasse RandomAccessFile.
Diese Klasse ist von keiner der File-Stream-Klassen sondern direkt von Object abgeleitet.
◇ Durch Objekte dieser Klasse können Dateien für einen wahlfreien Zugriff nur zum Lesen oder zum Lesen
und Schreiben geöffnet werden.
Der wahlfreie Zugriff wird durch die Möglichkeit zur expliziten Veränderung der aktuellen Bearbeitungsposition (File-Pointer, nicht zu verwechseln mit dem File-Pointer in C, der referiert eine Datei) realisiert.
◇ Die Klasse stellt zahlreiche Methoden bereit, mit denen auch spezialisierte Dateizugriffe möglich sind :
▻ Lesen und Schreiben von Bytes und Bytefolgen (Byte-Arrays)
▻ Schreiben von Strings als Byte-Folge, Zeichenfolge und in UTF-8-Codierung
▻ zeilenweises Lesen (Textdateien !)
▻ Lesen von Strings in modifizierter UTF-8-Codierung
▻ Lesen und Schreiben von Werten der einfachen Datentypen in interner Binärdarstellung (Binärdateien !)
◇ Anmerkung zur modifizierten UTF-8-Codierung :
▻ UTF = Universal Transfer Format : effiziente Codierung von Unicode-Zeichen durch 1, 2 und 3 Bytes
▻ Zeichen zwischen '\u0001' und '\u007F' durch ein Byte :
01 ... 7F
Zeichen zwischen '\u0080' und '\u07FF' durch zwei Bytes : C2 80 ... DF BF
Zeichen zwischen '\u0800' und '\uFFFF' durch drei Bytes : E0 A0 80 ... EF BF BF
der NUL-Character (das Zeichen '\u0000')
durch zwei Bytes : C0 80
▻ Vor der eigentlichen den String codierenden Bytefolge wird deren Länge als short-Wert
(2 Bytes) in den Stream geschrieben.
◇ Konstruktoren der Klasse RandomAccessFile
public RandomAccessFile(String path, String mode) throws
FileNotFoundException
public RandomAccessFile(File fil, String mode) throws
FileNotFoundException
▻ Der erste Parameter referiert die zu bearbeitende Datei (über den Zugriffspfad bzw ein FileObjekt, das diesen repräsentiert)
▻ Der zweite Parameter legt die Zugriffsart fest :
- "r" nur Lesen,
- "rw" Lesen und Schreiben. ("rws" und "rwd" sind auch zulässig)
▻ Die Konstruktoren versuchen die referierte Datei für die angegebene Zugriffsart zu öffnen.
▻ Falls die referierte Datei nicht existiert wird bei der Zugriffsart "rw" versucht, sie zu erzeugen.
▻ Die Konstruktoren können die folgenden Exceptions werfen :
- FileNotFoundException, falls die referierte Datei nicht existiert (Zugriffsart "r") oder ein
Directory ist oder nicht erzeugt werden kann oder aus einem anderen Grund nicht geöffnet werden
kann.
- SecurityException, falls für die vorgesehene Zugriffsart keine Berechtigung besteht
- IllegalArgumentException, falls ein nicht zulässiger String für die Zugriffsart angegeben
wird.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/9 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (9)
• Wahlfreier Zugriff zu Dateien – Klasse RandomAccessFile, Forts
◇ Methoden der Klasse RandomAccessFile zum Lesen u. Schreiben (Auswahl) :
Schreiben
void write(int b)
void write(byte[] ba)
Lesen
int read()
int read(byte[] ba)
Datentyp
byte
byte-Array
Rückgabewert : Anzahl gelesener Bytes
void write(byte[] ba,
int off, int len)
int read(byte[] ba,
int off, int len
byte-Array (Länge
len ab Offset off)
Rückgabewert : Anzahl gelesener Bytes
void writeBytes(String str)
void writeChars(String str)
void writeUTF(String str)
----String readUTF()
String als Byte-Folge
String als Char-Folge
String (UTF-8-Cod.)
String readLine()
String (Zeile)
Lesen der nächsten Zeile (Rückgabewert)
Bytes werden zu Zeichen ergänzt
(höherwertiges Byte == NUL-Byte
void
void
void
void
void
void
void
void
writeBoolean(boolean b)
writeByte(int b)
writeChar(int c)
writeShort(int s)
writeInt(int i)
writeLong(long l)
writeFloat(float f)
writeDouble(double d)
boolean readBoolean()
byte readByte()
char readChar()
short readShort()
int readInt()
long readLong()
float readFloat()
double readDouble()
boolean
byte
char
short
int
long
float
double
Alle Methoden zum Lesen/Schreiben werfen eine IOException, wenn ein I/O-Fehler auftritt.
Die meisten Lese-Methoden werfen beim vorzeitigen Erreichen des Stream-Endes eine EOFException
Æ alle Methoden sind mit der throws-Klausel throws IOException definiert.
◇ Weitere Methoden der Klasse RandomAccessFile (Auswahl)
void seek(long pos) throws IOException
▻ Setzen der Bearbeitungsposition auf pos Bytes nach dem Dateianfang
long getFilePointer() throws IOException
▻ Rückgabe der aktuellen Bearbeitungsposition (in Bytes bezogen auf den Dateianfang)
int skipBytes(int cnt) throws IOException
▻ Versuch, die Bearbeitungsposition um cnt Bytes weiterzusetzen
▻ Rückgabe der Anzahl Bytes, um die tatsächlich weitergesetzt wurde
long length() throws IOException
▻ Rückgabe der Dateilänge
void close()throws IOException
▻ Schliessen der Datei und Freigabe aller belegten Resourcen
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/10 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (10)
• Demoprogramm zum wahlfreien Dateizugriff
// RandAccDemo.java
// Zufallsgesteuerte Auswahl eines Spruches aus einer Textdatei mit Spruechen.
// Die einzelnen Sprueche sind jeweils durch eine Zeile,
// die nur das Zeichen '*' enthaelt, getrennt.
import java.io.*;
public class RandAccDemo
{
public static void main(String[] args)
{
try
{
RandomAccessFile raf = new RandomAccessFile("sprueche.txt", "r");
long pos = (long)(raf.length()*Math.random());
raf.seek(pos);
while((pos!=0) && ((char)raf.read()!='*'))
raf.seek(--pos);
int ch;
if (pos==0)
System.out.println();
while (((ch=raf.read())!=-1) && ((char)ch!='*'))
{
System.out.print((char)ch);
}
System.out.println();
raf.close();
}
catch (IOException ex)
{
System.out.println(ex);
}
}
}
Beispiele für Programmaufruf und -ausgabe
E:\Java\fhm\ee\vorl\fileacc>java RandAccDemo
Gut gehaengt ist besser als schlecht verheiratet.
E:\Java\fhm\ee\vorl\fileacc>java RandAccDemo
Es ist nicht genug, dass man redet,
man muss auch richtig reden.
E:\Java\fhm\ee\vorl\fileacc>java RandAccDemo
Ein Tor nur schliesst aus aeusserem Gehaben
getrost auf eines Menschen innere Gaben.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 13/04/11 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Dateizugriff in Java (11)
• Demoprogramm zum Schreiben von Daten in Binärdarstellung (mittels RandomAccessFile)
// BinDataDemo.java
// Schreiben von Werten einfacher Datentypen und Strings in interner Binärdarstellung
// Lesen als Bytefolgen
import java.io.*;
public class BinDataDemo
{
public static String byteToHex(byte b)
{
String str = Integer.toHexString(b & 0x00FF);
if (str.length() == 1)
str = '0' + str;
return str;
}
public static void main(String[] args)
{
if (args.length <1)
System.out.println("Aufruf : \"java DataStreamDemo dateipfad\"");
else
{
try
{
File fil = new File(args[0]);
RandomAccessFile raf = new RandomAccessFile(fil, "rw");
raf.writeBoolean(true);
raf.writeInt(124);
raf.writeDouble(3.14);
raf.writeUTF("Hallo Java-Freunde");
raf.writeUTF("\u007F\u0080\u07FF\u0800\uFFFF\u0000");
raf.seek(0);
System.out.println("Inhalt der Datei \"" + args[0] + "\" :");
int b;
int cnt = 0;
while((b=raf.read())!=-1)
{
cnt++;
String hex = byteToHex((byte)b);
System.out.print(hex + ' ');
if (cnt%25 == 0)
System.out.println();
}
System.out.println();
raf.close();
}
catch(IOException ex)
{
System.out.println("Exception : " + ex.getMessage());
}
}
}
}
Programmaufruf und -ausgabe
E:\Java\fhm\ee\vorl\fileacc>java DataStreamDemo demo.dat
Inhalt der Datei "demo.dat" :
01 00 00 00 7c 40 09 1e b8 51 eb 85 1f 00 12 48 61 6c 6c 6f 20 4a 61 76 61
2d 46 72 65 75 6e 64 65 00 0d 7f c2 80 df bf e0 a0 80 ef bf bf c0 80
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/00/0 – TH – 01
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Programmieren (4. Sem.)
Kapitelüberblick
13. Vererbung und Polymorphie
13.1. Umfassende Klassendefinition
13.2. Klassenableitung
13.3. Polymorphie
13.4. Interfaces und ihre Implementierung
13.5. Programmbeispiel : Simpson-Integration
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/01/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Umfassende Klassendefinition (1)
• Wiederholung
◇ Klassen sind die grundlegenden Programmiereinheiten in Java.
Jedes Java-Programm besteht aus einer oder mehreren Klassen.
Es existiert kein Code ausserhalb einer Klasse.
◇ I.a. ist jede Klasse in einer eigenen Quelldatei definiert (Ausnahme : eingebettete Klassen).
Diese Klassen-Quelldateien bilden die Übersetzungseinheiten (Übersetzungs-Module).
Pro Klasse (auch für jede eingebettete Klasse) wird vom Compiler eine eigene Byte-Code-Datei erzeugt.
◇ Klassen definieren den Aufbau und die Funktionalität (das Verhalten) von Objekten.
Objekte sind Instanzen von Klassen.
Sie bestehen aus Datenkomponenten (Felder, fields), die ihren Zustand beschreiben und besitzen
Funktionen (Memberfunktionen, Methoden, methods), die mit diesen Datenkomponenten arbeiten und ihr
Verhalten festlegen.
Die Datenkomponenten und die (Member-)Funktionen werden in einer Klassendefinition festgelegt und als
Klassenkomponenten bezeichnet.
◇ Neben den instanzspezifischen Datenkomponenten (Instanz-Variable) und Memberfunktionen (InstanzMethoden) kann eine Klasse auch klassenspezifische Datenkomponenten (Klassen-Variable) und Memberfunktionen (Klassen-Methoden) besitzen. Derartige statische Klassenkomponenten beschreiben den
Zustand und das Verhalten der Klasse.
• Klassenkomponenten
◇ Klassenkomponenten (class members) können sein :
▻ Datenkomponenten (Membervariable, Felder, fields)
▻ Funktionskomponenten (Memberfunktionen, Methoden, methods)
▻ Eingebettete Klassen und Interfaces (nested classes and interfaces)
(hier nicht weiter betrachtet)
◇ Zusätzlich kann eine Klassendefinition enthalten :
▻ Konstruktoren (Sie werden in Java nicht zu den Memberfunktionen gerechnet)
▻ Initialisierungsblöcke (Code zur Initialisierung von Datenkomponenten)
(hier nicht weiter betrachtet)
• Syntax der Klassendefinition (vollständig) :
class
Klassen-Name
KlassenModifizierer
Typ-ParamDeklaration
{
KlassenAbleitung
Komponentendefinition
Konstruktordefinition
Initialisierungsblock
;
InterfaceImplementierung
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/01/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Umfassende Klassendefinition (2)
• Klassen-Modifizierer
◇ Sie legen bestimmte Eigenschaften der Klasse fest
◇ Die wichtigsten Modifizierer sind :
▻ public
Die Klasse ist öffentlich zugänglich – sie kann überall verwendet werden.
Ohne diesen Modifizierer ist sie nur innerhalb des Packages, in dem sie enthalten ist, verwendbar.
▻ abstract
Die Klasse ist unvollständig definiert oder sie wird als unvollständig definiert betrachtet
Æ abstrakte Klasse.
Eine abstrakte Klasse ist nicht instanzierbar.
I.a. besitzt sie eine oder mehrere abstrakte Methoden.
Eine abstrakte Methode besitzt keine vollständige Definition. Häufig ist sie lediglich deklariert.
Ihre – vollständige – Definition bleibt einer abgeleiteten Klasse überlassen.
▻ final
Von der Klasse können keine weiteren Klassen abgeleitet werden.
Damit können ihre Methoden niemals überschrieben werden.
◇ Die gleichzeitige Verwendung der Modifizierer public und abstract bzw public und final
ist zulässig.
Die Modifizierer abstract und final schließen sich gegenseitig aus.
• Typ-Param-Deklaration
Deklaration von formalen Typ-Parametern (Typ-Variable).
Falls vorhanden, wird dadurch eine generische Klasse definiert.
Generische Klassen werden hier nicht weiter betrachtet.
• Klassen-Ableitung
Festlegung der Basisklasse, falls es sich um eine abgeleitete Klasse handelt.
Eine direkte Ableitung von der Klasse Object wird nicht explizit angegeben.
• Interface-Implementierung
Festlegung der von der Klasse direkt implementierten Interfaces
• Eingebettete Klassen und Interfaces
Als Klassenkomponenten lassen sich auch Klassen und Interfaces definieren.
Æ eingebettete Typen.
Dies wird gegebenenfalls angewendet, um den logischen Zusammenhang eng zusammenarbeitender
Klassen auszudrücken.
Es gibt verschiedene Arten eingebetteter Typen
Sie werden hier nicht weiter betrachtet
• Initialisierungsblöcke
Hierbei handelt es sich um Codeblöcke, die ausserhalb jeder Funktion definiert sind.
Dieser Code dient – als Alternative und/oder Ergänzung zu Konstruktoren und Feld-Initialisierern – zur
Initialisierung von Datenkomponenten. Damit lassen sich – insbesonder auch für statische Datenkomponenten –
komplexere Initialisierungsalgorithmen formulieren.
Auf Initialisierungsblöcke wird hier nicht weiter eingegangen.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/01/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Umfassende Klassendefinition (3)
• Ergänzungen zur Definition von Memberfunktionen :
◇ Methoden-Modifizierer :
Neben den schon bekannten Modifizierern public, private, protected, static und
final existieren noch weitere Methoden-Modifizierer. U.a. sind dies :
▻ abstract
Es handelt sich um eine abstrakte Methode.
Für eine derartige Methode wird nur die Signatur (Name und Parameter), der Rückgabetyp und gegebenenfalls die throws-Klausel nicht jedoch die Implementierung festgelegt. (Methode wird nur deklariert)
Der Methoden-Rumpf wird durch ein ; ersetzt.
Abstrakte Methoden sind nur in abstrakten Klassen zulässig.
Jede von einer abstrakten Klasse abgeleitete Klasse, die selbst nicht wieder abstrakt ist, muß eine
Definition der abstrakten Methoden bereitstellen.
▻ native
Dieser Modifizierer erlaubt das Einbinden von Methoden, die in nativen Machinencode vorliegen.
Üblicherweise werden derartige Methoden in einer anderen Programmiersprache (z.B. C, C++,
FORTRAN, Assembler) formuliert und dann in Maschinencode übersetzt.
Eine native-Methode wird in der Klassendefinition nur deklariert (statt Methoden-Rumpf nur ; ).
◇ Überladene Funktionen :
In einer Klasse können zwei oder mehr Funktionen mit gleichem Namen, aber unterschiedlicher Parameterliste (Æ unerschiedliche Signatur) definiert werden.
Derartige Funktionen werden als überladen bezeichnet.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (1)
• Prinzip und Eigenschaften der Klassenableitung
◇ Eine Klasse kann durch Vererbung erweitert (extended, subclassed) werden Æ Definition einer
abgeleiteten Klasse.
▻ Die abgeleitete Klasse (subclass, extended class) erbt alle Datenkomponenten und Memberfunktionen
ihrer Basisklasse (superclass), d.h. diese Komponenten stehen auch in der abgeleiteten Klasse zur
Verfügung.
▻ Sie kann neue Datenkomponenten und Methoden hinzufügen. Æ Ergänzung / Änderung der
Eigenschaften und/oder des Verhaltens der Klasse bzw ihrer instanzierter Objekte.
◇ Von einer als final vereinbarten Klasse können keine weiteren Klassen abgeleitet werden.
◇ In Java hat jede Klasse, die nicht explizit von einer anderen Klasse abgeleitet ist, die Klasse Object als
direkte Basisklasse.
◇ Da in Java nur einfache Vererbung möglich ist, besitzt jede Klasse – außer der Klasse Object – genau
eine Basisklasse.
◇ Abgeleitete Klassen sind zuweisungs-kompatibel zu ihren Basisklassen.
Æ Eine Basisklassen-Referenzvariable kann auch auf Objekte abgeleiteter Klassen zeigen.
Über diese Referenz können aber nur die Komponenten der Basisklasse (d.h. des jeweiligen BasisklassenTeilobjekts) angesprochen werden, nicht jedoch die in der abgeleiteten Klasse zusätzlich definierten
Komponenten. (Ausnahme : Zugriff zu überschreibenden Methoden, s. Polymorphie)
◇ In jedem Objekt einer abgeleiteten Klasse steht mit dem Schlüsselwort super eine Referenz auf das in ihm
enthaltene Basisklassen-Teilobjekt zur Verfügung.
Mittels der super-Referenz können nur Komponenten der Basisklasse angesprochen sowie BasisklassenKonstruktoren aufgerufen werden. Sie kann nicht – wie this – allein benutzt werden, um das Basisklassen-Teilobjekt insgesamt anzusprechen.
• Syntax zur Angabe der Basisklasse in der Klassendefinition (extends-Deklaration)
Klassen-Ableitung :
extends
Basisklassenname
• Konstruktoren von abgeleiteten Klassen
◇ Ein Konstruktor kann nur die Datenkomponenten der eigenen Klasse initialisieren.
Die Initialisierung der geerbten Datenkomponenten der Basisklasse muß durch einen Konstruktor der
Basisklasse erfolgen.
◇ Jeder Aufruf eines Konstruktors muß daher als erstes den Aufruf eines Konstruktors der Basisklasse
bewirken. Dies kann u.a. erfolgen durch :
▻ den expliziten Aufruf eines Basisklassen-Konstruktors mittels super(...).
Dieser Aufruf muß die erste Anweisung im Konstruktor der abgeleiteten Klasse sein
▻ den impliziten Aufruf des no-arg-Konstruktors der Basisklasse, wenn die erste Anweisung im
Konstruktor der abgeleiteten Klasse weder super(...) noch this(...) ist.
◇ Anmerkung : In den Parameter-Ausdrücken eines expliziten Konstruktoraufrufs (mittels
super(...)) darf keine Komponente des aktuellen Objekts referiert werden.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/2 – TH – 03
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (2)
• Demonstrationsbeispiel zur Vererbung
◇ Definition einer Basisklasse Punkt
// Punkt.java
public class Punkt
{
private double x;
private double y;
public Punkt()
{ this(0.0, 0.0); }
// no-arg-Konstruktor
// nur zur Demo, ist nicht notwendig
public Punkt(double wx, double wy)
{ x = wx; y = wy; }
// Konstruktor
public Punkt move(double dx, double dy)
{ x += dx; y += dy;
return this;
}
// Die this-Referenz referiert das aktuelle Objekt
// innerhalb einer Memberfunktion
public String showPunkt()
{
return "(" + x + " , " +y + ")";
}
}
◇ Definition einer abgeleiteten Klasse FarbPunkt
// Farbpunkt.java
public class Farbpunkt extends Punkt
{
private String col;
public Farbpunkt()
{ col = "black";
}
// no-arg-Konstruktor
// impliziter Aufruf von super()
public Farbpunkt(String wcol)
{ col = wcol;
}
// Konstruktor
// impliziter Aufruf von super()
public Farbpunkt(double wx, double wy, String wcol)
// Konstruktor
{ super(wx, wy);
// expliziter Aufruf von super()
col = wcol;
}
public String showFarbPunkt()
{
return /*super.*/showPunkt() + " & " + col;
}
}
// verwendet Basisklassenmethode
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/3 – TH – 03
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (3)
• Demonstrationsbeispiel zur Vererbung, Forts.
◇ Definition einer Testklasse APunktTest
// APunktTest.java
// Testklasse fuer die Klassen Punkt und Farbpunkt
public class APunktTest
{
public static void main(String[] args)
{
Punkt p1
= new Punkt(4.2, 6.3);
Farbpunkt p2 = new Farbpunkt("rot");
Punkt p3
= new Farbpunkt(2.5, 3.7, "blau");
//
System.out.println("p1 :
System.out.println("p2 :
System.out.println("p3 :
System.out.println("p3 :
System.out.println("nach
p1.move(1.0, 1.0);
p2.move(1.0, 1.0);
p3.move(1.0, 1.0);
System.out.println("p1 :
System.out.println("p2 :
System.out.println("p3 :
" + p1.showPunkt());
" + p2.showFarbPunkt());
" + p3.showFarbPunkt());
" + p3.showPunkt());
\"move(1,1)\": ");
" + p1.showPunkt());
" + p2.showFarbPunkt());
" + p3.showPunkt());
}
}
◇ Ausgabe des Demonstrations-Programms
p1 :
p2 :
p3 :
nach
p1 :
p2 :
p3 :
(4.2 , 6.3)
(0.0 , 0.0) & rot
(2.5 , 3.7)
"move(1,1)":
(5.2 , 7.3)
(1.0 , 1.0) & rot
(3.5 , 4.7)
// Fehler: p3 ist Punkt-Referenz !
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (2)
• Namensgleichheit bei Komponenten
Die in der abgeleiteten Klasse neu definierten Komponenten können den gleichen Namen wie Komponenten
der Basisklasse tragen. In einem derartigen Fall werden die gleichnamigen Komponenten der Basisklasse
entweder überschrieben oder überdeckt oder überladen.
• Überschreiben von Methoden (Overriding) Æ Polymorphie
◇ Eine in der abgeleiteten Klasse definierte Methode mit gleichem Namen und gleicher Parameterliste
( == gleicher Signatur) sowie gleichem Rückgabetyp wie in der Basisklasse, überschreibt die Methode
der Basisklasse. Hierdurch wird die Basisklassen-Implementierung der Methode für die abgeleitete Klasse
durch eine neue Implementierung ersetzt.
◇ Eine abstrakte Methode der Basisklasse (Deklaration als abstract), wird durch die überschreibende
Methode in der abgeleiteten Klasse überhaupt erst implementiert.
◇ Die Definition einer Methode in der abgeleiteten Klasse, die sich nur im Rückgabetyp von einer Methode
gleichen Namens in der Basisklasse unterscheidet, ist ein Fehler.
Ausnahme : Wenn der Rückgabetyp ein Referenztyp ist, darf die überschreibende Methode eine Referenz
auf eine davon abgeleitete Klasse zurückgeben
◇ Es können nur Methoden überschrieben werden, die weder als static noch als private noch als
final vereinbart sind. Methoden, die überschrieben werden können, werden als virtuell bezeichnet.
Æ In Java ist jede nichtstatische Methode der Basisklasse, die weder private noch final ist,
grundsätzlich virtuell.
◇ Eine in der abgeleiteten Klasse definierte überschreibende Funktion darf die in der Basisklasse festgelegte
Zugriffsberechtigung nicht einschränken.
Eine Erweiterung der Zugriffsberechtigung ist zulässig.
Beispiel : Wenn in der Basisklasse für eine Methode protected festgelegt ist, darf eine überschreibende
Methode in der abgeleiteten Klasse protected oder public sein, jedoch nicht private oder
package.
◇ Bezüglich der Exception-Deklaration (throws-Klausel) gelten folgende Regeln :
▻ Die Exception-Deklarationen von überschreibender und überschriebener Methode können
unterschiedlich sein.
▻ Eine überschreibende Methode darf in ihrer Exception-Deklaration nur Exception-Typen enthalten,
die zu einem in der Exception-Deklaration der überschriebenen Methode festgelegten Typen polymorph
kompatibel sind (d.h. von der gleichen Klasse oder einer von ihr abgeleiteten Klasse sind).
▻ Eine überschreibende Methode muss nicht alle von der überschriebenen Methode deklarierten ExceptionTypen ebenfalls deklarieren.
Auch wenn die überschriebene Methode eine Exception-Deklaration hat, darf diese bei der
überschreibenden Methode fehlen.
▻ Eine überschreibende Methode darf nichtgeprüfte Exceptions werfen, die in der überschriebenen
Methode nicht auftreten können. Diese dürfen aber nicht in die Exception-Deklaration aufgenommen
werden.
◇ Zu der überschriebenen Methode kann – innerhalb der überschreibenden Methode oder in einer anderen
Instanz-Methode der gleichen Klasse – über die Basisklassen-Teilobjekt-Referenz super zugegriffen
werden (nicht jedoch über ihren vollqualifizierten Namen).
super.method(...) ruft immer die Implementierung der Methode method(...) auf, die in der
direkten Basisklasse verwendet wird.
Es kann sich dabei durchaus um eine Methode handeln, die in der Ableitungshierarchie "weiter oben" definiert
und in der direkten Basisklasse selbst nicht neu definiert worden ist.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/5 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (5)
• Überladen von Methoden (Overloading)
◇ Eine in der abgeleiteten Klasse definierte Methode mit gleichem Namen aber anderer Parameterliste,
überlädt die Methode der Basisklasse.
Der Rückgabetyp bleibt unberücksichtigt, er kann gleich oder unterschiedlich sein.
Das gleiche gilt für die Exception-Deklaration (throws-Klausel).
◇ In der abgeleiteten Klasse kann sowohl zu der geerbten Methode der Basisklasse als auch zu der neu
definierten Methode allein über ihren Namen zugegriffen werden.
Æ in Java ist ein Überladen von Methoden auch über Klassengrenzen hinweg möglich.
◇ Auch statische Methoden können im obigen Sinn überladen werden.
◇ Ferner können statische Methoden nicht-statische Methoden und umgekehrt überladen.
• Demonstrationsbeispiel zum Überschreiben und Überladen : siehe nächste Seite
• Überdecken von Klassenkomponenten (Hiding)
◇ Statische Methoden können überdeckt statt überschrieben werden.
Eine in der abgeleiteten Klasse definierte statische Methode mit gleicher Signatur sowie gleichen
Rückgabetyps wie eine statische Methode der Basisklasse, überdeckt die Methode der Basisklasse.
◇ Eine statische Methode darf keine Instanz-Methode überdecken (Æ Compiler-Fehler)
◇ Überdecken von Datenkomponenten ist zulässig
▻ zwischen Instanz-Variablen (nicht-statischen Datenkomponenten)
▻ zwischen Klassen-Variablen (statischen Datenkomponenten)
▻ gemischt zwischen Instanz- und Klassen-Variablen.
◇ Das Überdecken zwischen Datenkomponenten unterschiedlichen Typs ist zulässig.
◇ Überdeckt werden genaugenommen Namen.
Überdecken eines Namens bedeutet, dass in der abgeleiteten Klasse der Name allein nur in der in dieser
Klasse definierten Bedeutung verwendet werden kann.
Um den Namen in der Bedeutung, die in der Basisklasse definiert ist, zu verwenden, muss der entsprechende
vollqualifizierte Name oder der Name zusammen mit einer anderen Basisklassen-Referenz
(z.B. super.kompo, innerhalb einer Instanz-Methode) verwendet werden.
Die Verwendung des vollqualifizierten Namens ist nur für statische Komponenten zulässig.
◇ Beim Zugriff zu überdeckten Komponenten wird die tatsächlich ausgewählte Komponente durch die
deklarierte Klasse der verwendeten Referenz (und nicht durch die Klasse des referierten Objekts) festgelegt.
(Festlegung zur Compile-Zeit, early binding, keine Laufzeit-Polymorphie !)
◇ Zwischen einer Variablen und einer Funktion gleichen Namens findet kein Überdecken statt.
Beide können gleichzeitig allein mit ihrem Namen verwendet werden.
Das gilt auch, wenn beide in derselben Klasse definiert sind.
◇ Eine als private deklarierte Komponente kann weder überschrieben noch überdeckt werden
(Sie ist ja in der abgeleiteten Klasse überhaupt nicht zugänglich).
Ihr Name kann deshalb in der abgeleiteten Klasse für beliebige Definitionen verwendet werden.
Beispielsweise ist es bei einer Memberfunktion zulässig, in der abgeleiteten Klasse eine Methode mit
gleicher Signatur aber unterschiedlichem Rückgabetyp zu definieren.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/6 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (6)
• Demonstrationsbeispiel zum Überschreiben und Überladen von Methoden
◇ Definition einer Basisklasse Punkt
public class Punkt
{
private double x = 0.0;
private double y = 0.0;
public Punkt()
{ }
public Punkt(double wx, double wy)
{ x = wx; y = wy; }
public Punkt move(double dx, double dy)
{ x += dx; y += dy; return this; }
// Die this-Referenz referiert das aktuelle Objekt
// innerhalb einer Memberfunktion
public Punkt change(Punkt p)
{ x = p.x; y = p.y; return this;}
public String toString()
{ String rs = "(" + x + " , " + y + ")";
return rs;
}
}
◇ Definition einer abgeleiteten Klasse Farbpunkt
public class Farbpunkt extends Punkt
{
private String col;
public Farbpunkt()
{ col = "black";
}
// impliziter Aufruf von super()
public Farbpunkt(String wcol)
{ col = wcol;
}
// impliziter Aufruf von super()
public Farbpunkt(double wx, double wy, String wcol)
{ super(wx, wy);
col = wcol;
}
public Farbpunkt change(String ncol)
{ col = ncol;
return this;
}
// ueberlaedt Basisklassenmethode
public Farbpunkt change(Farbpunkt fp)
{ change((Punkt)fp);
change(fp.col);
return this;
}
// ueberlaedt Basisklassenmethode
public String toString()
// ueberschreibt Basisklassenmethode
{ String ts = super.toString() + " & " + col;
return ts;
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/02/7 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenableitung (6)
• Demonstrationsbeispiel zum Überschreiben und Überladen von Methoden, Forts
◇ Definition einer verwendenden Test-Klasse PunktTest
// PunktTest.java
public class PunktTest
{
public static void main(String[] args)
{
Punkt p1
= new Punkt(4.2, 6.3);
Punkt p2
= new Farbpunkt();
Punkt p4
= new Farbpunkt("magenta");
Farbpunkt p5 = new Farbpunkt(2.5, 3.7, "blue");
System.out.println("p1 : " + p1);
System.out.println("p2 : " + p2);
System.out.println("p4 : " + p4);
System.out.println("p5 : " + p5);
System.out.println("nach einigen Aenderungen : ");
p5.move(1.0, 1.0);
System.out.println("p5 : " + p5);
p5.change("yellow");
System.out.println("p5 : " + p5);
p5.change(p1);
System.out.println("p5 : " + p5);
p4.change(p5);
System.out.println("p4 : " + p4);
}
}
◇ Ausgabe des Demonstrations-Programms
p1 :
p2 :
p4 :
p5 :
nach
p5 :
p5 :
p5 :
p4 :
(4.2 , 6.3)
(0.0 , 0.0) & black
(0.0 , 0.0) & magenta
(2.5 , 3.7) & blue
einigen Aenderungen :
(3.5 , 4.7) & blue
(3.5 , 4.7) & yellow
(4.2 , 6.3) & yellow
(4.2 , 6.3) & magenta
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/03/1 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Polymorphie (1)
• Wesen der Polymorphie
◇ Poymorphie (griech. : Vielgestaltigkeit) bedeutet, dass mit dem gleichen Namen unterschiedliche Dinge
bezeichnet werden können.
D.h. der gleiche Name/Begriff kann unterschiedliche Bedeutungen haben.
• Realisierungsarten der Polymorphie in Java
◇ Eine simple Form der Polymorphie liegt bei – auch innerhalb einer Klasse möglichen – überladenen
Funktionen vor.
Funktionen mit unterschiedlicher Funktionalität werden über den gleichen Namen aufgerufen.
Die Unterscheidung, welche Funktion aufzurufen ist, wird durch die Parameterliste festgelegt.
Dies kann der Compiler vornehmen Æ Compilezeit-Polymorphie, statisches Binden, early binding.
◇ Compilezeit-Poymorphie ist auch bei der Auswahl von überdeckten Komponenten zwischen
Basisklassen und abgeleiteten Klassen gegeben.
◇ Wesentlich interessanter und mächtiger sind die Referenz-Polymorphie und die darauf aufbauende
Laufzeit-Polymorphie durch virtuelle Methoden.
Beide haben das Konzept der Vererbung (Ableitung) als Voraussetzung.
• Referenz-Polymorphie (polymorphic references)
◇ Abgeleitete Klassen sind zuweisungs-kompatibel zu ihren Basisklassen.
D.h. einer Basisklassen-Referenzvariablen können auch Referenzen auf abgeleitete Objekte zugewiesen
werden.
Æ Eine Referenz-Variable kann somit auf Objekte der eigenen Klasse sowie auf Objekte von ihr
abgeleiteter Klassen zeigen
Æ Über den Namen einer Referenz-Variablen können somit Objekte unterschiedlicher – wenn auch
in Ableitungsbeziehungen zueinander stehender – Klassen angesprochen werden.
◇ Andererseits kann ein Objekt einer abgeleiteten Klasse immer auch als Objekt ihrer Basisklasse betrachtet
werden.
Æ Ein Objekt einer abgeleiteten Klasse kann überall verwendet werden, wo ein Objekt der Basisklasse
benötigt wird.
• Laufzeit-Polymorphie durch virtuelle Methoden
◇ Folgt aus der Referenz-Polymorphie :
Virtuelle Methode == (in Java jede) überschriebene/überschreibende Methode
Virtuelle Methoden bewirken, dass Objekte einer abgeleiteten Klasse und Objekte der jeweiligen Basisklasse
für den gleichen Methodenaufruf unterschiedliches Verhalten zeigen.
◇ Beim Aufruf einer virtuellen Methode über eine Basisklassen-Referenz wird die in der tatsächlichen Klasse
des aktuell referierten Objekts definierte Methode ausgeführt.
Über eine Basisklassenreferenz aufgerufene virtuelle Methoden können also – je nach der tatsächlichen
Klasse des referierten Objekts – zur Abarbeitung unterschiedlicher Funktionen führen.
Da eine Basisklassen-Referenz während der Laufzeit i.a. auf unterschiedliche Objekte zeigen kann, kann
der Compiler einem Methodenaufruf keine eindeutige Funktion zuordnen. Dies kann erst die JVM.
Æ Dynamisches Binden, late binding, Laufzeit-Polymorphie !
◇ Ein Cast einer Referenz auf ein Objekt der abgeleiteten Klasse in die Basisklassen-Referenz ändert nicht den
tatsächlichen Typ des referierten Objekts. Über einen derartigen Cast kann daher nicht zur überschriebenen
sondern nur zur überschreibenden Methode zugegriffen werden.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/03/2 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Polymorphie (2)
• Demonstrationsbeispiel zur Polymorphie
◇ Verwendung der Klassen Punkt und Farbpunkt
◇ Definition einer weiteren Test-Klasse PunktTest
// PunktTest.java
// Testklasse fuer die erweiterten Versionen
// der Klassen Punkt und Farbpunkt
public class PunktTest
{
public static void main(String[] args)
{
Punkt p1
= new Punkt(4.2, 6.3);
Punkt p2
= new Farbpunkt();
Farbpunkt p3 = new Farbpunkt("magenta");
Farbpunkt p4 = new Farbpunkt(2.5, 3.7, "blue");
Punkt pa[]
= {p1, p2, p3, p4};
for (int i=0; i<pa.length; i++)
System.out.printf("p%d : %s\n", i+1, pa[i].toString());
System.out.println("nach einigen Aenderungen : ");
p4.move(1.0, 1.0);
p4.change("yellow");
p3.change(p4);
p1.change(p4);
p2.change(p1);
//p2.change("red");
// Fehler : p2 ist Punkt-Referenz !!!
((Farbpunkt)p2).change("red");
for (int i=0; i<pa.length; i++)
System.out.printf("p%d : %s\n", i+1, pa[i]);
System.out.println("Cast der Farbpunkt-Ref. p4 in Punkt-Ref, :");
System.out.println("p4 : " + ((Punkt)p4).toString());
}
}
◇ Ausgabe des Demonstrations-Programms
p1 :
p2 :
p3 :
p4 :
nach
p1 :
p2 :
p3 :
p4 :
Cast
p4 :
(4.2 , 6.3)
(0.0 , 0.0) & black
(0.0 , 0.0) & magenta
(2.5 , 3.7) & blue
einigen Aenderungen :
(3.5 , 4.7)
(3.5 , 4.7) & red
(3.5 , 4.7) & yellow
(3.5 , 4.7) & yellow
der Farbpunkt-Ref. p4 in Punkt-Ref. :
(3.5 , 4.7) & yellow
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/03/3 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Polymorphie (3)
• Typkompatibilität und -umwandlung
◇ Einer Basisklassen-Variablen kann jederzeit eine Referenz auf ein Objekt einer von der Basisklasse
abgeleiteten Klasse zugewiesen werden.
Das durch eine Basisklassen-Variable referierte Objekt einer abgeleiteten Klasse wird dadurch als Objekt
der Basisklasse behandelbar.
Æ Implizite Typumwandlung.
Da von einem spezialisierteren Typ in einen allgemeineren Typ umgewandelt wird, spricht man auch von
einer erweiternden Typumwandlung (widening conversion). Weil diese Umwandlung in der KlassenHierarchie aufwärts erfolgt nennt man sie auch Aufwärts-Cast (upcast).
◇ Die Zuweisung einer Basisklassen-Referenz, die aber tatsächlich auf ein Objekt einer abgeleiteten Klasse
zeigt, an eine Variable des tatsächlich referierten Typs ist implizit nicht möglich.
Sie erfordert eine explizite Typumwandlung mittels des Cast-Operators. Hierbei findet eine Umwandlung
von einem allgemeineren Typ in einen spezialisierteren Typ statt. Man nennt dies eine einengende Typumwandlung (narrowing conversion) oder einen Abwärts-Cast (down cast).
◇ Ein Abwärts-Cast ist prinzipiell unsicher.
Er darf nur dann durchgeführt werden, wenn durch die Basisklassen-Referenz tatsächlich ein Objekt des
angegebenen Zieltyps referiert wird.
Der Versuch einer Typumwandlung, bei der dies nicht erfüllt ist, führt zum Werfen einer Exception vom Typ
ClassCastException.
• Der Operator instanceof
◇ Dieser binäre Operator ermöglicht die Überprüfung, ob ein Ausdruck zuweisungskompatibel zu einem
bestimmten Typ ist.
◇ Syntax :
Ausdruck
instanceof
Typangabe
◇ Wert eines instanceof-Ausdrucks :
▻ true, wenn der Ausdruck der linken Seite zuweisungs-kompatibel zum Typ der rechten Seite ist
▻ false, wenn der Ausdruck der linken Seite nicht zuweisungs-kompatibel zum Typ der rechten Seite ist
◇ Der instanceof-Operator kann eingesetzt werden, um einen sicheren Abwärts-Cast zu ermöglichen.
◇ Beispiel :
class That
{ // ...
}
class More extends That
{ // ...
}
{ // ...
That sref = new More();
More mref;
// ...
if (sref instanceof More)
mref=(More)sref;
// ...
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (1)
• Prinzip des Interfaces
◇ Interfaces definieren – ähnlich wie Klassen – Typen.
Allerdings erfolgt die Definition in einer abstrakten Form, die keinerlei Implementierung bereitstellt.
Damit lassen sich Interfaces nicht instanziieren.
Sie legen – wie der Name bereits ausdrückt – lediglich eine Schnittstelle (Kontrakt) fest, die dann von
Klassen implementiert werden kann.
◇ Ein Interface besteht – ähnlich wie eine Klasse – aus Komponenten.
Diese Komponenten können aber lediglich sein :
▻ abstrakte Methoden
▻ Konstante
▻ eingebettete Klassen und Interfaces (hier nicht betrachtet)
◇ Im Prinzip ähnelt ein Interface einer abstrakten Klasse.
Im Unterschied zu einem Interface kann eine abstrakte Klasse aber eine (Teil-) Implementierung enthalten.
(Instanz- und Klassen-Variable, Klassen-Methoden, definierte Instanz-Methoden).
Ein Interface kann als abstrakte Klasse, die nur Konstante und abstrakte Methoden (und gegebenenfalls
eingebettete Typen) vereinbart, aufgefasst werden ("rein abstrakte" Klasse).
◇ Interfaces müssen wie Klassen in jeweils einer eigenen Quelldatei (Ausnahme eingebettete Interfaces)
definiert werden, deren Hauptname gleich dem Interface-Namen sein muß.
Interfaces werden vom Compiler auch getrennt übersetzt.
• Interface-Definition
◇ Syntax :
interface
Interface-Name
InterfaceModifizierer
Typ-ParamDeklaration
{
Konstantendefinition
InterfaceAbleitung
}
Abstrakte-Methoden-Deklaration
Klassen-/Interface-Definition
◇ Beispiel :
public interface Fahrbar
{
int MOTOR_UND_REIFEN = 3;
//
int MOTOR_UND_SCHRAUBE = 5; //
int MUSKEL_UND_REIFEN = 2;
int MUSKEL_UND_SCHRAUBE = 4;
int LEHRLAUF = 0;
void vorwFahren(double dist);
void rueckwFahren(double dist);
int getAntrieb();
}
;
implizit geltende Modifizierer static und final (Konstante)
sowie public können weggelassen werden
// implizit geltende Modifizierer abstract und public
// können weggelassen werden
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (2)
• Interface-Modifizierer
◇ Zulässig sind u.a. :
▻ public
Ohne diesen Zugriffs-Spezifizierer besitzt jedes Interface die Zugrifssberechtigung package.
▻ abstract
Jedes Interface ist implizit abstract.
Eine explizite Angabe dieses Modifizierers ist daher überflüssig.
• Definition von Memberkonstanten (Interface-Konstante)
◇ Ein Interface darf als Datenkomponenten nur Konstante enthalten.
◇ Jede Datenkomponente ist daher implizit static und final. Zusätzlich ist sie implizit public.
Eine explizite Angabe dieser Feld-Modifizierer ist zwar zulässig, aber überflüssig.
◇ Jede Datenkomponente muß durch einen Initialisierer initialisiert werden.
Æ blank finals sind nicht zulässig. Der Initialisierer muß ein konstanter Ausdruck sein.
• Deklaration abstrakter Memberfunktionen (Interface-Methoden)
◇ Jede in einer Interface-Definition enthaltene Memberfunktion ist implizit public und abstract.
Ihre Vereinbarung muß an Stelle eines Funktionsrumpfes ein ; enthalten.
Nichtöffentliche Memberfunktionen machen keinen Sinn.
◇ Eine explizite Verwendung der Modifizierer abstract und public ist zwar zulässig, aber überflüssig
◇ Andere Modifizierer sind unzulässig.
• Abgeleitete Interfaces
◇ Interfaces können auch voneinander abgeleitet werden
◇ Es gibt aber kein allgemeines Wurzel-Basis-Interface (etwa wie die Wurzel-Basisklasse Object)
◇ Im Unterschied zu Klassen ist bei Interfaces Mehrfachvererbung zulässig.
Æ Ein Interface kann von mehreren anderen Interfaces abgeleitet sein.
◇ Syntax :
Interface-Ableitung :
extends
Basis-Interface-Name
,
◇ Beispiel :
Bibliotheks-Interfaces
Serializable (Package java.io)
Runnable
(Package java.lang)
public Interface SerializeAndRunnable
extends java.io.Serializable, Runnable
{
// ...
}
Das Interface SerializeAndRunnable enthält – durch Vererbung – alle Komponenten der Interfaces
Serializable und Runnable. Zusätzlich kann es weitere Komponenten definieren.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (3)
• Implementierung von Interfaces
◇ Der Sinn von Interfaces liegt in der Definition von Schnittstellen, die zur Realisierung einer Funktionalität
durch Klassen implementiert werden müssen.
◇ Eine Klasse, die ein Interface implementiert, muß sämtliche Methoden des Interfaces (einschliesslich der
von Basis-Interfaces geerbten) definieren (d.h. für sie eine Implementierung bereitstellen) oder selbst als
abstract deklariert sein. Im letzteren Fall können – müssen aber nicht – die nicht implementierten
Methoden des Interfaces als abstrakt deklariert werden
Prinzipiell entspricht die Implementierung eines Interfaces damit der Ableitung von einer (rein) abstrakten
Klasse.
◇ Eine Klasse kann – gegebenenfalls zusätzlich zur Ableitung von einer Klasse – mehrere Interfaces
implementieren. Æ Realisierung einer Art eingeschränkter Mehrfachableitung in Java.
◇ Syntax :
Interface-Implementierung :
implements
Interface-Name
,
Die implements-Klausel muss nach einer – gegebenenfalls vorhandenen – extends-Klausel
aufgeführt werden.
◇ Beispiel :
public class Auto implements Fahrbar
{
private double kmZaehler;
private double kraftstoff;
private double verbrauch;
public Auto(double verbr, double km)
{ kmZaehler = km;
verbrauch = verbr;
}
public int getAntrieb()
{
return MOTOR_UND_REIFEN;
}
public void vorwFahren(double dist)
{
// Funktionsrumpf
}
// Definition der im Interface
// deklarierten Methoden
public void rueckwFahren(double dist)
{
// Funktionsrumpf
}
// weitere Memberfunktionen
}
◇ Die Implementierung eines Interfaces wird auch an abgeleitete Klassen vererbt.
In einem derartigen Fall ist die Angabe einer implements-Klausel bei der abgeleiteten Klasse nicht
explizit notwendig, aber zulässig.
Æ Dem Kopf einer Klassendefinition können nicht in jedem Fall alle implementierten Interfaces entnommen
werden.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (4)
• Demonstationsbeispiel zur Implementierung eines Interfaces
▻ Definition der das Interface Fahrbar implementierenden Klasse Auto
// Auto.java
// Definition der Klasse Auto
// Klasse implementiert das Interface Fahrbar
import java.util.*;
public class Auto implements Fahrbar
{
public static String TANKLEER = "Tanken notwendig !";
private double kmZaehler;
private double kraftstoff;
private double verbrauch;
public Auto(double verbr, double km)
{
kmZaehler = km;
verbrauch = verbr;
}
public int getAntrieb()
{
return MOTOR_UND_REIFEN;
}
public void vorwFahren(double dist)
{
double maxEntf = kraftstoff/verbrauch*100;
if (dist>maxEntf)
dist=maxEntf;
kmZaehler+=dist;
kraftstoff-=dist/100*verbrauch;
if (dist==maxEntf)
throw new RuntimeException(TANKLEER);
}
public void rueckwFahren(double dist)
{
}
public void tanken(double lit)
{
kraftstoff += lit;
}
public double getKmStand()
{
return kmZaehler;
}
public double getKraftstoff()
{
return kraftstoff;
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/5 – TH – 02
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (5)
• Demonstationsbeispiel zur Implementierung eines Interfaces, Forts.
▻ Definition einer Start- und Testklasse AutoTest
//AutoTest.java
//Klasse AutoTest zum Testen der Klasse Auto
import java.util.Scanner;
public class AutoTest
{
public static void main(String[] args)
{ Auto myCar = new Auto(6.0, 500);
Scanner stdinp = new Scanner(System.in);
double entf = 0;
double liter;
double altkm = myCar.getKmStand();
double neukm;
boolean mussTanken = false;
boolean endeFahrt = false;
do
{ try
{ if (entf == 0.0)
{ System.out.print("Fahrstrecke ? ");
entf=stdinp.nextDouble();
}
if (entf==0.0)
endeFahrt = true;
else
myCar.vorwFahren(entf);
}
catch (RuntimeException ex)
{ if (ex.getMessage().equals(Auto.TANKLEER));
{
mussTanken = true;
}
}
finally
{ neukm = myCar.getKmStand();
if (neukm > altkm)
{ entf = entf - (neukm-altkm);
System.out.println("gefahrene km : " + (neukm-altkm));
System.out.println("km-Stand : " + neukm);
altkm = neukm;
}
if (mussTanken)
{ System.out.print("Tanken notwendig, wieviel Liter ? ");
liter = stdinp.nextDouble();
myCar.tanken(liter);
if (myCar.getKraftstoff() > 0)
mussTanken = false;
else
endeFahrt = true;
}
}
} while (!endeFahrt);
System.out.println("Ende der Fahrt !!!");
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/6 – TH – 03
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (6)
• Demonstationsbeispiel zur Implementierung eines Interfaces, Forts. (2)
▻ Beispielhafte Programmdialoge
Fahrstrecke ? 300
Tanken notwendig, wieviel Liter ? 45
gefahrene km : 300.0
km-Stand : 800.0
Fahrstrecke ? 250
gefahrene km : 250.0
km-Stand : 1050.0
Fahrstrecke ? 230
gefahrene km : 200.0
km-Stand : 1250.0
Tanken notwendig, wieviel Liter ? 0
Ende der Fahrt !!!
Fahrstrecke ? 450
Tanken notwendig, wieviel Liter ? 45
gefahrene km : 450.0
km-Stand : 950.0
Fahrstrecke ? 320
gefahrene km : 300.0
km-Stand : 1250.0
Tanken notwendig, wieviel Liter ? 42
gefahrene km : 20.0
km-Stand : 1270.0
Fahrstrecke ? 280
gefahrene km : 280.0
km-Stand : 1550.0
Fahrstrecke ? 130
gefahrene km : 130.0
km-Stand : 1680.0
Fahrstrecke ? 0
Ende der Fahrt !!!
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/04/7 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Interfaces und ihre Implementierung (7)
• Interfaces als Objekt-Referenzen
◇ Objekte einer Klasse, die ein Interface implementiert, lassen sich auch als Instanzen des implementierten
Interfaces behandeln.
Æ Explizite oder implizite Typkonvertierung (cast) eines Objekts in den Typ eines implementierten
Interfaces.
◇ Dies ermöglicht es auch, mit dem instanceof-Operator zu überprüfen, ob die Klasse eines Objekts
ein bestimmtes Interface implementiert.
Beispiel :
Auto car = new Auto(7.0, 10000);
boolean isfb = car instanceof Fahrbar;
// Æ true
◇ Man kann Variable eines Interface-Typs definieren und ihnen Referenzen auf Objekte einer implementierenden Klasse zuweisen.
Natürlich lassen sich über eine Interface-Variable auch nur die Komponenten eines Objekts ansprechen, die in
dem implementierten Interface definiert sind.
Beispiel :
// ...
Fahrbar fb = new Auto(10, 150000);
// ...
fb.getAntrieb();
// ok
fb.tanken(50);
// unzulässig !
// ...
◇ Jede Objekt-Referenz eines Interface-Typs lässt sich allerdings als Referenz auf die Klasse Object
verwenden. Damit lassen sich über eine Interface-Variable auch die in der Klasse Object definierten
Methoden aufrufen.
Dies ist deswegen möglich, da ja das referierte Objekt von irgendeiner Klasse sein muß und jede Klasse von
Object abgeleitet ist.
Beispiel :
// ...
Fahrbar fb = new Auto(5, 1500);
// ...
String str = fb.toString(); // keine Methode von Auto,
// ...
// aber von Object
• Marker Interfaces
◇ Es kann auch sinnvoll sein, ein Interface leer, d.h. ohne jegliche Komponenten, zu definieren.
◇ Ein derartige Interface dient dazu, anzuzeigen, dass eine implementierende Klasse über eine bestimmte
Eigenschaft verfügt. Es markiert die Klasse hinsichtlich des Besitzes dieser Eigenschaft Æ Marker Interface
◇ In der Java-Standardbibliothek sind mehrere derartige Marker Interfaces enthalten.
Beispiel :
▻ Cloneable (Package java.lang)
Es legt fest, dass Objekte einer implementierenden Klasse mit der clone()-Methode geclont werden
können.
Die clone()-Methode ist selbst nicht Komponente des Interfaces, sondern der Klasse Object.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/05/1 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Programmbeispiel : Simpson-Integration(1)
● Aufgabenstellung
◇ Im C-Teil der Vorlesung ist als Beispiel für die Verwendung von Funktions-Pointern ein Programm zur
Anwendung der Simpson-Integration auf verschiedene zu integrierende Funktionen y=f(x) vorgestellt
worden.
In dem Beispiel wird eine allgemeine Simpson-Integrations-Funktion formuliert, der die jeweils zu
integrierende Funktion mittels eines Funktions-Pointers als Parameter übergeben werden muss.
◇ Dieses Beispiel soll nun sinnvoll nach Java portiert werden.
Die Implementierung soll dabei so erfolgen, dass auch eine einfache Erweiterung auf andere numerische
Integrationsverfahren ermöglicht wird.
● Lösung :
◇ Definition einer abstrakten Basisklasse Integrator.
Sie ist Basisklasse für konkrete Klassen, die jeweils ein spezielles numerisches Integrationsverfahren
implementieren. Für die Simpson-Integration soll das die Klasse SimpsonIntegrator sein.
Die Klasse Integrator definiert eine Instanzvariable zur Speicherung der gewünschten Genauigkeit
(die ihr im Konstruktor zu übergeben ist) und deklariert eine abstrakte Methode integrate(
).
Diese ist von den abgeleiteten Klassen zur Realisierung des jeweiligen Integrations-Algorithmus geeignet
zu implementieren.
◇ Jede zu integrierende Funktion wird durch eine Klasse beschrieben, die das Interface FunctionYvonX
implementieren muss (Æ Funktionsklassen).
Dieses Interface deklariert die von den Funktionsklassen zu definierenden Methode funcVal(double x),
die die jeweilige zu integrierende Funktion realisiert.
Beispielhaft werden hier die Funktionsklassen Halbkreis, Dreieck und Polynom2 (Polynom 2. Ord.)
definiert.
◇ Jedes Objekt einer Funktionsklasse lässt sich als Instanz des Interfaces FunctionYvonX behandeln.
Als solche wird es (mittels einer entsprechenden Referenz) der Integrator-Funktion integrate(...)
als Parameter übergeben. Innerhalb dieser Funktion ruft das Integrator-Objekt die Methode
funcVal(...) für dieses Objekt auf.
(Æ "Das Integrator-Objekt schickt die Botschaft funcVal an das FunctionYvonX-Objekt")
◇ Als Startklasse dient eine Klasse SimpIntDemo. In ihrer Methode main() werden ein
SimpsonIntegrator-Objekt sowie die verschiedenen Funktionsklassen-Objekte erzeugt.
● Klassendiagramm der Lösung (ohne Startklasse)
Integrator
FunctionYvonX
eps
integrate()
funcVal()
SimpsonIntegrator
Halbkreis
Dreieck
Polynom2
integrate()
funcVal()
funcVal()
funcVal()
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/05/2 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Programmbeispiel : Simpson-Integration(2)
● Definition der abstrakten Klasse Integrator
// Integrator.java
// abstrakte Basisklasse fuer Integrator-Klassen
package integration;
public abstract class Integrator
{
protected double eps;
public Integrator(double gen)
{ eps = gen;
}
public abstract double integrate(FunctionYvonX func, double x1, double x2);
}
● Definition der Klasse SimpsonIntegrator
// SimpsonIntegrator.java
// Integrator-Klasse, implementiert die Simpson-Integration
package integration;
public class SimpsonIntegrator extends Integrator
{
public SimpsonIntegrator(double gen)
{ super(gen);
}
public double integrate(FunctionYvonX func, double dXu, double dXo)
{ long i;
double
dFl = 0.;
/* letzter Integralwert
*/
double
dFa = 0.;
/* aktueller Integralwert
*/
double
dH;
/* Schrittweite
*/
double
dX;
/* X-Wert
*/
double
dY;
/* Funktionswert
*/
double
dg;
/* Gewicht
*/
double
dErr;
/* Fehler
*/
long n = 2;
/* Intervallanzahl
*/
do /* Schleife ueber jeweils verdoppelte Intervallanzahl */
{ dH = (dXo - dXu)/n;
/* Schrittweite bestimmen
*/
dFa = func.funcVal(dXu) + func.funcVal(dXo);
for (i=1; i < n; i++)
/* Flaeche der akt. Intervallanzahl */
{ dX
= dXu + dH*i;
dY
= func.funcVal(dX);
if (i%2 == 1)
dg = 4.;
else
dg = 2.;
dFa += dg*dY;
}
dFa *= dH/3;
dErr = Math.abs((dFa -dFl)/dFa);
n*=2;
/* Verdoppeln der Intervallanzahl */
dFl = dFa;
} while ( dErr > eps);
return dFa;
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/05/3 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Programmbeispiel : Simpson-Integration(3)
● Definition des Interfaces FunctionYvonX
// FunctionYvonX.java
// Interface fuer Funktions-Klassen, Funktionen der Form y = f(x)
package integration;
public interface FunctionYvonX
{
double funcVal(double x);
}
● Definition der Klasse Halbkreis
// Halbkreis.java
// Funktions-Klasse, die einen Halbkreis implementiert
// Der Radius wird dem Konstruktor uebergeben
package integration;
public class Halbkreis implements FunctionYvonX
{
private double radius;
public Halbkreis(double r)
{ radius = r;
}
public double funcVal(double dX)
{ double dY = 0;
if (dX <= 1. && dX >= -1.)
dY = Math.sqrt (radius*radius - dX*dX);
return dY;
}
}
● Definition der Klasse Polynom2
//
//
//
//
Polynom2.java
Funktions-Klasse, die ein Polynom 2.Grades implementiert
y = a*x*x + b*x +c
Die Polynom-Koeffizienten werden dem Konstruktor uebergeben
package integration;
public class Polynom2 implements FunctionYvonX
{
private double a, b, c;
public Polynom2(double ak, double bk, double ck)
{ a = ak;
b = bk;
c = ck;
}
public double funcVal(double dX)
{ return a*dX*dX + b*dX + c;
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 14/05/4 – TH – 01
--------------------------------------------------------------------------------------------------------------------------------------------------------
Programmbeispiel : Simpson-Integration(4)
● Definition der Klasse Dreieck
//
//
//
//
//
Dreieck.java
Funktions-Klasse, die ein Dreieck implementiert
Koordinaten der Eckpunkte : (xl,0), (xr,0), (0,yh), mit xl < 0 und xr > 0
xl, xr und yh werden dem Konstruktor uebergeben
Die Flaeche des Dreiecks betraegt (xr-xl)*yh/2
package integration;
public class Dreieck implements FunctionYvonX
{
private double xl;
private double xr;
private double h;
public Dreieck(double xlw, double xrw, double yhw)
{ xl=xlw;
xr=xrw;
h=yhw;
}
public double funcVal(double dX)
{ double dRet;
if (dX > xr || dX < xl)
dRet = 0.;
else if(dX >= 0) dRet = (h-h/xr*dX);
else dRet = (h-h/xl*dX);
return dRet;
}
}
● Definition der Start-Klasse SimpIntDemo
// SimpIntDemo.java
// Startklasse fuer ein Demo-Programm zur Simpson-Integration
package integration;
import java.io.*;
import java.util.*;
public class SimpIntDemo
{
public static void main(String[] args)
{ double dXo = 1.;
double dXu = -1.;
double dF;
FunctionYvonX funcArr[] ={ new Halbkreis(1.0),
new Dreieck(-1, 1, 1),
int i;
boolean bBed;
Scanner scan = new Scanner(System.in);
Integrator sig = new SimpsonIntegrator(1.e-8);
new Polynom2(1, -6, 1),
new Dreieck(-0.5, 1, 3) };
do
{ System.out.printf(" Auswahl: ");
i=scan.nextInt();
bBed = i>0 && i <= funcArr.length;
/* Abbruchbedingung formulieren */
if(bBed)
{ dF = sig.integrate(funcArr[i-1],dXu,dXo);
System.out.printf (" Xu: %8.4f, Xo: %8.4f, F: %12.8f \n", dXu,dXo,dF);
}
} while(bBed);
}
}
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/00/0 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Programmieren (4. Sem.)
Kapitelüberblick
14. Grundkonzepte der Objektorientierten Programmierung (OOP)
14.0. Einführung : Grundgedanke der OOP
14.1. Objekte und Klassen
14.2. Kapselung
14.3. Vererbung
14.4. Polymorphie
14.5. Klassenbeziehungen
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/00/1 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Einführung
• Grundgedanke der OOP:
OOP ist eine Softwareentwicklungsmethodik, deren Grundidee aus der Simulationstechnik stammt :
In dieser werden die Objekte der realen Welt sowie deren Beziehungen durch entsprechende Strukturen im
Rechner abgebildet.
In der OOP wird dieses Prinzip auf alle Arten von Informationen und Abläufen – auch auf solche abstrakter
Natur – angewendet.
Der Aufgabenbereich eines zu lösenden Problems wird in Objekte und die zwischen ihnen bestehenden
Beziehungen zerlegt. Diese werden in einem das entsprechende Problem lösenden Programm nachgebildet.
Æ Ein OOP-Programm besteht somit im wesentlichen aus einer Anzahl miteinander in Beziehung stehender
Objekte.
Diese Denk- und Vorgehensweise ermöglicht es, auch sehr umfangreiche und komplexe Aufgaben auf einem
relativ hohem Abstraktionsniveau erfolgreich zu bearbeiten.
Sie nutzt die intellektuellen Fähigkeiten aus, die der Mensch zur Bewältigung der ihn umgebenden Komplexität
entwickelt hat.
Dies sind im wesentlichen die Fähigkeiten des Abstrahierens, des Klassifizierens und des Generalisierens.
Auf ihnen beruhen die Grundkonzepte der OOP :
◈
Bildung von Objekten
◈
Abstraktion der Objekte durch Klassen
◈
Kapselung
◈
Vererbung
◈
Polymorphie
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/01/1 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Grundkonzepte der OOP : Objekte und Klassen (1)
• Konkrete Objekte:
◇ Objekte sind in einem bestimmten Sinn abgeschlossene Einheiten, die durch zwei Aspekte gekennzeichnet
sind :
▻ Sie besitzen einen (inneren) Zustand
▻ und sie verfügen über Fähigkeiten, d.h. sie können bestimmte Operationen – aktiv oder passiv – ausführen
Diese Fähigkeiten und damit das dadurch bestimmte Verhalten können von außen angefordert, aktiviert
werden. Die Aktivierung der Fähigkeiten kann eine Zustandsänderung bewirken.
◇ Beispiel :
Willies Uhr
Zustand :
aktuelle Zeit
Fähigkeiten : Uhr stellen
Zeit fortschalten (ticken)
Zeit darstellen
• Objekte in der OOP
◇ In der OOP stehen Objekte im Vordergrund.
Sie bilden die grundlegenden Strukturierungseinheiten eines OOP-Programmms
Dabei kann ein Objekt sehr konkret aber auch beliebig abstrakt sein, es kann ein statisches Gebilde
(z.B. ein Auto), oder einen dynamischen Ablauf (Vorgang) beschreiben (z.B. ein Tennisspiel).
Der (innere) Zustand des Objekts wird durch Datenstrukturen (Datenkomponenten), seine Fähigkeiten
– die von ihm ausführbaren Operationen – werden durch Funktionen (Prozeduren) beschrieben.
Die Datenkomponenten werden auch als Attribute, die Funktionen (Memberfunktionen) als Methoden
bezeichnet.
◇ Ein Objekt verbindet also Daten und die zu ihrer Bearbeitung dienenden Funktionen (Code !) zu einer
Einheit.
Æ Die von einem Objekt ausführbaren Methoden (= Funktionen) sind Bestandteil des Objekts und nur als
solche relevant.
Dies steht im Gegensatz zur konventionellen (prozeduralen, imperativen) Programmierung, bei der Daten
und Code getrennt sind, wobei der Code (Prozeduren, Funktionen) eigenständig ist und im Vordergrund
steht : Code wird auf Daten angewendet.
◇ In der OOP wird eine Methode für ein Objekt aufgerufen, in dem an das Objekt – i.a. durch ein anderes
Objekt – eine entsprechende Nachricht (Botschaft) geschickt wird : Das Objekt interpretiert die Nachricht
und reagiert mit der Ausführung einer zugeordneten Operation (Methode).
Zwischen den Objekten bestehen also Kommunikationsbeziehungen.
Æ Ein OOP-Programm besteht im wesentlichen aus einer Ansammlung miteinander kommunizierender
und dadurch interagierender Objekte.
◇ Der OOP-Ansatz erfordert eine andere Vorgehensweise bei der Problemlösung :
Statt einer Top-Down-Zerlegung des Problems (Æ hierarchische Modularisierung) müssen die relevanten
Objekte (Aufbau und Verhalten) des Problems und die zwischen ihnen bestehenden Beziehungen ermittelt
werden ( Æ aufgaben- und kommunikationsorientierte Zerlegung)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/01/2 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Grundkonzepte der OOP : Objekte und Klassen (2)
• Klassen
◇ Der Aufbau, die Eigenschaften und Fähigkeiten (Verhaltensweisen) von Objekten werden durch
Klassen beschrieben.
◇ Eine Klasse legt die Datenkomponenten (Datenstruktur) und die Methoden zur Bearbeitung der Daten
(Memberfunktionen) für eine Menge gleichartiger Objekte – d.h. Objekte mit gemeinsamen Merkmalen
und gleichen Fähigkeiten, die diese von anderen Objekten unterscheiden – fest.
◇ Ein spezielles Objekt der durch eine Klasse definierten Objektmenge wird auch Instanz genannt.
Es unterscheidet sich von einem anderen Objekt (einer anderen Instanz) der gleichen Klasse nur durch
seinen jeweiligen Zustand, d.h. den Werten seiner Datenkomponenten.
⇒ Die Klasse entspricht dem Datentyp prozeduraler Programmiersprachen,
während eine Instanz (ein spezielles Objekt dieser Klasse) einer Variablen entspricht.
◇ Eine Klasse kann formal als Erweiterung einer Struktur (struct-Typ) in C aufgefasst werden.
Gegenüber einer nur aus Datenkomponenten bestehenden Struktur besitzt eine Klasse zusätzlich Funktionskomponenten.
◇ Beispiel : Klasse Uhr
Uhr
Datenkomp :
actTime
Funktionskomp : setTime(...)
tick()
displayClock()
◇ Jedes Objekt (Instanz) einer Klasse hat einen eigenen (inneren) Zustand.
Æ Die Datenkomponenten existieren für jedes Objekt (Unterschied zu Modulen der prozeduralen
Programmierung).
Sie werden erst geschaffen, wenn das Objekt generiert wird (Æ "Variablendefinition").
◇ Die Methoden (Funktionen) existieren dagegen nur einmal pro Klasse.
Sie werden durch die Definition der Klasse (Æ "Typdefinition") geschaffen.
Æ Auch wenn es gar keine Objekte dieser Klasse gibt, existieren die Methoden.
Jedes Objekt einer Klasse arbeitet mit demselben Code (Æ Code Sharing)
Beim Aufruf einer Methode für ein spezielles Objekt, wird dieser eine Referenz auf das Objekt als verborgener Parameter übergeben. Dadurch kann die Methode zu sämtlichen Komponenten (also auch den Datenkomponenten) dieses Objekts zugreifen.
Æ Durch den Aufruf der Methode wird diese einem speziellen Objekt zugeordnet.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/02/1 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Grundkonzepte der OOP : Kapselung
• Kapselung (Encapsulation):
◇ Der Benutzer eines Objekts (allg. : Anwenderprogramm, speziell : anderes Objekt) braucht seinen genauen
Aufbau nicht zu kennen.
Ihm müssen lediglich die Methoden, die er für eine Interaktion mit dem Objekt benötigt, d.h. über die er
die Fähigkeiten des Objekts aktivieren und dessen Zustand verändern kann, bekannt zu sein.
Von der internen Darstellung der den jeweiligen Objektzustand festlegenden Daten braucht er dagegen
keinerlei Kenntnis zu haben.
◇ Nur die Funktionen (= Methoden) eines Objekts, die zu seiner Verwendung tatsächlich benötigt werden,
werden allgemein zugänglich, d.h. öffentlich (public), gemacht.
Sie bilden das Interface (Protokoll), über das zu dem Objekt kontrolliert zugegriffen werden kann, d.h. sie
bilden seine Schnittstelle zur "Außenwelt".
Die Daten (u. gegebenenfalls reine Hilfs- und Verwaltungsfunktionen) sind nur Komponenten des Objekts
selbst zugänglich, d.h. privat (private).
Der "Außenwelt" gegenüber bleiben sie verborgen Æ Sie sind nach außen gekapselt.
Hierdurch wird sichergestellt, dass zu einem Objekt nur über eine wohldefinierte Schnittstelle zugegriffen
Werden kann.Æ Klassen-Schnittstelle
Zugriffe zu Interna, die nur zur internen Realisierung und Verwaltung des Objekts dienen, sind nicht möglich
Æ Vermeidung von Fehlern durch Verhinderung eines direkten und unkontrollierten Zugriffs
⇒ Trennung von Interface (Schnittstelle) und Implementierung.
Methoden
Daten
Methoden
◇ Die Kapselung bewirkt außerdem eine Datenabstraktion (data abstraction) :
Eine Datenstruktur ist - nach außen - nicht mehr an eine bestimmte Implementierung gebunden, sondern wird
allein über die auf sie anwendbaren Operationen (Methoden, Funktionen) definiert.
(Æ abstrakter Datentyp, ADT)
Æ Eine Änderung der Implementierung - bei gleichbleibendem Interface – hat keinen Einfluß auf den
Anwendungscode.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/03/1 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Grundkonzepte der OOP : Vererbung
• Vererbung (Inheritance) :
◇ Weitergabe von Eigenschaften (Daten und Funktionen) eines Objekts an ein anderes Objekt.
Zusätzlich zu den ererbten Eigenschaften kann ein Objekt neue spezifische Eigenschaften (Daten und
Funktionen) besitzen bzw. bestimmte Eigenschaften modifizieren.
Æ Schaffung einer neuen Art von Objekten durch Erweiterung einer bestehenden Art von Objekten.
◇ Die Vererbung führt zum Aufbau von Klassenhierarchien :
Eine neue Klasse wird aus einer - oder mehreren - bereits definierten Klasse(n) abgeleitet.
vorhandenene Klasse : Basisklasse, Elternklasse, Oberklasse
neue Klasse :
abgeleitete Klasse, Kindklasse, Unterklasse
Die abgeleitete Klasse erbt die Daten und Methoden der Basisklasse(n).
Dabei können geerbte Methoden abgeändert ("überschrieben") werden.
Zusätzlich kann die abgeleitete Klasse neue Daten und Methoden besitzen.
Æ Abänderung und Ergänzung im Sinne einer weiteren Spezialisierung
◇ Beispiel : Ableitung der Klasse UhrMitDatum von der Klasse Uhr
neue Datenkomponenten :
neue Funktionskomponenten :
geänderte Funktionskomponenten :
actDate
setDate(), setClock()
tick(), displayClock()
Uhr
Datenkomp :
actTime
Funktionskomp :
setTime(...)
tick()
displayClock()
UhrMitDatum
neue Datenkomp :
actDate
neue Funkt.komp :
setDate(...)
setClock(...)
modifiz. Funkt.komp : tick()
displayClock()
◇ Ein Objekt einer abgeleiteteten Klasse kann immer auch als – spezielles - Objekt der Basisklasse(n)
betrachtet werden : z.B. ist jede UhrMitDatum auch eine Uhr.
◇ Einfache Vererbung :
Mehrfachvererbung
:
Ableitung einer Klasse von nur einer Basisklasse.
Ableitung einer Klasse von mehreren Basisklassen
(nicht von allen OOP-Sprachen unterstützt, u.a. auch nicht von Java)
◇ Durch Vererbung übertragene Methoden (Funktionen) existieren nur einmal (Æ Code Sharing).
Dies erleichtert Änderungen und Erweiterungen an bestehenden Klassenhierarchien.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/04/1 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Grundkonzepte der OOP : Polymorphie
• Polymorphie (Polymorphism) :
◇ Verwendung des gleichen Namens für unterschiedliche - aber miteinander verwandte - Dinge.
(griech. : Vielgestaltigkeit)
◇ Polymorphie in der OOP ermöglicht, dass verschiedenartige Objekte (unterschiedlicher aber durch Vererbung miteinander verwandter Klassen) unter einem gemeinsamen Oberbegriff (Basisklasse) betrachtet
und bearbeitet werden können.(Æ Generalisierung)
Beispiel : Sowohl Objekte der Klasse Uhr als auch Objekte der Klasse UhrMitDatum lassen sich als
Uhr-Objekte behandeln.
.
◇ In der Basisklasse definierte Funktionen können in abgeleiteten Klassen mit dem gleichen Namen und
der gleichen Parameterliste (d.h. gleichem Interface) erneut definiert werden.
Æ Überschreiben von Funktionen (Function Overwriting), virtuelle Funktionen.
Dadurch wird das durch den Aufruf einer deratigen Funktion bewirkte Verhalten eines Objekts in der
abgeleiteten Klasse abgeändert.
Der gleiche (Funktions-)Name kann somit zur Spezifizierung einer Gruppe ähnlicher - aber doch unterschiedlicher – Operationen (Methoden) verwendet werden.
Æ Die gleiche durch den Funktions-Namen ausgedrückte Botschaft kann - an unterschiedliche Objekte
gerichtet – zum Aufruf unterschiedlicher Methoden führen.
Die in einem konkreten Fall ausgeführte Operation (Methode) hängt von der tatsächlichen Klasse des Objekts
ab, an das die Botschaft gerichtet ist (Æ "Ein Interface - mehrere Methoden").
Also nicht die Botschaft, d.h. der Aufruf, bestimmt, welche Methode (Funktion) ausgeführt wird, sondern der
Empfänger der Botschaft.
Beispiel : Die Botschaft "displayClock()" an ein UhrMitDatum-Objekt gerichtet, bewirkt die Ausgabe
der Uhrzeit und des Datums, während sie bei einem Uhr-Objekt nur zur Ausgabe der Uhrzeit führt.
⇒
Polymorphie erlaubt durch die Schaffung eines Standardinterfaces die einheitliche
Verarbeitung unterschiedlicher Objekte, die über gemeinsame Grundfähigkeiten verfügen.
Dadurch wird die Beherrschung einer größeren Komplexität ermöglicht.
◇ Beim Aufruf virtueller (überschreibbarer) Methoden wird die Zuordnung der tatsächlich aufgerufenen
Methode zur Botschaft (Methodenname) erst zur Laufzeit vorgenommen. Dies bezeichnet man als
"späte Bindung" ("late binding").
Bei einer Zuordnung bereits zur Compilezeit spricht man von "früher Bindung" ("early binding").
◇ In einer erweiterten Betrachtungsweise ermöglicht Polymorphie auch das – nicht nur in der OOP eingesetzte – Überladen von Funktionen (Methoden) und Operatoren :
▻ Überladen von Funktionen (Function Overloading) :
Mehrere Funktionen können den gleichen Namen besitzen, sofern ihre Parameterliste (Signatur)
unterschiedlich ist.
Durch den gleichen Namen wird auch hier eine Art Standard-Interface (das sich aber nicht auf die
Parameter erstreckt) bereitgestellt, über das sich mehrere unterschiedliche aber meist miteinander
verwandte Methoden aufrufen lassen.
Die speziell angewandte Methode hängt hier von den beim Aufruf übergebenen Daten (Parametern) ab.
▻ Überladen von Operatoren (Operator Overloading) :
Operatoren können zur Anwendung auf unterschiedliche Datentypen umdefiniert werden.
Æ Definition spezieller Operatorfunktionen (in Java nicht möglich)
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/05/1 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenbeziehungen (1)
• Vererbungsbeziehung
◇ Beziehung zwischen Klassen, deren Komponenten sich teilweise überdecken
◇ Eine abgeleitete Klasse erbt die Eigenschaften und Fähigkeiten (Komponenten) der Basisklasse(n).
"ist"-Beziehung Æ ein Objekt der abgeleiteten Klasse ist auch ein Objekt der Basisklasse(n)
◇ Ordnungsprinzip bei der Spezifikation von Klassen.
Æ Generalisierung / Spezialisierung
◇ Ein Spezialfall der Vererbung ist die Implementierung (Basisklasse definiert nur ein Zugriffsinterface)
• Nutzungsbeziehungen
◇ Unter einer (statischen) Nutzungsbeziehung versteht man eine in einem konkreten Anwendungsbereich
geltende Beziehung zwischen Klassen, deren Instanzen voneinander Kenntnis haben und die dadurch
miteinander kommunizieren können
Æ Nutzungsbeziehungen sind notwendig für die Interaktion von Objekten
◇ Assoziation
- Spezielle Beziehung zwischen Klassen bzw Objekten, bei der die Objekte unabhängig voneinander
existieren und lose miteinander gekoppelt sind
Beispiel : einem Objekt wird die Referenz auf ein anderes Objekt in einer Methode als Parameter
übergeben und nur in dieser Methode verwendet
- Navigationsrichtung : legt die Kommunikationsrichtung und die Richtung, in der ein Objekt der einen
Klasse ein Objekt der anderen Klasse referieren kann, fest.
bidirektional (Kommunikation in beiden Richtungen möglich) oder unidirektional
- Kardinalität (multiplicity) : bezeichnet die mögliche Anzahl der an der Assoziation beteiligten Instanzen
einer Klasse.
◇ Aggregation
- Spezielle Beziehung zwischen Klassen bzw Objekten, bei der die Objekte der einen Klasse Bestandteile
(Komponenten) eines oder mehrerer Objekte der anderen Klasse sind.
Æ zwischen den Objekten besteht eine feste Kopplung
- "hat"-Beziehung bzw "ist Teil von"-Beziehung
- Das "umschließende" Objekt bildet einen Container für das bzw die enthaltene(n) Objekt(e)
- Aggregation kann als Spezialfall der Assoziation aufgefaßt werden.
- eine Aggregation ist i.a. eine unidirektionale Beziehung (Navigation vom umschließenden Objekt zu den
Komponenten-Objekten)
Je nach dem Grad der Kopplung unterscheidet man :
▻ einfache Aggregation
Das umschließende Objekt und die Komponenten sind nicht existenzabhängig
Eine Komponente kann zusätzlich noch weiteren umschließenden Objekten der gleichen oder einer
anderen Klasse zugeordnet sein.
Bei Löschung des umfassenden Objekts bleiben die Komponenten unabhängig davon erhalten.
Beispiel : Objekt wird vom umfassenden Objekt erzeugt, Referenz darauf wird anderem Objekt übergeben
▻ echte Aggregation (Komposition, composite aggregation)
Die Komponenten können nur einem umfassenden Objekt zugeordnet sein und nur innerhalb diesem
existieren. Bei Löschung des Aggregats werden auch die Komponenten gelöscht.
Beispiel : Objekt wird von umfassenden Objekt erzeugt und nur dort verwendet
◇ Anmerkung :
In der Praxis kann es im Einzelfall sehr schwierig sein, zwischen Assoziation und Aggregation und den
verschiedenen Formen der Aggregation zu unterscheiden.
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/05/2 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenbeziehungen (2)
• Klassendiagramm
◇ Die (statischen) Beziehungen (Vererbungsbeziehungen und Nutzungsbeziehungen) zwischen den in einem
OOP-System zusammenwirkenden Klassen lassen sich durch Klassendiagramme beschreiben.
◇ Ein Klassendiagramm ist eines der in der UML (Unified Modelling Language) zusammengefassten graphischen Darstellungsmittel.
Es ermöglicht die Erstellung eines detaillierten statisches Systemmodells
◇ Zur Erhöhung der Übersichtlichkeit kann die Gesamtheit der Klassen eines Systems auf mehrere
Teildiagramme aufgeteilt sein
• Anmerkung :
◇ Die dynamischen Beziehungen zwischen den Objekten eines OOP-Systems werden durch Sequenzdiagramme, einer anderen Diagrammart der UML, beschrieben. Sie werden hier nicht weiter betrachtet.
• Elemente eines Klassendiagramms
Klassenname
KlasseA
Datenkomponenten
1
*
KlasseB
Funktionskomponenten
Klasse
Assoziation (bidirektional)
KlasseA
KlasseA
1
n
KlasseB
Assoziation (unidirektional)
KlasseB
KlasseA
Vererbung
KlasseB
1
1
KlasseB
(einfache) Aggregation
KlasseA
KlasseB
KlasseB
Komposition (echte Aggregation)
Implementierung
HOCHSCHULE MUENCHEN
FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK
FG TECHNISCHE INFORMATIK
V – PR–JV – 10/05/3 – TH – 01
------------------------------------------------------------------------------------------------------------------------------------------------------------
Klassenbeziehungen (3)
• Beispiele für einfache Klassendiagramme
Person
1..*
Manager
Projekt
*
Entwickler
2..n
*
*
1
Projektleiter
1
1
Firma
1
Auftraggeber
TextFilterCtrl
1
TextFileWriter
TextFileReader
1
1
1
CharFilter
Herunterladen