Ausnahmebehandlungen am Beispiel
public interface MyQueue<E>{ public void enqueue(e o); //Einfuegen // throws FullQueueException // in spaeteren Versionen public E dequeue(); //Rueckgabe und Loeschen public int size(); public boolean isempty(); public E front(); //Rueckgabe ohne Loeschen public class FullQueueException extends Exception{ public FullQueueException(){super(); 2
public class CycArrayQueue1<E> implements MyQueue<E>{ public int N; //frei waehlbare Groesse des Arrays private E[] Q; //Array fuer Queue-Inhalt private int f; //erste belegte Zelle private int r; //erste freie Zelle hinter belegtem Teil public CycArrayQueue1(int n){ N = n; f=0; r=0; Q = (E[]) new Object[n]; //Aus Platzgruenden kein Default-Konstruktor //und keine Default-Groesse des Arrays public void enqueue(e o){ Q[r] = o; r= (r+1)%n; // bei Ueberlauf wird keine Exception geworfen public E dequeue(){ E o= Q[f]; f= (f+1)%n; return(o); // bei leerer Queue wird keine Exception geworfen public int size(){return((n+r-f)%n); public boolean isempty() {return( r==f ); ; public E front(){return Q[f]; // bei leerer Queue wird keine Exception geworfen 3
Quelle public class Test1{ public static void main(string[] args){ CycArrayQueue1<String> q = new CycArrayQueue1<String>(4); String s = "erster"; String t = "zweiter"; String u = "spaeterer"; q.enqueue(s); q.enqueue(t); System.out.println(q.dequeue()); for(int i = 0; i < 8; i++){q.enqueue(u); System.out.println(q.dequeue()); 4
public class CycArrayQueue2<E> implements MyQueue<E>{ public int N; //frei waehlbare Groesse des Arrays private E[] Q; //Array fuer Queue-Inhalt private int f; //erste belegte Zelle private int r; //erste freie Zelle hinter belegtem Teil public CycArrayQueue2(int n){ N = n; f=0; r=0; Q = (E[]) new Object[n]; public void enqueue(e o) throws FullQueueException{ Q[r] = o; if( (r+1-f)%n == 0) throw new FullQueueException(); r= (r+1)%n; // bei Ueberlauf wird Exception geworfen public E dequeue(){ E o= Q[f]; f= (f+1)%n; return(o); // bei leerer Queue wird keine Exception geworfen public int size(){return((n+r-f)%n); public boolean isempty() {return( r==f ); ; public E front(){return Q[f]; // bei leerer Queue wird keine Exception geworfen 5
public class Test2{ public static void main(string[] args) throws FullQueueException{ CycArrayQueue2 q = new CycArrayQueue2(4); String s = "erster"; String t = "zweiter"; String u = "spaeterer"; try{q.enqueue(s); catch(fullqueueexception e) { System.out.println("Queue voll, "+ "Eintrag konnte nicht realisiert werden"); try{q.enqueue(t); catch(fullqueueexception e) { System.out.println("Queue voll, "+ "Eintrag konnte nicht realisiert werden"); System.out.println(q.dequeue()); for(int i = 0; i < 8; i++) { try{q.enqueue(u); catch(fullqueueexception e) { System.out.println("Queue voll, "+ "Eintrag konnte nicht realisiert werden"); System.out.println(q.dequeue()); 6
Generics
Quelle Diese Folien basieren auf dem Java-Tutorial Generics von Gilad Bracha http://java.sun.com/docs/books/tutorial/extra/generics/ 8
Motivierendes Beispiel List myintlist = new LinkedList(); myintlist.add(new Integer(42)); Integer x = (Integer) myintlist.iterator().next(); Es muss immer nach Integer gecastet werden, auch wenn der Programmierer weiss, dass myintlist nur Integers enthält 9
Die Lösung: Generics List<Integer> myintlist = new LinkedList<Integer>(); myintlist.add(new Integer(0)); Integer x = myintlist.iterator().next(); Generics sind Klassen- oder Interface Definitionen mit Typparametern Das bedeutet, dass die Informationen über alle Typen einer generischen Klasse (eines generischen Interfaces) erst zur Laufzeit bekannt sind. 10
Beispiele für Generics Auszug aus java.util.list und java.util.iterator Intuition public interface List <E>{ void add(e x); Iterator<E> iterator(); public interface Iterator<E>{ E next(); boolean hasnext(); zur Laufzeit werden alle Vorkommen von E durch den zur Laufzeit angegebenen Typen ersetzt. Hinweis Java lässt nur Referenz- Typen als Typparameter zu. (z.b., kein bool, int, float,...) 11
Konventionen In Java werden Typ-Parameter üblicherweise mit einem einzelnen Grossbuchstaben benannt public interface List <E>{ void add(e x); Iterator<E> iterator(); public interface Iterator<E>{ E next(); boolean hasnext(); 12
Syntax für die Definition eines Typ-Parameters Syntax Typ-Parameter Typ-Parameter: Typ-Variable [Begrenzung] Begrenzung: extends Klassen-Typ [Begrenzungs-Liste] extends Interface-Typ [Begrenzungs-Liste] Begrenzungs-Liste: Weitere-Begrenzung Begrenzungs-Liste Weitere-Begrenzung Weitere-Begrenzung: & Interface-Typ Beispiel T extends S & Comparable 13
Typ-Argument: < Typ-Parameter-Liste > Typ-Parameter-Liste: Typ-Argument Typ-Parameter-Liste, Typ-Argument Typ-Argument: Referenz-Typ Wildcard Wildcard:?? Wildcard-Einschränkung Wildcard-Einschränkung: extends Referenz-Typ super Referenz-Typ Syntax für die Verwendung eines generischen Types Syntax Typ-Argument Beispiel <Vector, Integer,?,? super Comparable> 14
Beispiel Syntax package TypeVarMembers; class C { void mcdefault() { public void mcpublic() { private void mcprivate() { protected void mcprotected() { Something s fishy here interface I { void mi(); class CT extends C implements I {... generische Methode <T extends C & I> void test(t t) { t.mi(); t.mcdefault(); t.mcpublic(); t.mcprivate(); t.mcprotected(); 15
Ein genauerer Blick Was passiert in folgendem Codefragment? List<String> ls = new ArrayList<String>(); List<Object> lo = ls; ist nicht erlaubt, weil lo.add(new Object()); String s = ls.get(0); Sei A Oberklasse von B, das bedeutet nicht, dass L<A> Oberklasse von L<B> ist. Es handelt sich hier also nicht um eine,weiternde Umwandlung einer Referenz. 16
Weitere Beispiele Früher (< Java 1.5) void printcollection(collection c) { Iterator i = c.iterator(); for (k = 0; k < c.size(); k++) { System.out.println(i.next()); Jetzt void printcollection(collection<object> c) { for (Object e : c) { System.out.println(e); Die neue Variante ist viel restriktiver als die alte, da sie nur Collections von Objects zulässt Was ist also ein Obertyp von L<T>? 17
Wie man es richtig macht Die Lösung sind so genannte Wildcards void printcollection(collection<?> c) { for (Object e : c) { System.out.println(e); Wildcards sind Obertypen von allen Typ-Argumenten. Sprechweise collection of unknown 18
Wildcards Auch bei Wildcards wird sichergestellt, dass nicht auf,falschen Typen operiert wird folgendes geht nicht Collection<?> c = new ArrayList<String>(); c.add(new Object()); 19
Wildcards II Aufgabe: eine Liste von Shapes zeichnen public abstract class Shape { public abstract void draw(canvas c); public class Circle extends Shape { private int x, y, radius; public void draw(canvas c) {... public class Rectangle extends Shape { private int x, y, width, height; public void draw(canvas c) {... public class Canvas { public void draw(shape s) { s.draw(this); public void drawall(list<shape> shapes) { for (Shape s: shapes) { s.draw(this); geht, ist aber unglücklich, warum? Kann nur auf eine List<Shape> aufgerufen werden! 20
Die Lösung: Wildcards mit Typ-Spezifizierung Wildcards II public void drawall(list<? extends Shape> shapes) { for (Shape s: shapes) { s.draw(this); aber folgendes geht wiederum nicht public void addrectangle(list<? extends Shape> shapes) { shapes.add(new Rectangle());? extends Shape muss kein Supertyp von Rectangle sein! 21
generische Methoden Auch Methoden können einen generisch sein static void fromarraytocollection(object[] a, Collection<?> c) { for (Object o : a) { c.add(o); So nicht, wissen wir schon static <T> void fromarraytocollection(t[] a, Collection<T> c) { for (T o : a) { c.add(o); Aber so! Der Typ des Arrays und der Collection sind nun gekoppelt 22
Beispiel generische Methoden static <T> void fromarraytocollection(t[] a, Collection<T> c) { for (T o : a) { c.add(o); Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co); String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs); fromarraytocollection(sa, co); Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection<Number> cn = new ArrayList<Number>(); fromarraytocollection(ia, cn); fromarraytocollection(fa, cn); fromarraytocollection(na, cn); fromarraytocollection(na, co); Kann auf jede Collection angewendet werden, deren Typ-Parameter Supertyp des Typ- Parameters des Arrays ist fromarraytocollection(na, cs);!!! 23
und noch ein Beispiel class Pair<T, S> { T fst; S snd; Pair(T f, S s) {fst = f; snd = s; Wollen eine Methode in Seq, die zwei Collections paarweise zusammenfügt public class Seq<T> { T head; Seq<T> tail; Seq() { head = null; tail = null; [13, 42, 4711, 2011] [ Aa, Bb, Cc ] Seq(T head, Seq<T> tail) { this.head = head; this.tail = tail; boolean isempty() { return tail == null; [(13, Aa ), (42, Bb ), (4711, Cc )] 24
und noch ein Beispiel class Pair<T, S> { T fst; S snd; Pair(T f, S s) {fst = f; snd = s; public class Seq<T> { T head; Seq<T> tail; Seq() { head = null; tail = null; Seq(T head, Seq<T> tail) { this.head = head; this.tail = tail; boolean isempty() { return tail == null; Verwendung Lösung public <S> Seq<Pair<T,S>> zipit(seq<s> that) { if (isempty() that.isempty()) return new Seq<Pair<T,S>>(); else { return new Seq<Pair<T,S>>( new Pair<T,S>(head, that.head), tail.zipit(that.tail)); public static void main(string[] args) { Seq<Number> nums = new Seq<Number>(new Integer(1), new Seq<Number>(new Double(1.5), new Seq<Number>())); Seq<String> strs = new Seq<String>("Aa", new Seq<String>("Bb", new Seq<String>())); Seq<Pair<Number, String>> combined = nums.zipit(strs); 25
Besonderheiten: Arrays Java verbietet die Instanziierung (nicht die Definition) von Arrays von Typ-Variablen oder generischen Typen abgesehen von einem ungebundenen Wildcard! konkret: List<String>[] lsa = new List<String>[10]; ist nicht erlaubt 26
Besonderheiten: Arrays Angenommen, dies wäre möglich, dann List<String>[] lsa = new List<String>[10]; Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; fishy, würde aber nicht erkannt werden String s = lsa[1].get(0); ClassCastException 27
Besonderheiten: Arrays ungebundene Wildcards in Arrays List<?>[] lsa = new List<?>[10]; erlaubt Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; String s = (String) lsa[1].get(0); ClassCastException expliziter cast erzwungen 28