Praktische Softwaretechnologie Vorlesung 5 Martin Giese Johann Radon Institute for Computational and Applied Mathematics Österr. Akademie der Wissenschaften Linz PSWT 2006 – 7. November 2006 – p.1/41 Die API Dokumentation API = Application Programming Interface • 166 Packages • 3417 Klassen • >35 000 Methoden und Felder Online Dokumentation (JavaDoc): http://java.sun.com/j2se/1.5.0/docs/api/ Zum Download (44MB): Link „J2SE 5.0 Documentation“ auf http://java.sun.com/javase/downloads/index.jsp PSWT 2006 – 7. November 2006 – p.2/41 Object vertiefen Die 3 wichtigsten Methoden: • toString() • equals() • hashCode() PSWT 2006 – 7. November 2006 – p.3/41 equals(Object) überschreiben Bedingungen an equals: • Die Relation {( x, y) | x.equals(y) == true} auf Referenzen != null ist Äquivalenzrelation • x.equals(null) == false für x!=null • Wert von x.equals(y) kann sich nur ändern wenn sich der Zustand von x oder y ändert. • Auch hashCode() überschreiben! PSWT 2006 – 7. November 2006 – p.4/41 equals(Object) überschreiben (forts.) public class Point { private int x,y; ... public boolean equals(Object o) { if (o instanceof Point) { Point p = (Point)o; return (x == p.x) && (y == p.y); } else { return false; } } } Unterklassen mit mehr Zustand (WeightedPoint) sollten equals(Object) nicht spezifischer machen! ➠ Aufgabe 14 PSWT 2006 – 7. November 2006 – p.5/41 equals(Object) überschreiben (forts.) public class Point { private int x,y; ... public boolean equals(Object o) { if (o instanceof Point) { Point p = (Point)o; return (x == p.x) && (y == p.y); } else { return false; } } public int hashCode() { return 31*x + y; } } PSWT 2006 – 7. November 2006 – p.5/41 Die ‘Wrapper’ Klassen Eine Klasse in java.lang für jeden primitiven Typ: Boolean, Byte, Short, Integer, Long, Character, Float, Double Objekte enthalten unveränderliches Feld vom entspr. Typ Wichtigste Felder/Methoden: • MIN_VALUE, MAX_VALUE • int intValue() etc. • static Integer valueOf(int) • static int parseInt(String) • in Character auch toLower(), toUpper(), etc. PSWT 2006 – 7. November 2006 – p.6/41 Autoboxing Konvertierung zwischen Wrapper primitiven Typen bei Bedarf: void mPrim(int i) {...} void mRef(Integer i) {...} int prim = 42; Integer ref = new Integer(23); Compiler wandelt mPrim(ref) bzw. mRef(42) mPrim(ref.intValue()) bzw. mRef(Integer.valueOf(42)) um in PSWT 2006 – 7. November 2006 – p.7/41 Mehr über Strings Wichtigste Methoden: • char charAt(int index), String substring(...) • boolean startsWith(String start), boolean endsWith(String end) • int indexOf(String str), . . . • String toLowerCase(), String toUpperCase() Zusätzlich viele Methoden char ⇔ Unicode code points PSWT 2006 – 7. November 2006 – p.8/41 StringBuilder String s = ""; for (int i=0; i<100; i++) { s = s + text(i); } PSWT 2006 – 7. November 2006 – p.9/41 StringBuilder String s = ""; for (int i=0; i<100; i++) { s = s + text(i); // 100 neue String Objekte! } PSWT 2006 – 7. November 2006 – p.9/41 StringBuilder String s = ""; for (int i=0; i<100; i++) { s = s + text(i); // 100 neue String Objekte! } Besser: Objekt mit StringBuilder bauen, dann String lesen. StringBuilder sb = new StringBuilder(); for (int i=0; i<100; i++) { sb.append(text(i)); } String s = sb.toString(); PSWT 2006 – 7. November 2006 – p.9/41 StringBuilder String s = ""; for (int i=0; i<100; i++) { s = s + text(i); // 100 neue String Objekte! } Besser: Objekt mit StringBuilder bauen, dann String lesen. StringBuilder sb = new StringBuilder(); for (int i=0; i<100; i++) { sb.append(text(i)); } String s = sb.toString(); Viele Methoden geben this zurück: sb.append("Text Nr.").append(i).append(" ist ").append(text(i)); PSWT 2006 – 7. November 2006 – p.9/41 java.lang.Math Mathematische Standardfunktionen (Siehe JavaDocs) PSWT 2006 – 7. November 2006 – p.10/41 java.math Package java.math enthält Klassen • BigInteger • BigDecimal für Arithmetik mit beliebiger Genauigkeit: BigInteger ist beliebig lange ganze Zahl BigDecimal ist skalierte Zahl m · 10n für int n, variable Genauigkeit PSWT 2006 – 7. November 2006 – p.11/41 Die I/O Klassen 2 Familien von I/O Kanälen: • InputStream und OutputStream für Folgen von Bytes. • Reader und Writer für Text = Folgen von Characters Zusammenhang über java.nio.charset.Charset: • ein Name, "US-ASCII", "UTF-8", "ISO-8859-1", etc. • eine Abb. Folgen von 16-bit char ⇔ Folgen von bytes PSWT 2006 – 7. November 2006 – p.12/41 InputStream Klassen InputStream System.in ByteArrayInputStream FilterInputStream BufferedInputStream FileInputStream ... InflaterInputStream CipherInputStream DataInputStream ... PSWT 2006 – 7. November 2006 – p.13/41 OutputStream Klassen OutputStream ByteArrayIOutputStream FilterInputStream BufferedOutputStream PrintStream FileOutputStream ... DeflaterOutputStream CipherOutputStream DataOutputStream ... System.out, System.err PSWT 2006 – 7. November 2006 – p.14/41 Reader Klassen Reader StringReader CharArrayReader BufferedReader InputStreamReader ... FilterReader FileReader PSWT 2006 – 7. November 2006 – p.15/41 Writer Klassen Writer StringWriter CharArrayWriter BufferedWriter OutputStreamWriter PrintWriter ... FilterWriter FileWriter PSWT 2006 – 7. November 2006 – p.16/41 Ausgabe leicht gemacht • Text auf stdout ausgeben: System.out.println(...); • Text in Datei schreiben: PrintWriter pw = new PrintWriter("blabla.txt"); pw.println(...); pw.close(); • Binärdaten in Datei schreiben: FileOutputStream fos = new FileOutputString("data.bin"); DataOutputStream dos = new DataOutputStream(fos); dos.writeInt(23); dos.writeDouble(12.3); dos.close(); PSWT 2006 – 7. November 2006 – p.17/41 Eingabe leicht gemacht • Text zeilenweise von stdio lesen: InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String line = br.readLine(); • Text zeilenweise aus Datei lesen: FileReader fr = new FileReader("blabla.txt"); BufferedReader br = new BufferedReader(fr); String line = br.readLine(); if (line == null) {...end of file...} br.close(); • Binärdaten aus Datei lesen: FileInputStream fis = new FileInputString("data.bin"); DataInputStream dis = new DataInputStream(fis); int i = dis.readInt(); double d = dis.readDouble(); PSWT 2006 – 7. November 2006 – p.18/41 dis.close(); Generische Typen Interface Stack bisher: interface Stack { void push(String s); String pop(); boolean isEmpty(); } ➠ nur für String Objekte PSWT 2006 – 7. November 2006 – p.19/41 Generische Typen Interface Stack für Objekte: interface Stack { void push(Object s); Object pop(); boolean isEmpty(); } PSWT 2006 – 7. November 2006 – p.19/41 Generische Typen Interface Stack für Objekte: interface Stack { void push(Object s); Object pop(); boolean isEmpty(); } Anwendendung mit Strings: Stack stringStack = new ArrayStack(); stringStack.push("Hallo"); ... String s = (String)(stringStack.pop()); ➠ lästig und fehleranfällig PSWT 2006 – 7. November 2006 – p.19/41 Generische Typen Generisches Interface Stack: interface Stack<E> { void push(E s); E pop(); boolean isEmpty(); } PSWT 2006 – 7. November 2006 – p.19/41 Generische Typen Generisches Interface Stack: interface Stack<E> { void push(E s); E pop(); boolean isEmpty(); } Anwendendung mit Strings: Stack<String> stringStack = new ArrayStack<String>(); stringStack.push("Hallo"); ... String s = stringStack.pop(); PSWT 2006 – 7. November 2006 – p.19/41 Generische Typen Generisches Interface Stack: interface Stack<E> { void push(E s); E pop(); boolean isEmpty(); } Anwendendung mit ints: Stack<Integer> intStack = new ArrayStack<Integer>(); intStack.push(23); // auto-boxing ... int i = intStack.pop(); // auto-unboxing PSWT 2006 – 7. November 2006 – p.19/41 Generische Typen Generisches Interface Stack: interface Stack<E> { void push(E s); E pop(); boolean isEmpty(); } Anwendendung mit ints: Stack<Integer> intStack = new ArrayStack<Integer>(); intStack.push(23); // auto-boxing ... int i = intStack.pop(); // auto-unboxing ➠ Im Java Tutorial vertiefen! PSWT 2006 – 7. November 2006 – p.19/41 Implementierung von Generischen Typen Typ-Parameter nur beim Compilieren bekannt interface Stack<E> { push(E o); E pop(); } ➠ interface Stack { push(Object o); Object pop(); } Daher Einschränkungen: • Keine Konstruktoren oder statischen Methoden auf E oder E[] • o instanceof E, o instanceof Stack<String>, etc. nicht erlaubt • Casts (E) und (E[]) ohne Laufzeitcheck (aber „unchecked“ Warnung vom Compiler) PSWT 2006 – 7. November 2006 – p.20/41 Beispiel für „unchecked“ Cast public class ArrayStack<E> { E[] elements; int top = 0; ArrayStack(int initialSize) { elements = new T[initialSize]; } } ➠ Compilerfehler: „generic array creation“ PSWT 2006 – 7. November 2006 – p.21/41 Beispiel für „unchecked“ Cast public class ArrayStack<E> { E[] elements; int top = 0; ArrayStack(int initialSize) { elements = new Object[initialSize]; } } ➠ Compilerfehler: „incompatible types“ found : java.lang.Object[] required: E[] PSWT 2006 – 7. November 2006 – p.21/41 Beispiel für „unchecked“ Cast public class ArrayStack<E> { E[] elements; int top = 0; ArrayStack(int initialSize) { elements = (E[]) new Object[initialSize]; } } ➠ Compilerwarnung: Note: stack/ArrayStack.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. PSWT 2006 – 7. November 2006 – p.21/41 Beispiel für „unchecked“ Cast public class ArrayStack<E> { E[] elements; int top = 0; ArrayStack(int initialSize) { elements = (E[]) new Object[initialSize]; } } ➠ Compilerwarnung mit -Xlint:unchecked: stack/ArrayStack.java:6: warning: [unchecked] unchecked cast found : java.lang.Object[] required: E[] PSWT 2006 – 7. November 2006 – p.21/41 Das Collection Framework Standardinterfaces und Implementierungen für • Listen von Objekten: java.util.List<E> • Mengen von Objekten: java.util.Set<E> • Abbildungen von Objekten: java.util.Map<K,V> Verwendung von Interfaces und abstrakten Klassen wie Stack! PSWT 2006 – 7. November 2006 – p.22/41 Map Klassen Map AbstractMap SortedMap HashMap TreeMap PSWT 2006 – 7. November 2006 – p.23/41 Verwendung von Map Map<Integer,String> namen = new HashMap<Integer,String>(); namen.put(0656415,"Ghitescu Antonia Luisa"); namen.put(9556261,"Wiesinger Robert"); namen.put(0355296,"Punzengruber Christian"); String n = namen.get(9876543); if (namen.containsKey(1234567)) {...} if (namen.containsValue("Meindl Diana")) {...} Eigene Klassen als Schlüssel verwenden: equals und hashCode implementieren PSWT 2006 – 7. November 2006 – p.24/41 Collection Klassen Collection AbstractCollection List AbstractList Set AbstractSet SortedSet ArrayList LinkedList HashSet TreeSet PSWT 2006 – 7. November 2006 – p.25/41 Utility Klassen • java.util.Arrays • Arrays mit Werten füllen • Arrays sortieren • In sortierten Arrays suchen • java.util.Collections • Listen sortieren • Suchen in Listen • Maximales Element in Collection suchen • ... PSWT 2006 – 7. November 2006 – p.26/41 Comparable Um Objekte sortieren zu können: Interface java.lang.Comparable<T> implementieren mit Methode int compareTo(T o) • < 0 falls this < o • 0 falls this = o • > 0 falls this > o Am besten 0 gdw this.equals(o) ➠ Legt „natürliche“ Ordnung von Objekten fest. PSWT 2006 – 7. November 2006 – p.27/41 Beispiel Comparable Punkte nach x, dann y Koordinate sortieren public class Point implements Comparable<Point> { private int x; private int y; public int compareTo(Point other) { if( this.x == other.x ) { return this.y - other.y; } else { return this.x - other.x; } } } Point[] points = new Point[20]; java.util.Arrays.sort(points); PSWT 2006 – 7. November 2006 – p.28/41 Iteratoren Schleifen über alle Elemente einer Collection: mit Iterator interface Iterator<E> { boolean hasNext(); E next(); } List<Point> l; ... Iterator<Point> it = l.iterator(); while (it.hasNext()) { Point p = it.next(); p.move(1,0); } PSWT 2006 – 7. November 2006 – p.29/41 Iterator Reihenfolge Reihenfolge • Bei List von vorne nach hinten • Bei Set nicht spezifiziert • Bei SortedSet vom kleinsten zum größten gemäß compareTo() PSWT 2006 – 7. November 2006 – p.30/41 Das „foreach“ Statement Iterator sehr häufig: neues Sprachkonstrukt List<Point> l; for(Point p : l) { p.move(1,0); } Geht für alle Collections, und auch für Arrays. PSWT 2006 – 7. November 2006 – p.31/41 Beispiel: Argumente sortieren Wörter von der Kommandozeile ohne Duplikate sortiert ausgeben. public static void main(String[] args) { SortedSet<String> words = new TreeSet<String>(); for (String s : args) { words.add(s); } for (String s : words) { System.out.println(s); } } PSWT 2006 – 7. November 2006 – p.32/41 Effective Java Sehr gutes Buch zu den Feinheiten von Java: Joshua Bloch, Effective JavaTM Programming Language Guide, Addison Wesley, 2001 PSWT 2006 – 7. November 2006 – p.33/41 Aufgabe 10 Vertiefen und Ergänzen des Stoffs durch Lesen in verschiedenen Tutorials: http://java.sun.com/docs/books/tutorial/index.html • Learning the Java Language: Numbers and Strings • Essential Java Classes: Basic I/O • Collections PSWT 2006 – 7. November 2006 – p.34/41 Aufgabe 11 Ein Programm, das • eine Zahl n von der Kommandozeile liest • die Zahl e = 1+ 1 1 + +··· 2! 3! mit n Stellen Genauigkeit berechnet und ausgibt • dazu die Klassen in java.math benutzt > Java E 100 2.7182818284590452353602874713526624977572470936999595749669 676277240766303535475945713821785251664274 PSWT 2006 – 7. November 2006 – p.35/41 Aufgabe 12 Ein Programm, das sukzessive Primzahlen berechnet. Eingabe: Zahl n Ausgabe: Alle Primzahlen unter n Algorithmus: P := {} Für i := 2, . . . , n { Falls kein j ∈ P Teiler von i ist, setze P := P ∪ {i} } P ist das Resultat PSWT 2006 – 7. November 2006 – p.36/41 Aufgabe 13 Ein Programm, das • eine Textdatei zeilenweise einliest • Entweder von System.in • Oder aus einer Datei die auf der Kommandozeile genannt wird • Jede Zeile in Wörter (Folgen von Buchstaben) zerlegt ➠ Character.isLetter(char c) • Eine Tabelle ausgibt wie oft jedes Wort vorgekommen ist. . . • . . . nach absteigender Häufigkeit sortiert. Dabei sollen alle Hashtabellen, sowie Sortieren, etc. von Standardklassen erledigt werden! PSWT 2006 – 7. November 2006 – p.37/41 Aufgabe 13 (Beispiel) > cat test.txt fünf fünf vier fünf vier drei fünf vier drei zwei! +fünf, vier drei zwei eins > java WordCount test.txt fünf 5 vier 4 drei 3 zwei 2 eins 1 PSWT 2006 – 7. November 2006 – p.38/41 Aufgabe 14 Betrachte folgende Klasse. . . public class Point { private int x,y; ... public boolean equals(Object o) { if (o instanceof Point) { Point p = (Point)o; return (x == p.x) && (y == p.y); } else { return false; } } } PSWT 2006 – 7. November 2006 – p.39/41 Aufgabe 14 (forts.) . . . und folgende: public class WeightedPoint extends Point { private int w; ... public boolean equals(Object o) { if (o instanceof WeightedPoint) { WeightedPoint wp = (WeightedPoint)o; return super.equals(wp) && (w == wp.w); } else { return false; } } } • Inwiefern wird der Vertrag von equals gebrochen? • Was könnte man dagegen tun? PSWT 2006 – 7. November 2006 – p.40/41 Aufgabe 15 Eine Erweiterung des Stack Frameworks aus Aufgabe 9: • Statt nur Strings zu stapeln, einen Parameter einführen: public interface Stack<E> { void push(E o); E pop(); ... } • Eine zusätzliche Implementierung LinkedListStack<E> die eine java.util.LinkedList benutzt. • Alle Implementierungen sollen equals und hashCode unterstützen. (Alle Objekte auf Stapel equals? Für hashCode siehe java.util.List) PSWT 2006 – 7. November 2006 – p.41/41