Kapitel 1

Werbung
Kapitel 1
STRUKTURIERUNG VON PROGRAMMEN
Techniken der Programmentwicklung
Prof. Dr. Wolfgang Schramm
Übersicht
1
1.
Strukturierung von Programmen
2.
Vererbung
3.
Abstrakte Klassen und Interfaces
4.
Ausnahmebehandlung
5.
Datenströme: die Java io-­Bibliothek
6.
Multithreading
7.
Innere Klassen
8.
Collections
9.
Generics
10. Reflection
Lernziele des Kapitels
2
2
¨
¨
¨
¨
Sichtbarkeit und Lebensdauer
von Variablen verstehen und
unterscheiden.
Nachvollziehen,
dass
Softwarestruktur
organisiert
werden muss und kennenlernen
der Aufteilung in Pakete.
Verstehen des Konzepts des
Information
Hiding
und
Umsetzung in Java.
Grundlagen
für
Datenabstraktion/
Abstrakte
Datentypen kennenlernen.
Inhalt
3
o
Lebensdauer und Sichtbarkeit von Variablen
o
Pakete
¤
Anlegen
¤
Export und Import von Namen
¤
Pakete und Verzeichnisse
o
Information Hiding
o
Datenabstraktion, Abstrakte Datentypen
Variablen
4
o
o
o
o
Variablen dienen dazu, Daten im Hauptspeicher eines
Programms abzulegen und gegebenenfalls zu lesen oder zu
verändern.
Instanzvariablen: werden im Rahmen einer Klassendefinition
definiert und zusammen mit dem Objekt angelegt.
Klassenvariablen: werden ebenfalls im Rahmen einer
Klassendefinition definiert, existieren aber unabhängig von
einem konkreten Objekt.
Lokale Variablen: werden innerhalb einer Methode oder
eines Blocks definiert und existieren nur dort.
Variablen – Lebensdauer und Sichtbarkeit
5
Lokale Variablen
o
Sichtbar von der Stelle ihrer Deklaration bis zum Ende der Methode, in der sie deklariert
wurden. Falls innerhalb eines Blocks lokale Variablen angelegt wurden, sind sie bis zum Ende
des Blocks sichtbar.
o
Lebensdauer beginnt, wenn die zugehörige Deklarationsanweisung ausgeführt wird. Sie
endet mit dem Ende des Methodenaufrufs. Falls innerhalb eines Blocks lokale Variablen
angelegt wurden, endet ihre Lebensdauer mit dem Verlassen des Blocks.
o
Es ist in Java nicht erlaubt, lokale Variablen zu deklarieren, die gleichnamige lokale Variablen
eines weiter außen liegenden Blocks verdecken. Das Verdecken von Klassen-­‐ oder
Instanzvariablen ist dagegen zulässig.
Instanzvariablen
o
Lebensdauer beginnt mit dem Zeitpunkt des Erzeugens einer neuen Instanz einer Klasse. Mit
dem Zerstören des zugehörigen Objektes werden auch alle Instanzvariablen zerstört.
o
Sie sind innerhalb der ganzen Klasse sichtbar, solange sie nicht von gleichnamigen lokalen
Variablen verdeckt werden.
Klassenvariablen
o
leben während der kompletten Laufzeit des Programms. Die Regeln für ihre Sichtbarkeit
entsprechen denen von Instanzvariablen.
Variablen
6
o
o
o
o
Variablen dienen dazu, Daten im Hauptspeicher eines
Programms abzulegen und gegebenenfalls zu lesen oder zu
verändern.
Instanzvariablen: werden im Rahmen einer Klassendefinition
definiert und zusammen mit dem Objekt angelegt.
Klassenvariablen: werden ebenfalls im Rahmen einer
Klassendefinition definiert, existieren aber unabhängig von
einem konkreten Objekt.
Lokale Variablen: werden innerhalb einer Methode oder
eines Blocks definiert und existieren nur dort.
Variablen – Lebensdauer und Sichtbarkeit
7
Lokale Variablen
o
Sichtbar von der Stelle ihrer Deklaration bis zum Ende der Methode, in der sie deklariert
wurden. Falls innerhalb eines Blocks lokale Variablen angelegt wurden, sind sie bis zum Ende
des Blocks sichtbar.
o
Lebensdauer beginnt, wenn die zugehörige Deklarationsanweisung ausgeführt wird. Sie
endet mit dem Ende des Methodenaufrufs. Falls innerhalb eines Blocks lokale Variablen
angelegt wurden, endet ihre Lebensdauer mit dem Verlassen des Blocks.
o
Es ist in Java nicht erlaubt, lokale Variablen zu deklarieren, die gleichnamige lokale Variablen
eines weiter außen liegenden Blocks verdecken. Das Verdecken von Klassen-­‐ oder
Instanzvariablen ist dagegen zulässig.
Instanzvariablen
o
Lebensdauer beginnt mit dem Zeitpunkt des Erzeugens einer neuen Instanz einer Klasse. Mit
dem Zerstören des zugehörigen Objektes werden auch alle Instanzvariablen zerstört.
o
Sie sind innerhalb der ganzen Klasse sichtbar, solange sie nicht von gleichnamigen lokalen
Variablen verdeckt werden.
Klassenvariablen
o
leben während der kompletten Laufzeit des Programms. Die Regeln für ihre Sichtbarkeit
entsprechen denen von Instanzvariablen.
Warum Strukturierung von Software (Programmen)?
8
o
o
o
o
Die einzige Möglichkeit bei großen (aber auch kleinen)
Softwaresystemen die Kontrolle zu behalten à Teilen und
Herrschen (divide et impera).
Die Software selbst und auch das Problem müssen in kleine,
beherrschbare Teile zerlegt werden.
Diese Teile müssen über definierte Schnittstellen miteinander
interagieren.
Diese Zerlegung erfolgt im allgemeinen auf mehreren Ebenen
und mit jeder Ebene wird das Abstraktionsniveau angehoben.
Programmelemente zur Strukturierung von Programmen
9
o
Anweisungen
o
Blöcke
o
Methoden
o
Klassen
o
Pakete
o
Applikationen
o
Applets
o
Java-­‐Archive
Anweisungen / Blöcke
10
o
Anweisungen = elementarste ausführbare Programm-­‐
elemente; alle anderen Elemente bauen darauf auf.
¤
o
Eine Anweisung kann eine Deklaration (z.B. for-­‐ Schleife) enthalten,
einen Ausdruck auswerten oder den Programmablauf steuern.
Block = Kollektion von Anweisungen, die nacheinander
ausgeführt werden.
¤
Ein Block ist selbst eine Anweisung.
Pakete
11
o
o
o
o
Werden nach Architekturgesichtspunkten angelegt.
Strukturieren größere Softwaresysteme.
Enthalten Klassen oder selbst wieder Pakete.
Paket bildet eine Einheit, obwohl seine Klassen über viele
Dateien verstreut sein können.
Pakete
12
o
Sammlung zusammengehöriger Klassen.
o
Jede Klasse in Java ist Bestandteil genau eines Pakets.
o
Schaffen einen eigenen Sichtbarkeitsbereich für Namen.
o
o
o
Paketnamen können aus mehreren Teilen bestehen und beliebig tiefe
Hierarchien ausdrücken.
Der Name einer Methode oder einer Variablen besteht grundsätzlich aus
drei Elementen:
¤
Paketname(n)
¤
Klassen-­‐ oder Objektname
¤
Methoden-­‐ bzw. Variablenname
Beispiel für einen Methodennamen ist java.lang.Math.sqrt.
Anlegen von Paketen
13
o
Paketnamen sind hierarchisch und durch Punkte getrennt.
o
Deklaration:
package packageName; // erste Anweisung in der Quelldatei
à
o
alle in der Datei deklarierten Klassen gehören zum angegebenen Paket.
Ohne explizite Paketangabe ® Klassen der Datei werden
einem namenlosen Standardpaket – dem default Paket –
zugeordnet.
Möglichst nicht
verwenden!!!
Pakete und Sichtbarkeit
14
o
o
Sichtbarkeitsgrenze: alles was zu einem Paket gehört, ist
zunächst einmal lokal zu diesem Paket und in anderen
Paketen unsichtbar.
Klassen können explizit exportiert werden; sie werden
dadurch für andere Klassen sichtbar.
à Gezielte Festlegung von Schnittstellen zwischen Subsystemen.
Export von Namen 1/2
15
o
Was zu einem Paket gehört, ist außerhalb des Pakets unsichtbar.
Beispiel:
package myPackage;
class C1 {
kein Zugriff von außerhalb
int i;
void m () { ... }
}
class C2 {
...
}
®
®
In verschiedenen Paketen können die gleichen Namen verwendet werden.
Namenskonflikte kann es nur innerhalb des „eigenen“ Pakets geben.
Export von Namen 2/2
16
¨
Namen können von einem
à Zugriffsspezifizierer public
Paket
exportiert
Beispiel:
package myPackage;
public class C1 {
// Export von C1
public int i;
// Export von i
public void m (int a) { // Export von m
int b; ... }
public C1() { ... }
// Export des Konstruktors
int j;
void n() { ... }
C1(int i) { ... } // Lokaler Konstruktor
}
class C2 { ... }
¨
Export von: Klassen, Methoden, Feldern und Konstruktoren.
werden:
Qualifizierter Import von Namen
17
o
Exportierte Klassen können in anderen Paketen importiert werden à
qualifizierte Import-­‐Anweisung.
Beispiel:
package otherPackage;
myPackage.C1 obj1; // Import der Klasse C1 aus myPackage
obj1 = new myPackage.C1(); // Erzeugen eines Objekts von C1
obj1.m(4);
// Zugriff auf importierte Methode m
...
myPackage2.C1 obj2; // Import der Klasse C1 aus myPackage2
¤
¤
Durch Angabe des vollständigen Pfadnamens des Pakets, in welchem die Klasse
deklariert ist, vor dem Klassennamen wird diese Klasse importiert.
Der Klassenname wird immer mit dem vorangestellten Paketpfad verwendet.
Expliziter Import von Namen
18
o
Exportierte Klassen können in anderen Paketen importiert werden à
explizite Import-­‐Anweisung.
Beispiel:
package otherPackage;
import myPackage.C1;
C1 obj1;
obj1 = new C1();
obj1.m(4);
...
myPackage2.C1 obj2;
o
o
o
o
o
o
//
//
//
//
//
Import der Klasse C1 aus myPackage
Verwendung der Klasse C1 ohne Qualifikation
Erzeugen eines Objekts von C1
Zugriff auf importierte Methode m
qual.
Import
der
Klasse
C1
aus
myPackage2
Die import-­‐Zeile muss direkt auf die package-­‐Zeile folgen.
Für jede Klasse wird eine import-­‐Zeile benötigt.
Die Klassen in den import-­‐Zeilen müssen mit ihrem Paketnamen qualifiziert werden.
Alle Klassen in import-­‐Zeilen müssen verschiedene Namen haben.
Alle Klassen eines Pakets können mit einer einzigen Zeile importiert werden:
import packagename.*;
Geltungsbereich einer import-­‐Zeile: Datei-­‐ nicht das ganze Paket!
Import statischer Datenelemente und Methoden
19
o
Þ
Seit Java 5 mit spezieller import-­‐Anweisung.
Man kann statische Variablen oder Methoden anderer
Klassen ohne Angabe des Klassennamens verwenden.
Syntax: import static <Qualifier>.<Name>
Beispiel: Import aller statischen Elemente der Klasse Math
import static java.lang.Math.*
class Sample {
void foo() {
...
double x = sin(PI);
// sin, PI, sqrt und E sind aus Math
double y = sqrt(E);
//
können
ohne
// benutzt werden
Qualifizierung
Organisation von Paketen 1/2
20
o
Abbildung: Klassen ® Dateien und Pakete ® Verzeichnisse
mit folgenden Regeln:
¤
¤
Eine public Klasse C muss in einer Datei namens C.java implementiert
werden.
Alle Klassendateien (.class) eines Pakets p müssen in einem Verzeichnis
namens p liegen.
¤
Die Quellecode-­‐Dateien (.java) sollten genauso organisiert sein.
¤
Beispiel: Paket p enthält Klassen A, B und C.
p
A.java
B.java
C.java
IDEs (z.B. Eclipse)
erledigen das für
Sie.
Organisation von Paketen 2/2
21
¨
¨
Zusammenfassung von Paketen zu größeren Paketen ist möglich.
¤
Pakethierarchie/ Hierarchie von Subsystemen
¤
Pakethierarchie wird auf die Verzeichnisstruktur übertragen.
Beispiel: Paket p1 enthält Klassen A und B, Paket p2 enthält Klassen C und D. Die Pakete p1 und
p2 werden zu einem neuen Paket p zusammengefasst.
p
package p.p1;
p1
public class A;
A.java
B.java
....
import p.p1.A; // Import von A
// Angabe des gesamten Paketpfads
import p.p1.*;
// Import aller Klassen des Pfads
p2
C.java
D.java
import p.*; // Vorsicht
// Import aller Klassen von p
Pakete der Java-­‐Bibliothek
22
o
o
o
Die wichtigsten Klassen (Standardklassen) z.B. Object, String
à java.lang.
Alle Klassen des Pakets java.lang werden automatisch
importiert.
Weitere wichtige Pakete des JDK:
java.io
Paket zum Lesen und Schreiben von Datenströmen (Dateien,
Bildschirmausgabe, Tastatureingabe).
java.util
Paket mit nützlichen Hilfsklassen (z.B. Random, Date)
java.swing
Paket für grafische Benutzeroberflächenelemente (Knöpfe,
Textfelder, Fenster).
Eindeutige Paketnamen
24
o
Vermeidung
Projekten.
¤
¤
o
Namenskollisionen
bei
sehr
großen
Viele Entwickler: jeder vergibt eigene Namen für „seine“ Klassen /
Pakete.
Verwendung einer großen Anzahl unterschiedlicher Klassen-­‐
bibliotheken von verschiedenen Herstellern.
Vergabe von Paketnamen à angelehnt an das domain name
system der Internet-­‐Adressen
¤
o
von
Domain-­‐Namen sind weltweit eindeutig
Paketename = Domain-­‐Namen mit den Namensbestand-­‐
teilen in umgekehrter Reihenfolge.
⇒Namenskollisionen zwischen Paketen unterschiedlicher Hersteller
werden vermieden.
o
Beispiel: diverse Pakete des JDK com.oracle.*
Eine weitere Organisationseinheit: Java Archive
26
o
o
Java Archive (JAR) – Sammlung von (mehreren) Java-­‐Klassen
(und Hilfsdateien) im ZIP-­‐Format gepackt.
Vorteile
¤
Komprimiert à weniger Speicherplatzverbrauch.
¤
Eine einzelne Datei (statt viele) à mehr Ordnung.
¤
¤
¤
Zusammengehörige Klassen à gruppieren.
Kann direkt ausgeführt werden (java −jar <Archivname>.jar).
Können genauso auf den Klassenpfad gelegt werden, wie Verzeichnisse
mit Klassen.
jar -­‐ Vorteile
27
o
o
o
Sicherheit: Man kann den Inhalt digital signieren und so vor
Veränderungen schützen.
Sealing: Man kann festlegen, dass alle Klassen eines Paketes
in einem JAR enthalten sein müssen, d.h. es können keine
Klassen eingeschmuggelt werden.
Versionierung: In den Metadaten der JAR-­‐Datei kann man
Versionsinformationen für die enthaltenen Klassen ablegen.
jar-­‐Dateien erzeugen
28
o
o
o
Programm
jar
erzeugt
*.jar-­‐Dateien:
jar −cvf <archivname>.jar.
Syntax ist ähnlich zum Unix-­‐Kommando tar.
Zusätzlich zu den eingepackten Dateien enthält ein JAR
Metadaten im META−INF-­‐Verzeichnis.
Einbinden von Archiven
29
o
Eigene und fremde JARs können eingebunden werden
¤
¤
in Eclipse in den Projekteigenschaften unter „Java Build Path“ und
Libraries.
auf der Kommandozeile bei Compiler und Java-­‐VM über die Option
−classpath.
Einbinden von jar-­‐Dateien in Eclipse
30
Information Hiding / Datenabstraktion
31
o
o
Wichtiges Prinzip der Softwaretechnik.
Hilft, die Komplexität großer Programm in den Griff zu
bekommen.
Verstecke die Implementierung komplexer Daten in einer Klasse und erlaube den Zugriff ausschließlich über Methoden dieser Klasse.
Es interessiert nur WAS man mit den Daten macht, aber nicht WIE sie implementiert sind.
Probleme des direkten Zugriffs auf Daten
32
o
Beim Zugriff auf eine komplexe Datenstruktur (z.B. Baum,
Graph) muss man sonst die Struktur der Daten genau kennen,
z.B. um Ketten von Referenzen zu durchlaufen, um die
gewünschten Daten zu erhalten.
® Kompliziert und fehleranfällig.
® Unerwünschte enge Kopplung zwischen der Klasse und ihren Klienten.
o
Datenstrukturen, auf die direkt zugegriffen wird, kann man
nur schwer ändern, denn man muss dann auch alle
zugreifenden Programme ändern.
® Wenn die Zugriffe über ein ganzes Programm verteilt sind, ist es schwierig, alle zu
finden.
Alles was man übersieht, führt zu Fehlern.
Datenabstraktion durch eine Klasse
33
Zugriffsmethoden
(Klassenschnittstelle)
Daten
Klasse
Abstrakter Datentyp (ADT)
Vorteile der Datenabstraktion
34
o
o
o
Das Arbeiten mit den Daten wird für Klienten einfacher, weil
sie von den Implementierungsdetails abstrahieren können
und nur mit den Zugriffsmethoden arbeiten.
Die Implementierung der Daten kann jederzeit geändert
werden, ohne dass die Klienten ihre Programme ebenfalls
ändern müssen -­‐ solange die Schnittstelle unverändert bleibt.
Versteckte Daten sind vor mutwilliger oder versehentlicher
Zerstörung durch andere Klassen geschützt
Datenabstraktion in Java
35
o
Erfolgt mittels bestimmter Modifier (auch Zugriffs-­‐ oder
Sichtbarkeitsattribute genannt), welche die Sichtbarkeit von
Datenelementen und Methoden festlegen:
¤
public
private
¤
protected (nur im Zusammenhang mit Vererbung)
¤
ohne Modifier: Standard-­‐Sichtbarkeit oder package scoped
¤
Hinweis:
¤
n
n
Die Modifier beziehen sich auf Datenelemente und Methoden von Klassen.
Klassen selbst haben andere Modifier.
Sichtbarkeitsattribute in Paketen
36
Beispiel
Sichtbarkeit
int i;
Die Namen sind in allen Klassen des deklarierenden Pakets sichtbar.
void m() { ... }
public int i;
public void m() { ... }
protected int i;
protected void m() { ... }
private int i;
private void m() { ... }
Die Namen sind in allen Paketen sichtbar, die die deklarierende Klasse importieren. Ebenso im deklarierenden Paket.
Die Namen sind in allen Unterklassen sowie in allen Klassen des deklarierenden Pakets sichtbar.
Die Namen sind nur in der deklarierenden Klasse sichtbar und sonst nirgendwo.
Sichtbarkeit und Vererbung:
Einschränkungen der Sichtbarkeit
37
o
In Java kann eine Klasse die Sichtbarkeit von Methoden ihrer
Oberklasse(n) nicht einschränken.
o Beispiel:
abstract
public
}
class
GeometrischeFigur
void verschiebe ( ... ) { ...
{
}
class
Kreis
extends
GeometrischeFigur
{
private void verschiebe ( ... ) { ... }
}
private verursacht einen Compiler-­Fehler!
Grund (im Beispiel):
Sonst würde Code, der mit Objekten der Klasse GeometrischeFigur funktioniert hat, mit Kreis-­‐Objekten nicht mehr funktionieren!
Sichtbarkeit und Vererbung:
Erweiterung der Sichtbarkeit
38
o
In Java kann eine Klasse die Sichtbarkeit von Methoden ihrer
Oberklasse(n) (indirekt) erweitern.
o Realisierungs-­‐Idee:
Eine Unterklasse überdeckt eine ererbte Methode durch eine
Methode mit erweiterten Rechten und ruft die ererbte auf (auf die
sie Zugriff hat).
o Beispiel:
class
GeometrischeFigur
{
protected void verschiebe ( ... ) { ... }
}
class
Kreis
extends
GeometrischeFigur
{
public void verschiebe ( ... ) {
super.verschiebe(
...
);
}
}
Ergebnis:
Für Instanzen der Klasse Kreis ist der Code der eingeschränkt
sichtbaren Methode verschiebe() aus der Klasse GeometrischeFigur
nun verfügbar.
o
Noch Fragen ?
39
Herunterladen