4.1 Eigenschaften „aller Objekte“ • allgemeine Eigenschaften aller Objekte in java.lang.Object: Kapitel 4: Datenstrukturen verstehen – Jede Klasse ist implizit Unterklasse von Object (“extends Object”), d.h. man kann “extends Object” weglassen. 4.1 Eigenschaften „aller Objekte“ 4.2 Implementierung von Datenstrukturen 4.3 Algorithmen auf Datenstrukturen Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung – Probleme mit Mehrfachvererbung werden vermieden. – auf alle Objekte anwendbare Methoden erlauben: Objekte zu vergleichen Objekte eindeutig zu identifizieren Objekte zu drucken Zugriff auf Objekte zu synchronisieren (-> später!) K4 - 1 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Eigenschaften aus Klasse „Object“ • Vergleich mit Operation == : – Referenzgleichheit, d.h. physische Identität der Objekte – Typischer Fehler: Stringvergleich mit "==" • Vergleich mit o.equals(): – deklariert in java.lang.Object – redefiniert in vielen Bibliotheksklassen » z.B. in java.lang.String – für selbstdefinierte Klassen » Standardbedeutung „Referenzgleichheit“ » bei Bedarf selbst redefinieren ! • Jede Klasse kann die Standard-Operationen redefinieren: – equals(): Objektgleichheit (Standard: Referenzgleichheit) – hashCode(): Zahlcodierung (bei Verwendung z.B. in HashSet die Operation redefinieren!) – toString(): Textdarstellung, z.B. für println() Objektoiertierte Programmierung K4 - 2 Wann sind Objekte gleich? (1) class Object { public boolean equals (Object obj); public int hashCode(); public String toString(); ... } Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 3 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Wann sind Objekte gleich? (2) Objektoiertierte Programmierung K4 - 4 Wann sind Objekte gleich? (3) public static void main (String[] args) { Artikel tisch = new Artikel("Tisch",200); Artikel stuhl = new Artikel("Stuhl",100); Artikel schrank = new Artikel("Schrank",300); public static void main (String[] args) { Set s = new HashSet(); s.add(new Artikel("Tisch",200)); //ein Artikel s.add(new Artikel("Stuhl",100)); s.add(new Artikel("Schrank",300)); s.add(new Artikel("Tisch",200)); //ein aehnlicher System.out.println(s); } } Systemausgabe: Set w2 = new HashSet(); w2.add(tisch); w2.add(stuhl); w2.add(schrank); w2.add(tisch); // derselbe Artikel!! System.out.println(w1); Systemausgabe: [Tisch(200), Tisch(200), Schrank(300), Stuhl(100)] [Schrank(300), Tisch(200), Stuhl(100)] wenn in „Artikel“ kein „equals()“ definiert ist Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 5 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 1 Objektoiertierte Programmierung K4 - 6 Ordnung auf Elementen: Interface „Comparable“ In „java.lang“: public interface Comparable { public int compareTo (Object o); } Definiert eine feste totale Ordnung auf der Klasse In „java.util“: public interface Comparator { public int compare (Object o1, Object o2); public boolean equals (Object obj); } Resultat kleiner/gleich/größer 0 wenn "this" kleiner/gleich/größer als Objekt "o" • Zu einer Klasse (Elemente einer Datenstruktur?) kann es verschiedene Komparatoren geben, die über compare Das Ergebnis des Objektvergleichs wird also als int angegeben!! Standarddatentypen (z.B. String) implementieren Comparable. verschiedene Ordnungen definieren („<“, „>=“, ...) • Die equals-Methode vergleicht Komparatoren. „lexikographisch kleiner“ Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 7 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Das Interface „Cloneable“ Objektoiertierte Programmierung K4 - 8 Reflection: getClass(), forName(), ... In „java.lang“: public interface Cloneable { // leeres Interface } In „Object“: public Class getClass (); In „Class“: Public static Class forName(String name); Die Klausel • Die Klasse „Class“ bietet die „Reflection“-Möglichkeiten von Java an: class A implements Cloneable sagt dem Java-Compiler, dass in der Klasse A die Methode clone() aus Object verwendet werden darf (also nicht selbstverständlich!). – Auskunft über alle Bestandteile von Klassen: Methoden und Exemplarvariablen, deren Typen und Zugiffsrechte ... – über den „ClassLoader“ die Möglichkeit, zur Laufzeit Klassen nachzuladen. „flache Kopie“ => redefinieren! Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Ganz ähnlich: Das Interface „Comparator“ Objektoiertierte Programmierung K4 - 9 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Erwartete Zusammenhänge Objektoiertierte Programmierung K4 - 10 Das Interface „java.io.Serializable“ public interface Comparable { // leeres Interface } x.clone() != x x.clone().getClass() = = x.getClass() x.clone().equals(x) Die Klausel class A implements Serializable sagt dem Java-Compiler, dass in der Klasse A Serialisierung verwendet werden darf. Durch Serialisierung kann man ganze Objekt-Geflechte bequem in einer Datei speichern und dadurch „persistent“ machen aber alles NICHT zwingend gefordert !! d.h. über einen Programmlauf hinaus erhalten Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 11 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 2 Objektoiertierte Programmierung K4 - 12 Objekt-Serialisierung in Java Objekt-Serialisierung: Abspeichern import java.io.*; • Die Klassen java.io.ObjectOutputStream und java.io.ObjectInputStream stellen Methoden bereit, um ein Geflecht von Objekten linear darzustellen (zu serialisieren) bzw. aus dieser Darstellung zu rekonstruieren. class XClass implements Serializable { private int x; public XClass (int x) { this.x = x; } Datei mit Namen „Xfile.dat“ } class ObjectOutputStream { public ObjectOutputStream (OutputStream out) throws IOException; public void writeObject (Object obj) throws IOException; } XClass xobj; ... FileOutputStream fs = new FileOutputStream("Xfile.dat"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(xobj); • Achtung: „statische“ und „transiente“ Attribute werden nicht mitserialisiert! Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 13 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) class XClass implements Serializable { private int x; public XClass (int x) { this.x = x; } } Datei mit Namen „Xfile.dat“ Abstrakter Datentyp (Schnittstelle) Konkreter Datentyp (Implementierung) • Abstraktion: • Konkretisierung: – Operationen – Verhalten der Operationen • Theorie: zum Lesen öffnen ... FileInputStream fs = new FileInputStream("Xfile.dat"); ObjectInputStream os = new ObjectInputStream(fs); xobj = (XClass) os.readObject(); – Datenstrukturen – Effizienzfragen • Praxis(Java): – Abstrakte Klassen – Interfaces • Beispiel(Java): – List ... deserialisieren und casten! K4 - 15 Ada zum Vergleich? • Beispiel(Java): – LinkedList – ArrayList Objektoiertierte Programmierung K4 - 16 MyCollection.java (1) • Eigene Implementierung einer Klasse des Collection-Frameworks: class MyCollection extends AbstractCollection implements Collection { class MyCollection extends AbstractCollection implements Collection { // „Minimalimplementierung“, s.u. private class Elem { // eingebettete „innere“ Klasse private Object elem; private Elem next; } public Elem (Object elem, Elem next) { this.elem = elem; this.next = next; } // keine weiteren Operationen! • Standard-Gerüste für Implementierung von Kollektionsklassen: java.util.AbstractCollection, java.util.AbstractList,... } • Eigene Kollektion muß mindestens definieren: – add() // falls sie erweiterbar sein soll – size() – iterator() Objektoiertierte Programmierung – Implementierungsalternativen Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Übungshalber: Selbstdefinierte Kollektion Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) • Theorie: • Praxis(Java): Objektoiertierte Programmierung K4 - 14 – Instantiierbare Klassen – Ausführbare Operationen – Algebraische Spezifikationen » Axiomensysteme ... Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung 4.2 Implementierung von Datenstrukturen import java.io.*; XClass xobj; ... und hier wird serialisiert! ... Objekt-Serialisierung: Einlesen ... zum Schreiben öffnen ... ... private Elem start; // Exemplarvariablen ... private Elem end; // ... von MyCollection private int size; ... K4 - 17 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 3 Objektoiertierte Programmierung K4 - 18 MyCollection.java (3) MyCollection.java (2) ... private class MyCollectionIterator implements Iterator { // Fortsetzung von MyCollection public MyCollection() { start = null; end = null; size = 0; } private Elem current; public MyCollectionIterator() { current = start; } public boolean hasNext() { return current != null; } public boolean add (Object o) { Elem e = new Elem(o,null); if (start == null) start = e; if (end != null) end.next = e; end = e; size++; return true; } public Object next() { Object o = current.elem; current = current.next; return o; } } public Iterator iterator() { return new MyCollectionIterator(); } } // Ende von MyCollection public int size() { return size; } ... Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 19 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Standard-Gerüst AbstractCollection(1) // Fortsetzung von AbstractCollection (Ausschnitt) ... public boolean add(Object o) { throw new UnsupportedOperationException(); } abgestützt auf nicht implementiertes „add()“ ... • Minimal zu ergänzen: public Iterator iterator(); public int size(); • Änderbare Kollektionen erfordern zusätzlich: public boolean add(Object o); public boolean addAll(Collection c) { boolean modified = false; Iterator e = c.iterator(); while (e.hasNext()) { if(add(e.next()))modified = true; } return modified; } ... und die abstrakte Methode iterator() ... public abstract class AbstractCollection implements Collection { public abstract Iterator iterator(); public abstract int size(); public boolean isEmpty() {return size() == 0;} ... abgestützt auf abstraktes „size()“ Objektoiertierte Programmierung K4 - 21 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Standard-Gerüst AbstractCollection(3) Objektoiertierte Programmierung Objektoiertierte Programmierung K4 - 22 Implementierungen im Collection-Framework <<interface>> // Fortsetzung von AbstractCollection (Ausschnitt) ... public String toString() { StringBuffer buf = new StringBuffer().append("["); Iterator i = iterator(); boolean hasNext = i.hasNext(); while (hasNext) { Object o = i.next(); buf.append(o = = this ? "(this Collection)" : String.valueOf(o)); hasNext = i.hasNext(); if (hasNext) buf.append(", "); warum nicht } toString()? buf.append("]"); return buf.toString(); } auch abgestützt auf iterator() } Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) K4 - 20 Standard-Gerüst AbstractCollection(2) • Zweck: Implementierung von Collections vereinfachen. Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung Vererbung (extends) Collection <<interface>> List Implementierung (implements) <<interface>> Set <<interface>> SortedSet ArrayList HashSet LinkedList K4 - 23 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 4 TreeSet <<interface>> Map <<interface>> SortedMap HashMap TreeMap Objektoiertierte Programmierung K4 - 24 Konkrete Datenstruktur: ArrayList ... tatsächlich noch etwas komplexer, z.B.: public class ArrayList extends AbstractList implements List, Cloneable, Serializable { <<interface>> Collection <<interface>> List private transient Object elementData[]; private int size; AbstractCollection public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException ("Illegal Capacity: "+ initialCapacity); „Herausfaktorisieren“ gemeinsamer Funktionalität AbstractList AbstractSequentialList this.elementData = new Object[initialCapacity]; } ArrayList .... LinkedList Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) } Objektoiertierte Programmierung K4 - 25 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung Anfügen an ArrayList Konkrete Datenstruktur: LinkedList public boolean add(Object o) { ensureCapacity(size + 1); elementData[size++] = o; return true; public class LinkedList extends AbstractSequentialList implements List, Cloneable, Serializable { private transient Entry header = new Entry(null, null, null); private transient int size = 0; } 0 capacity 0 size capacity public ListIterator listIterator(int index) { return new ListItr(index); size } implementiert als doppelt verkettete Liste .... } o o Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 27 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Vereinheitlicht den Zugriff auf verschiedene Listen ListIterator Objektoiertierte Programmierung K4 - 28 ArrayList oder LinkedList? • Gemessener relativer Aufwand für Operationen auf Listen: (aus Eckel, Thinking in Java) public interface ListIterator extends Iterator { boolean hasNext(); Object next(); K4 - 26 // gibt es auch in Iterator // gibt es auch in Iterator boolean hasPrevious(); Object previous(); Typ Lesen ArrayList LinkedList 110 1980 Iteration 490 220 Einfügen Entfernen 3790 110 8730 110 int nextIndex(); int previousIndex(); • Stärken von ArrayList: void remove(); // gibt es auch in Iterator void set(Object o); void add(Object o); – wahlfreier Zugriff – Iteration • Stärken von LinkedList: } Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) – Iteration – Einfügen und Entfernen irgendwo in der Liste Objektoiertierte Programmierung K4 - 29 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 5 Objektoiertierte Programmierung K4 - 30 java.util.HashSet (Auszug) Prinzip einer Hashfunktion Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung 0 Object public class HashSet implements Set ... { public HashSet (int initialCapacity, float loadFactor); ... public boolean add (Object o); public boolean remove (Object o); public void clear(); public boolean isEmpty(); public boolean contains (Object o); public int size(); public boolean equals (Object o); public int hashCode(); ... public Iterator iterator(); } hashCode(): int o: Object o.hashCode() Direkte Ermittlung einer Speicheradresse (z.B. Feldindex) mit konstantem Zeitaufwand. U.U. Kollisionen => auflösen! capacity K4 - 31 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) java.util.SortedSet (Auszug) java.util.TreeSet public interface SortedSet extends Set { public public public public public public ... public public public ... public public K4 - 32 Balancierter Rot-Schwarz-Baum, vgl. Einführung i.d. Informatik II • java.util.TreeSet: public class TreeSet … implements SortedSet … { … boolean add (Object o); boolean remove (Object o); void clear(); boolean isEmpty(); boolean contains (Object o); int size(); } • Anwendungsbeispiel: class Warengruppe { private Set inhalt; public Warengruppe (…) { … this.inhalt = new TreeSet(); } … } boolean equals (Object o); int hashCode(); Iterator iterator(); Object first(); Object last(); ... } Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung Objektoiertierte Programmierung K4 - 33 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 34 Anwendungsbeispiel mit TreeSet HashSet oder TreeSet? • Systemreaktion: • Gemessener relativer Aufwand für Operationen auf Mengen: (aus Eckel, Thinking in Java) Exception in thread "main" java.lang.ClassCastException: Artikel at java.util.TreeMap.compare(TreeMap.java, Compiled Code) Typ • Modifikation der Klasse „Artikel“: class Artikel implements Comparable { ... public int compareTo (Object o) { return name.compareTo(((Artikel)o).name); } } Objektoiertierte Programmierung Enthalten 7,4 6,6 Iteration 9,5 TreeSet 31,1 18,7 11,8 • Stärken von HashSet: – unsortierte Mengen – Verhalten von Iteration abhängig von reservierter Größe der Tabelle • Stärken von TreeSet: – sortierte Mengen – Verhalten von Iteration abhängig von Anzahl der Elemente hier ist ein Namensvergleich sinnvoll ! Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Einfügen HashSet K4 - 35 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 6 Objektoiertierte Programmierung K4 - 36 4.3 Algorithmen auf Datenstrukturen z.B. „Sortieren“ (aus Collections) public class Collections { eine sogenannte „Utility-Klasse“ ... public static Object max (Collection coll); public static Object min (Collection coll); public static int binarySearch (List list, Object key); public static void reverse (List list); public static void sort (List list) } public static void sort(List list) { // zuerst in ein Array konvertieren: Object a[] = list.toArray(); // dann Sortieralgorithmus aus „Arrays“: Arrays.sort(a); // zum Schluss per ListIterator zurück: ListIterator i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set(a[j]); } • Algorithmen arbeiten mit beliebigen Klassen, die das Collectionbzw. List-Interface implementieren. • Bei manchen Operationen ist Ordnung auf Elementen vorausgesetzt. • Statische Operationen: Aufruf z.B. Collections.sort(...) Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Sortieren in „Arrays“ Objektoiertierte Programmierung } K4 - 37 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) private static int iteratorBinarySearch (List list, Object key) { int low = 0; int high = list.size()-1; ListIterator i = list.listIterator(); while (low <= high) { int mid = (low + high) >> 1; Object midVal = get(i, mid); int cmp = ((Comparable)midVal).compareTo(key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; // key found Verwendung von „Comparable“ } return -(low + 1); // key not found } private static void mergeSort (Object src[], Object dest[],int low, int high) { // Hier als Pseudocode: // Insertion sort on smallest arrays // Recursively sort halves of dest into src // Optimization: If list is already sorted, // just copy from src to dest. // Merge sorted halves (now in src) into dest } „Arrays“ bietet auch Quicksort Objektoiertierte Programmierung K4 - 38 z.B. „Binärsuche“ (aus Collections) auch eine „Utility-Klasse“ public static void sort(Object[] a) { Object aux[] = (Object[])a.clone(); mergeSort(aux, a, 0, a.length); } Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K4 - 39 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 7 Objektoiertierte Programmierung K4 - 40