Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Programmierkurs JavaUE 38GenericsDietrich BolesSeite 1 Programmierkurs Java Dr. Dietrich Boles Teil Objektorientierte Programmierung Unterrichtseinheit.

Ähnliche Präsentationen


Präsentation zum Thema: "Programmierkurs JavaUE 38GenericsDietrich BolesSeite 1 Programmierkurs Java Dr. Dietrich Boles Teil Objektorientierte Programmierung Unterrichtseinheit."—  Präsentation transkript:

1 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 1 Programmierkurs Java Dr. Dietrich Boles Teil Objektorientierte Programmierung Unterrichtseinheit 38 Generics

2 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 2 Gliederung Generics Motivation Generische Klassen Klassendefinition Objekte / Objektvariablen Übersetzung Typ-Kompatibilität Generische JDK-Klassen Iterator Vector Beispiel Typ-Parameter mit Einschränkungen Vererbung Interfaces Arrays Wildcards new static Generische Methoden Motivation Beispiele Zusammenfassung

3 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 3 Motivation / Problem Simulation eines Getränkehandels Quelle: J. Nowak. Fortgeschrittene Programmierung mit Java 5,dpunkt. Gegeben: vielerlei Getränke Gewünscht: typisierte Flaschen, die nur mit Bier, Rotwein oder Weißwein gefüllt werden können Drink Wine WhiteWine RedWine Beer

4 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 4 Motivation / Ausgangslage abstract class Drink { } class Beer extends Drink { private String brewery; public Beer(String brewery) { this.brewery = brewery; } public String getBrewery() { return this.brewery; } public String toString() { return this.getClass().getName() + "[" + this.brewery + "]; } } abstract class Wine extends Drink { private String region; public Wine(String region) { this. region = region; } public String getRegion() { return this.region; } public String toString() { return this.getClass().getName() + "[" + this.region + "]"; } } class WhiteWine extends Wine { public WhiteWine(String region) { super(region); } } class RedWine extends Wine { public RedWine(String region) { super(region); } }

5 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 5 Motivation / erste Lösung class Bottle { private Drink content; public boolean isEmpty() { return this.content == null; } public void fill(Drink content) { this.content = content; } public Drink empty() { Drink content = this.content; this.content = null; return content; }... Bottle beerBottle = new Bottle(); beerBottle.fill(new WhiteWine("Burgunder"));... Beer beer = (Beer)beerBottle.empty();// ClassCastException! Lösung: polymorphe Klasse Probleme: - keine korrekte Lösung - Typ-Unsicherheit

6 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 6 Motivation / zweite Lösung abstract class DrinkBottle {} class BeerBottle extends DrinkBottle { private Beer cont; public void fill(Beer content) { this.cont = content; } public Beer empty() { Beer c=this.cont; this.cont=null; return c; } } abstract class WineBottle extends DrinkBottle {} class WhiteWineBottle extends WineBottle { private WhiteWine cont; public void fill(WhiteWine content) { this.cont = content; } public WhiteWine empty() { WhiteWine c=this.cont; this.cont=null; return c; } } class RedWineBottle extends WineBottle { private RedWine cont; public void fill(RedWine content) { this.cont = content; } public RedWine empty() { RedWine c = this.cont; this.cont = null; return c; } } Lösung:Getränk-spezifische Flaschen Problem:Keine Vererbung, keine wirkliche Polymorphie!

7 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 7 Motivation / dritte Lösung (1) class Bottle { private T content; public boolean isEmpty() { return this.content == null; } public void fill (T content) { this.content = content; } public T empty() { T content = this.content; this.content = null; return content; } Lösung:- Generische (parametrisierte) Klasse - T ist formaler Typ-Parameter (Typ-Variable) der Klasse Bottle

8 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 8 Motivation / dritte Lösung (2) Bottle beerBottle = new Bottle (); Bottle whiteWineBottle = new Bottle (); beerBottle.fill(new Beer("Veltins")); beerBottle.fill(new WhiteWine("Burgunder")); // Fehlermeldung durch Compiler! whiteWineBottle.fill(new WhiteWine("Burgunder")); Beer beer = beerBottle.empty (); System.out.println (beer); WhiteWine whiteWine = whiteWineBottle.empty (); System.out.println (whiteWine); Aktueller Typ-Parameter (Klasse)

9 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 9 Generische Klassen / Klassendefinition class C {... } class D extends T { } class E { T obj; } interface I { public void setze(T1 obj1, T2 obj2); } class F implements I { public T5 liefere() {...} public void setze(T4 obj1, T6 obj2) {... } } T kann im weiteren Klassenkopf und im Klassenrumpf (fast) überall da verwendet werden, wo Klassennamen stehen können

10 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 10 Generische Klassen / Objekte und Objektvariablen class C { public T f(T t) {...} } class A { } class B { } C obj = new C (); C obj2 = new C (); A a = obj.f(new A()); B b = obj2.f(new B()); A a2 = obj.f(new B()); // Fehlermeldung durch Compiler Formaler Typ-Parameter Aktueller Typ-Parameter (Klasse, kein Standarddatentyp) Parametrisierte Klasse / Typ

11 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 11 Generische Klassen / Übersetzung class C { T t; T f(T t) { T t1 = t; this.t = t1; String str = t.toString(); return this.t; } class C { Object t; Object f(Object t) { Object t1 = t; this.t = t1; String str = t.toString(); return this.t; } Compiler Raw-Type + Meta-Informationen! Daher erlaubt: C obj = new C();

12 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 12 Generische Klassen / Typ-Kompatibilität class C {... } class A { } class B { } class D extends A { } C C // C obj = new C (); Fehler C C // C = new C (); Fehler C Object // Object obj = new C (); ok

13 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 13 Generische JDK-Klassen / java.util.Iterator public interface Iterator { public boolean hasNext(); public T next(); } public interface Iterable { // in java.lang public java.util.Iterator iterator(); }

14 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 14 Generische JDK-Klassen / java.util.Vector public class Vector extends java.util.AbstractList implements Iterable,... { public Vector(); public Vector(int initCapacity); public boolean add(T obj); public boolean contains(Object obj); public T elementAt(int index); public T get(int index); public void insertElementAt(T o,int i); public boolean remove(Object obj); public int size(); public java.util.Iterator iterator();... }

15 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 15 Generische JDK-Klassen / Beispiel import java.util.Vector; import java.util.Iterator; public class IteratorBspMitCast { public static void main(String[] args) { Vector speicher = new Vector(); speicher.add(4711); speicher.add(46); speicher.add(33); int summe = 0; Iterator iter = speicher.iterator(); while (iter.hasNext()) { summe += (Integer)iter.next(); } System.out.println(summe); } Cast notwendig! Compiler-Warnung:... uses unsafe operations Raw-Type

16 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 16 Generische JDK-Klassen / Beispiel import java.util.Vector; import java.util.Iterator; public class IteratorBsp { public static void main(String[] args) { Vector speicher = new Vector (); speicher.add(4711); speicher.add(46); speicher.add(33); int summe = 0; Iterator iter = speicher.iterator(); while (iter.hasNext()) { summe += iter.next(); } System.out.println(summe); } Kein Cast notwendig!

17 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 17 Generische JDK-Klassen / Beispiel import java.util.Vector; public class IteratorBspFor { public static void main(String[] args) { Vector speicher = new Vector (); speicher.add(4711); speicher.add(46); speicher.add(33); int summe = 0; for (Integer i : speicher) { summe += i; } System.out.println(summe); } neue for-Schleife

18 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 18 Typ-Parameter mit Einschränkungen Motivationsproblem: Bottle ist keine Getränkeflasche! Lösung: Einschränkung des Typ-Parameters class Bottle { /* wie auf Folie 7 */ } class Petrol { } class Stout extends Beer {... } Bottle drinkBottle = new Bottle (); Bottle beerBottle = new Bottle (); Bottle objectBottle = new Bottle (); // Fehlermeldung durch Compiler Bottle petrolBottle = new Bottle (); // Fehlermeldung durch Compiler Bottle stoutBottle = new Bottle ();

19 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 19 Typ-Parameter mit Einschränkungen / Übersetzung class A { public void doIt() {...} } class C { T t; T f(T t) { T t1 = t; this.t = t1; this.t.doIt(); return this.t; } Compiler class C { A t; A f(A t) { A t1 = t; this.t = t1; this.t.doIt(); return this.t; }

20 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 20 Vererbung class A { } class B { public void f(T t) {... } } class C extends A { } class D extends B { } class E extends B { public void f(A obj) {... } // Überschreiben public void f(Object obj) {... } // Überladen }

21 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 21 Interfaces class A { } class B { } interface I { public void f1(T1 t); public void f2(T2 t); } class C implements I { public void f1(A t) {... } public void f2(B t) {... } } class D implements I, I {... } // Fehler: dasselbe Interface nicht zweimal implementieren

22 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 22 Arrays mit parametrisierten Klassen (1) Motivationsproblem: Klasse für Getränke-spezifische Getränkekästen Problem: Arrays mit parametrisierten Klassen sind nicht erlaubt Lösung: class BottleBox { private Object[] bottles; private int count = 0; public BottleBox(int number) { // this.bottles = new T[number]; nicht erlaubt this.bottles = new Object[number]; } public void add(Bottle bottle) { this.bottles[this.count] = bottle; this.count++; } public Bottle getBottle(int index) { return (Bottle )this.bottles[index]; } Internes sicheres (!) Cast

23 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 23 Arrays mit parametrisierten Klassen (2) BottleBox beerBottleBox = new BottleBox (6); // Bierkasten füllen for (int i = 0; i < 6; i++) { Bottle beerBottle = new Bottle (); beerBottle.fill(new Beer("Jever")); beerBottleBox.add(beerBottle); } Bottle wineBottle = new Bottle (); beerBottleBox.add(wineBottle); // Fehlermeldung... // Bierkasten leeren for (int i = 0; i < 6; i++) { Bottle beerBottle = beerBottleBox.getBottle(i); Beer beer = beerBottle.empty (); System.out.println(beer); }

24 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 24 Wildcards (1) Motivationsproblem: Klasse für Getränkekästen mit beliebigen Flaschen Lösung: Wildcards class BottleBox { private Object[] bottles; private int count = 0; public BottleBox(int number) { this.bottles = new Object[number]; } public void add(Bottle bottle) { this.bottles[this.count] = bottle; this.count++; } public Bottle getBottle(int index) { return (Bottle )this.bottles[index]; }

25 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 25 Wildcards (2) BottleBox box = new BottleBox(6); // Füllen Bottle beerBottle = new Bottle (); beerBottle.fill(new Beer("Veltins")); box.add (beerBottle); Bottle whiteWineBottle = new Bottle (); whiteWineBottle.fill (new WhiteWine("Burgunder")); box.add (whiteWineBottle); // Leeren for (int i = 0; i < 6; i++) { Bottle bottle = box.getBottle (i); Drink drink = bottle.empty (); System.out.println(drink); }

26 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 26 Wildcards (3) class A { } class B { } class C { } C ca = new C (); // ok C cobj = new C (); // Fehler C obj = new C (); // ok, aber möglichst vermeiden C c1 = new C (); // ok C c2 = new C (); // ok ? steht für irgendeinen Typ

27 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 27 Wildcards (4) Motivationsproblem: Klasse für Getränke-spezifische Getränkekästen Problem der Lösung auf Folie 22: BottleBox Lösung: class BottleBox > { private Object[] bottles; private int count = 0; public BottleBox(int number) { this.bottles = new Object[number]; } public void add(T bottle) { this.bottles[this.count] = bottle; this.count++; } public T getBottle(int index) { return (T)this.bottles[index]; } Semantische Ungereimtheit

28 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 28 Wildcards (5) BottleBox > beerBottleBox = new BottleBox >(6); // Bierkasten füllen for (int i = 0; i < 6; i++) { Bottle beerBottle = new Bottle (); beerBottle.fill(new Beer("Jever")); beerBottleBox.add(beerBottle); }... // Bierkasten leeren for (int i = 0; i < 6; i++) { Bottle beerBottle = beerBottleBox.getBottle(i); Beer beer = beerBottle.empty (); System.out.println(beer); }

29 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 29 new class A { } class C { T t = new T(); // Fehlermeldung; Grund: Übersetzung // von T nach Object }

30 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 30 static class A { } Class B { } class C { static T t; // Fehlermeldung static C c; // Fehlermeldung } C ca = new C (); C cb = new C (); Grund: Der Compiler generiert nur eine (!) Klasse. Beide Objekte würden sich die statischen Attribute teilen.

31 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 31 Generische Methoden / Motivation (1) Motivationsproblem: Umfüllen von Flaschen Mögliche Lösung: class BottleTransfuser { void transfuse(Bottle fromBottle, Bottle toBottle) { T drink = fromBottle.empty(); toBottle.fill(drink); } BottleTransfuser beerTransfuser = new BottleTransfuser ();... Problem: beerTransfuser kann nur Bierflaschen umfüllen!

32 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 32 Generische Methoden / Motivation (2) allgemeiner Lösung: Generische Methoden class BottleTransfuser { void transfuse (Bottle fromBottle, Bottle toBottle) { T drink = fromBottle.empty(); toBottle.fill(drink); } BottleTransfuser transfuser = new BottleTransfuser (); Bottle b1 = new Bottle (); b1.fill(new Beer("Jever")); Bottle b2 = new Bottle (); transfuser.transfuse(b1, b2); Bottle b3 = new Bottle (); b3.fill(new WhiteWine("Burgunder")); Bottle b4 = new Bottle (); transfuser.transfuse(b3, b4); transfuser.transfuse(b1, b4); // Fehlermeldung

33 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 33 Generische Methoden / Beispiele (1) class A { public void f() {} } class B extends A { } class C { public void f1(T t) { String str = t.toString(); } public static void f2(T t) { t.f(); } C obj = new C();C.f2(new A()); obj.f1( " Hallo " );C.f2(new B()); obj.f1(4711);C.f2("Hallo"); // Fehlermeldung

34 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 34 Generische Methoden / Beispiele (2) class C { public static void f3(T t1, T t2) { } public static T f4(T t1, T t2) { return Math.random() < 0.5 ? t1 : t2; } C.f3(11, "Hallo"); // Supertyp Object C.f3("Hallo", 11); // Supertyp Object String s2 = C.f4("Hallo", "World"); // Supertyp String String s1 = C.f4(11, "Hallo"); // Fehlermeldung Comparable c1 = C.f4(11, "World"); // Supertyp Comparable Die "T" müssen einen gemeinsamen Supertyp haben

35 Programmierkurs JavaUE 38GenericsDietrich BolesSeite 35 Zusammenfassung Generics: Parametrisierte Klassen Sinn und Zweck: Semantische Korrektheit Vermeidung von Type-Casts Vermeidung von ClassCast-Exceptions


Herunterladen ppt "Programmierkurs JavaUE 38GenericsDietrich BolesSeite 1 Programmierkurs Java Dr. Dietrich Boles Teil Objektorientierte Programmierung Unterrichtseinheit."

Ähnliche Präsentationen


Google-Anzeigen