Praktische Softwaretechnologie Vorlesung 4 Martin Giese Johann Radon Institute for Computational and Applied Mathematics Österr. Akademie der Wissenschaften Linz PSWT 2006 31. Oktober 2006 p.1/28
Die Klasse java.lang.object Keine explizit angegebene Oberklasse java.lang.object Alle Klassen erben von Object Object definiert einige Methoden: equals(object o) hashcode() tostring()... Können (sollten) von Unterklassen überschrieben werden. PSWT 2006 31. Oktober 2006 p.2/28
Der final modifier Veränderung von Feldern nach Initialisierung verbieten: private final int x; Auch gut um deutlich zu machen, daß sich der Wert nicht ändert! Auch häufig für statische Konstanten: public static final int MONTHS_PER_YEAR = 12; Methode erlaubt kein Überschreiben: public final void m(...) {... Klasse erlaubt keine Unterklassen: public final class A {... PSWT 2006 31. Oktober 2006 p.3/28
Fehlerbehandlung in C Signalisieren von Fehlerzuständen in C entweder durch Rückgabewerte: c = getc(); if (c == EOF) {... Fehlerbehandlung oder globale Variable errno: if ((fd=fopen("file.txt","r")) == -1) { if (errno==eaccess) {... Fehlerbehandlung... Umständlich, fehleranfällig, lenkt vom Wesentlichen ab Fehlerbehandlung oft vernachlässigt PSWT 2006 31. Oktober 2006 p.4/28
Exceptions Fehlersignalisierung in Java: Exceptions Exceptions sind Objekte aus einer Unterklasse von java.lang.exception Exceptions werden geworfen : throw new java.io.exception(); Exceptions werden gefangen : try {... Hier kann eine Exception geworfen werden... catch (java.io.ioexception e) {... Hier wird Exception e behandelt... throw kann auch innerhalb von aufgerufenen Methoden sein. PSWT 2006 31. Oktober 2006 p.5/28
Abrupte Beendigung Offizieller Sprachgebrauch: Jedes Statement (und jeder Block) kann enden (complete). Ausführen bis zum letzten Statement normales Ende (normal completion) break, continue, return, throw abrupte Terminierung (abrupt completion) Abrupte Terminierung hat immer einen Grund (reason) Beispiel Methodenaufuf: Ausführung von Methodenrumpf endet abrupt auf Grund von return Methodenaufruf endet normal mit entspr. Rückgabewert PSWT 2006 31. Oktober 2006 p.6/28
Abrupte Beendigung (2) Statement throw e endet immer abrupt auf Grund der Exception e Ein Statement in einem Block, if, Schleife endet abrupt wegen Exception e äußeres Statement endet sofort aus dem selben Grund Ein Methodenrumpf endet abrupt wegen Exception e Methodenaufruf endet abrupt aus dem selben Grund D.h.: Eine Exception kann aus mehreren Methodenaufrufen auf einmal zurückspringen. Aufzuhalten nur durch try-catch PSWT 2006 31. Oktober 2006 p.7/28
Try-catch Semantik TC = try {...P1... catch (e Exc) {... P2... P1 endet normal TC endet normal P1 endet abrupt wegen Exception e vom Typ E, Untertyp von Exc P2 wird ausgeführt, TC endet wie P2 P1 endet abrupt aus einem anderen Grund TC endet abrupt aus dem selben Grund PSWT 2006 31. Oktober 2006 p.8/28
Try-catch-finally Semantik TCF = try {...P1... catch (e Exc) {... P2... finally {... P3... Wie try-catch, aber: Es wird auf jeden Fall zuletzt P3 ausgeführt. P3 endet normal TCF endet so wie try-catch ohne finally geendet hätte. P3 endet abrupt TCF endet aus dem selben Grund abrupt. PSWT 2006 31. Oktober 2006 p.9/28
throws Deklaration Exceptions können durch Methoden geworfen werden, müssen aber deklariert werden: public void writedata() throws java.io.ioexception {... Nötig für alle Excepetions die geworfen aber nicht gefangen werden. Ausnahme: manche Exceptions sind unchecked und brauchen nicht deklariert zu werden PSWT 2006 31. Oktober 2006 p.10/28
Die Throwable Hierarchie Object Throwable Error Exception OutOfMemoryError... RuntimeException IOException ParseException IndexOutOfBoundsException ClassCastException... NullPointerException PSWT 2006 31. Oktober 2006 p.11/28
Eigene Exceptions Normalerweise 2 Konstruktoren: public class EmptyStackException extends RuntimeException { public EmptyStackException() { super(); public EmptyStackException(String detail) { super(detail); PSWT 2006 31. Oktober 2006 p.12/28
null Der null Wert ist in jedem Referenztyp enthalten: Point p = null; int[] a = null; String s = null; Zugriff auf Felder und Methodenaufruf für null nicht möglich. NullPointerException zur Laufzeit PSWT 2006 31. Oktober 2006 p.13/28
Casts Cast = Typkonvertierung zwischen primitiven Typen mit unterschiedlicher Laufzeit-Semantik (double)1 == 1.0 (int)1.3 == 1 (int)0x100000001l == 1 PSWT 2006 31. Oktober 2006 p.14/28
Casts Cast = Typkonvertierung zwischen primitiven Typen mit unterschiedlicher Laufzeit-Semantik Zwischen Referenztypen: Point p = new WeightedPoint();... double w = p.weight; // Compilerfehler! WeightedPoint wp = p; // Compilerfehler! PSWT 2006 31. Oktober 2006 p.14/28
Casts Cast = Typkonvertierung zwischen primitiven Typen mit unterschiedlicher Laufzeit-Semantik Zwischen Referenztypen: Point p = new WeightedPoint();... double w = ((WeightedPoint)p).weight; WeightedPoint wp = (WeightedPoint)p; PSWT 2006 31. Oktober 2006 p.14/28
Casts Cast = Typkonvertierung zwischen primitiven Typen mit unterschiedlicher Laufzeit-Semantik Zwischen Referenztypen: Point p = new WeightedPoint();... double w = ((WeightedPoint)p).weight; WeightedPoint wp = (WeightedPoint)p; ändert nur statischen Typ, nicht dynamischen Typ oder Wert wirft ggf. ClassCastException sollte daher i.a. nur nach entsprechendem Test geschehen... PSWT 2006 31. Oktober 2006 p.14/28
instanceof Um dynamischen Typ zur Laufzeit zu testen: p instanceof WeightedPoint true falls dyn. Typ von Wert von p <: WeightedPoint PSWT 2006 31. Oktober 2006 p.15/28
instanceof Um dynamischen Typ zur Laufzeit zu testen: p instanceof WeightedPoint true falls dyn. Typ von Wert von p <: WeightedPoint Typische Anwendung: class Point {... public boolean equals(object o) { if (o instanceof Point) { Point other = (Point)o; return this.x==other.x && this.y == other.y; else { return false; PSWT 2006 31. Oktober 2006 p.15/28
Interfaces public interface Stack { void push(string o); String pop(); void clear(); boolean isempty(); PSWT 2006 31. Oktober 2006 p.16/28
Interfaces public interface Stack { void push(string o); String pop(); void clear(); boolean isempty(); public class BoundedArrayStack implements Stack { public void push(string o) {... public String pop() {... public void clear() {... public boolean isempty() {...... Klasse implementiert Interface wegen Deklaration Vorhandensein von Methoden reicht nicht. PSWT 2006 31. Oktober 2006 p.16/28
Interfaces public interface Stack { void push(string o); String pop(); void clear(); boolean isempty(); public class BoundedArrayStack implements Stack { public void push(string o) {... public String pop() {... public void clear() {... public boolean isempty() {...... public class LinkedListStack implements Stack { public void push(string o) {...... PSWT 2006 31. Oktober 2006 p.16/28
Mehrfachvererbung mit Interfaces public interface Bounded { public int getmaxsize(); PSWT 2006 31. Oktober 2006 p.17/28
Mehrfachvererbung mit Interfaces public interface Bounded { public int getmaxsize(); public class BoundedArrayStack implements Stack, Bounded { public void push(string o) {... public String pop() {... public void clear() {... public boolean isempty() {... public int get getmaxsize() {...... PSWT 2006 31. Oktober 2006 p.17/28
Mehrfachvererbung mit Interfaces public interface Bounded { public int getmaxsize(); public class BoundedArrayStack implements Stack, Bounded { public void push(string o) {... public String pop() {... public void clear() {... public boolean isempty() {... public int get getmaxsize() {...... public interface BoundedStack extends Bounded, Stack { PSWT 2006 31. Oktober 2006 p.17/28
Mehrfachvererbung mit Interfaces public interface Bounded { public int getmaxsize(); public class BoundedArrayStack implements Stack, Bounded { public void push(string o) {... public String pop() {... public void clear() {... public boolean isempty() {... public int get getmaxsize() {...... public interface BoundedStack extends Bounded, Stack { C++: auch mehrfache Implementierungsvererbung komplizierte Regeln PSWT 2006 31. Oktober 2006 p.17/28
Elemente in Interfaces Methodendeklarationen: immer (implizit) public nie static keine Konstruktoren Felder: immer (implizit) public static final, also Konstanten Interfaces können nur andere interfaces erweitern PSWT 2006 31. Oktober 2006 p.18/28
Benutzung von Interfaces public static void fillstack(stack s1) { s1.push("test");... public static void transferstack(stack from, Stack to) { while (!from.isempty()) { to.push(from.pop()) public static void main(string[] args) { Stack s1 = new BoundedArrayStack(10); Stack s2 = new LinkedListStack(); fillstack(s1); System.out.println(s1); transferstack(s1,s2); System.out.println(s2); PSWT 2006 31. Oktober 2006 p.19/28
Abstrakte Klassen Eine Klasse ist abstrakt, wenn sie als solche deklariert ist: public abstract class AbstractStack {... PSWT 2006 31. Oktober 2006 p.20/28
Abstrakte Klassen Eine Klasse ist abstrakt, wenn sie als solche deklariert ist: public abstract class AbstractStack {... eine abstrakte Klasse kann abstrakte Methoden ohne Implementierung enthalten public abstract void push(string s); wird von Unterklasse mit Implementierung überschrieben PSWT 2006 31. Oktober 2006 p.20/28
Abstrakte Klassen Eine Klasse ist abstrakt, wenn sie als solche deklariert ist: public abstract class AbstractStack {... eine abstrakte Klasse kann abstrakte Methoden ohne Implementierung enthalten public abstract void push(string s); wird von Unterklasse mit Implementierung überschrieben kann keine Instanzen haben: new AbstractStack() Compilerfehler! PSWT 2006 31. Oktober 2006 p.20/28
Typische Anwendung von abstrakten Klassen public abstract class AbstractStack implements Stack { public abstract String pop(); public abstract void push(string s); public abstract String isempty(); /** Remove all elements from the stack. * This default implementiation repeatedly calls pop() */ public void clear() { while(!isempty()) { pop(); BoundedStack extends AbstractStack kann clear() erben kann auch effizientere Implementierung angeben. PSWT 2006 31. Oktober 2006 p.21/28
Aufzählungstypen Typen mit einer festen, endlichen Menge von Werten: public class Apfel { public static final int FUJI = 0; public static final int BOSKOP = 1; public static final int GRANNY_SMITH = 2; public class Birne { public static final int WILLIAMS_CHRIST = 0; public static final int ABATE_FETEL = 1; public static final int MOSTBIRNE = 2;... int obstsalat = 2*FUJI/BOSKOP + 1*WILLIAMS_CHRIST PSWT 2006 31. Oktober 2006 p.22/28
Aufzählungstypen Typen mit einer festen, endlichen Menge von Werten: public class Apfel { public static final int FUJI = 0; public static final int BOSKOP = 1; public static final int GRANNY_SMITH = 2; public class Birne { public static final int WILLIAMS_CHRIST = 0; public static final int ABATE_FETEL = 1; public static final int MOSTBIRNE = 2;... int obstsalat = 2*FUJI/BOSKOP + 1*WILLIAMS_CHRIST Keine brauchbare Typisierung Keine Überprüfung auf legale Werte PSWT 2006 31. Oktober 2006 p.22/28
Aufzählungstypen Typen mit einer festen, endlichen Menge von Werten: public enum Apfel { FUJI, BOSKOP, GRANNY_SMITH; PSWT 2006 31. Oktober 2006 p.22/28
Aufzählungstypen Typen mit einer festen, endlichen Menge von Werten: public enum Apfel { FUJI, BOSKOP, GRANNY_SMITH; public String name() { switch(this) { case FUJI: return "Fuji"; break; case BOSKOP: return "Boskop"; break; case GRANNY_SMITH: return "Granny Smith"; break;... "2 Stück" + Apfel.FUJI.name(); PSWT 2006 31. Oktober 2006 p.22/28
Garbage Collection In C: int[] p = malloc(1024 * sizeof(int));... free(p); In Java: int[] p = new int[1024];... Freigabe wenn keine Referenz mehr auf ein Objekt besteht. Gegebenenfalls Variablen mit null überschreiben. Vermeidet viele Probleme mit illegalen Referenzen, Memory leaks. Freigabe von Netwerk-Sockets, Datenbankverbindungen, etc. immer noch manuell. PSWT 2006 31. Oktober 2006 p.23/28
Aufgabe 8 Vertiefen und Ergänzen des Stoffs durch Lesen im Java Tutorial: http://java.sun.com/docs/books/tutorial/java/index.html Interfaces and Inheritance PSWT 2006 31. Oktober 2006 p.24/28
Aufgabe 9 Verbessere deine Stack Implementierungen: Stack Klassen leben in package stack, Tests in package test Mache Stack zu einem Interface mit zusätzlich clear löscht alle Werte auf dem Stack exch tauscht die zwei obersten Werte auf dem Stack aus. peek gibt obersten Wert zurück ohne ihn vom Stack zu löschen Klasse AbstractStack implements Stack läßt push, pop und isempty abstrakt implementiert clear, exch, peek mit den abstrakten Methoden PSWT 2006 31. Oktober 2006 p.25/28
Aufgabe 9 (forts) Bisherige Implementierung nach BoundedStack umbenennen. extends AbstractStack neue Methoden von AbstractStack erben für leeren/vollen Stack Exceptions definieren und werfen In Test auch neue Methoden überprüfen. (Variablen Typ Stack) In Test Fehler (wie pop von leerem Stack) erzeugen und Exceptions überprüfen. PSWT 2006 31. Oktober 2006 p.26/28
Aufgabe 9 (forts) DebugStack mit Delegation statt Vererbung Konstruktor DebugStack(String name, Stack delegate) delegate in privatem Feld merken Alle Operationen an delegate weiterleiten, aber mit Debugging-Ausgaben nicht von AbstractStack erben, sondern neue Methoden auch mit Delegation PSWT 2006 31. Oktober 2006 p.27/28
Aufgabe 9 (forts) Neue Stack Implementierung ArrayStack extends AbstractStack basiert wieder auf array und index Wenn Stack voll, neues, doppelt so großes Array anlegen, Inhalt kopieren Implementierung von clear aus AbstractStack überschreiben mit Impl. die wieder ein kleines Array anlegt. ArrayStack testen DebugStack mit ArrayStack und BoundedStack testen. Erklären warum DebugStack nicht von AbstractStack erben sollte. PSWT 2006 31. Oktober 2006 p.28/28