Programmierkurs Java Java Generics und Java API (1/2) Prof. Dr. Stefan Fischer Institut für Telematik, Universität zu Lübeck https://www.itm.uni-luebeck.de/people/fischer Datenstrukturen • In vielen Sprachen (z.B. C) hat praktisch jedes Programm seine eigenen Datentypen implementiert • Probleme: viel unnötiger Code, Fehlerquelle, schwer auszutauschen, jedes Programm war „einzigartig“ hohe Einarbeitungszeit • Daher: Java stellt Standardtypen bereit – Teil der Java Distribution – Sog. „Java Collections Framework“ (java.util.*) • Referenzen – http://download.oracle.com/javase/tutorial/collections/ – http://download.oracle.com/javase/7/docs/api/ #2 Java Collections Framework (JCF) • Stellt sog. Container-Klassen bereit – Container nehmen andere Datentypen in sich auf – Dynamische Datenstrukturen, die ihre Größe anpassen • Zwei grundlegende Typen: Collection und Map – Collection (java.util.Collection) in dieser Vorlesung • Listen, Mengen, Schlangen (Queues) – Map für Assoziativspeicher (java.util.Map) • Speichert <name, wert>-Tupel #3 Java Collections Framework (JCF) • Interfaces legen den Funktionsumfang eines Containertyps fest – z.B. das Interface Collection • Konkrete Klassen erben von diesen und implementieren die Funktion des Containers – Abstrakte Basisklassen dienen zur vereinfachten Implementierung konkreter Klassen • Beispiel Implementiert Interface „Collection“ Abstrakte Listenimplementierung Konkret, Speicherung in Array #4 Teil der Vererbungshierarchie Collection AbstractList ArrayList ... AbstractSet Vector TreeSet ... HashSet #5 Collection Interface • Wichtige Methoden – – – – – – boolean add(E e); void clear(); boolean contains(Object o); int size(); Iterator iterator(); ... • Was ist wohl ein Iterator? – Später... #6 Interface java.util.Collection #7 Instanziierung einer Collection • Beispiel: Verwendung einer Liste – Zunächst Wahl einer Implementierung – Dann Instanziierung •Collection c = new ArrayList(); #8 Verwendung von Collection import java.util.*; public class NutzungVonCollection { private static void test( Collection c ) { for ( int i = 0; i < 5; i++ ) c.add( i ); System.out.println(“Ist leer? “ + c.isEmpty()); System.out.println( “Anzahl Elemente: “ + c.size()); } } #9 Konzept der Iteratoren • Dient dem Zugriff auf Elemente einer Collection – Im einfachsten Fall kann man nur vorwärts von einem Element zum nächsten gelangen – Iterator iterator = collection.iterator(); • Zwei wesentliche Methoden eines Iterators – boolean hasNext(): true, wenn es ein weiteres Element gibt – Object next(): Liefert nächstes Objekt • Beispiel: Iteration über Collection next() hasNext: true next() hasNext: true 1324 next() hasNext: true 234 next() hasNext: true 333 next() hasNext: true 445 next() hasNext: true 54343 next() hasNext: true 6434 next() hasNext: true 75 hasNext: false 8345 #10 Verwendung von Iteratoren • Vorsicht: nicht 2x next() aufrufen pro 1x hasNext() – z.B. innerhalb der while-Schleife #11 Verwendung von Iteratoren • Oft besser: Referenz auf nächstes Objekt einer Variable zuweisen #12 Kürzere Variante: for-Schleife • Iterationen über Collections lassen sich mit der for-Schleife prägnant und kurz schreiben – Initialisierung: Zuweisung einer Iterator-Referenz – Bedingung: Prüfen auf hasNext(); – Inkrement: Nichts tun #13 Noch kürzere Variante: foreach-Schleife • Seit Java 1.5 gibt es noch eine weitere Schleife – Speziell für die Iteration über Collections, Arrays, etc. – Abkürzende Schreibweise, kann durch for-Schleife ersetzt werden – Möglich für alle Objekte, die das Interface „Iterable“ implementieren – Also z.B. Collection • Syntax: – for(Typ variable : iterableObject ) statement; #14 Das Interface „Iterable“ #15 Foreach und Collections • Beispiel: Umwandlung einer for-Schleife in eine foreach-Schleife #16 Collections und ihre Daten • Beispiel – c.add( new String(“1“) ); c.add( new Integer(42) ); • Collection enthält String- und Integer-Instanzen – add-Methode akzeptiert nur Object-Instanzen – Iterator kann daher nur Object zurückgeben • Beispielhafte Iteration über diese Collection – for(Object o : c) System.out.println(“Länge: “ + ((String)o).length()); • Problem: Typsicherheit – Wie stellt man sicher, dass in einer Collection nur Daten eines bestimmten Typs gespeichert werden können? #17 Wie speichert man Daten? • class IntBox { private int val; } • class StringBox { private String val; void setValue( int val ) { this.val = val; } void setValue( String val ) { this.val = val; } int getValue() { return val; } String getValue() { return val; } } #18 Wie implementiert man „generische“ Typen? • • Häufig durch Speichern von ObjectInstanzen • – Box b = new Box(); Point p = new Point(1,2); class ObjectBox { private Object val; void setValue( Object val ) { this.val = val; } Object getValue() { return val; } } Verwendung b.setValue( p ); ((Point)b.getValue()).getX(); • Probleme – Umständlich • Jeder Zugriff erfordert Typ-Cast – Unsicher • Typ-Cast kann fehlschlagen • ((Vector)b.getValue()).doX(); ClassCastException #19 Lösung: Generische Typen in Java • Sog. Java Generics – Klassen und Methoden können „generisch“ implementiert werden • Statt Object wird ein Platzhalter-Typ verwendet – Alt: private Object val; – Neu: private T val; • Dieser Typ kann wie ein normaler Typ verwendet werden – Bei der konkreten Verwendung muss T spezifiert werden #20 Lösung: Java Generics • class ObjectBox { private Object val; } • class Box<T> { private T val; Sagt Java, dass T im Folgenden ein Platzhalter ist void setValue( Object val ) { this.val = val; } void setValue(T val) { this.val = val; } Object getValue() { return val; } T getValue() { return val; } } #21 Verwendung • Instanziierung – Box<String> stringBox = new Box<String>(); – Box<Integer> intBox = new Box<Integer>(); – Box<Point> pointBox = new Box<Point>(); • Zugriff – Point p = new Point(1,2); pointBox.setValue( p ); double x = pointBox.getValue().getX(); getValue() liefert Point zurück #22 Generics: Einfache generische Methoden • class HopOderTop { public static <T> T aOderB(T a, T b) { if (Math.random() > 0.5) return a; else return b; } } • System.out.println( HopOderTop.aOderB(“Zuhören“, “Weiterschlafen“) ); • System.out.println( “Note: “ + HopOderTop.aOderB( 1.0, 1.3 ) ); #23 Seit Java 1.5 verwendet das JCF Generics • Alt: Collection l = new ArrayList(); • Neu: Collection<String> = new ArrayList<String>(); • Vorteile – Es können keine falschen Datentypen mehr gespeichert werden – Typ-Cast entfällt – Beispiele: nächste Folie #24 Beispiel: Ohne und mit Generics #25