Kapitel 18: Java – ein paar Kleinigkeiten zum Schluss Grundlagen der Programmierung 1 Holger Karl Wintersemester 2016/2017 Inhaltsverzeichnis Inhaltsverzeichnis 1 Abbildungsverzeichnis 2 Liste von Definitionen u.ä. 18.1 Überblick . . . . . . . 18.2 Exceptions . . . . . . 18.3 Lambda-Ausdrücke . 18.4 Generizität . . . . . . 18.5 Pakete . . . . . . . . 18.6 Standardpakete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 3 3 4 6 7 9 18.7 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . 11 Abbildungsverzeichnis 18.1 18.2 Beispiel einer UML-Darstellung eines einfachen Paketes mit zwei Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pakete von Paketen; UML-Darstellung . . . . . . . . . . . . . . 7 8 Liste von Definitionen u.ä. 2 18.1. Überblick 18.1 18.1.1 Überblick Was bisher geschah • Java Grundlagen • Die wundersame Welt der Objektorientierung in Java 18.1.2 Dieses Kapitel • Fehlende Kleinigkeiten • Betonung einiger Aspekte der aktuellen Java Version 8 18.2 Exceptions 18.2.1 Exceptions • Java hat einen Exception-Mechanismus sehr ähnlich zu Python – Klassenbasiert; erweiterbar; . . . • Syntax leicht unterschiedlich – Behandlung: try und catch (statt except) – Auslösen: throw statt raise – finally wie final • Beispiel 1 2 3 4 5 6 7 8 9 18.2.2 try { /* Anweisungen */ } catch (OverflowException | UnderflowException e) { /* Anweisungen */ } catch (Exception e) { /* Anweisungen */ } finally { /* Anweisungen */ } Exceptions im Methodenkopf Besonderheit: Eine Methode kann Exceptions aufzählen, die sie nicht selbst behandelt 3 4 Liste von Definitionen u.ä. • Beispiel: Methode zum Datei öffnen kann ein File not found nicht selbst sinnvoll behandeln • Syntax: throws (das s ist wichtig!) als Teil der Signatur 1 2 3 4 5 6 18.2.3 class X { void m () throws ExceptionName1, ExcpetionName2, { /* Anweisungen */ if (...) throw ExceptionName1; } } Nutzung solcher Methoden • Angenommen, wir wollen dieses m in einer anderen Methode m1 nutzen • Dann müssen alle von m (möglicherweise) geworfenen Exceptions entweder – Bei einem Aufruf von m in einem catch behandelt werden oder – m1 muss eine nicht behandelte Exception-Klasse ihrerseits im Methodenkopf als throws deklarieren • Andernfalls: Compiler stellt fest, dass nicht alle Exceptions behandelt werden – Verweigert Übersetzung • Konsequenz: spätestens in main wird alles behandelt – Ausnahme: System-Exceptions wie NullPointer 18.3 18.3.1 Lambda-Ausdrücke Java 8: Lambda-Ausdrücke! • Vor Java 8: Keine Lambda-Ausdrücke – Mit extrem umständlichen Hilfskonstruktionen, z.B. anonyme Klassen, um eine Vergleichsfunktion für Sortieren zu definieren • Seit Java 8: Lambda-Ausdrücke; im Prinzip ähnlich zu Python – Mit anonymem Interface mit einer Methode – Implizit, ohne ausdrückliches Interface 18.3.2 Java 8: Lambda-Ausdrücke – Beispiel mit Interface 18.3. Lambda-Ausdrücke 1 2 3 5 // wir brauchen zunächst ein Interface als Typ // hier: Integer auf Integer abbilden interface meinFunktionstyp {int exec (int x); } 4 5 6 // davon können wir eine Variable bauen: meinFunktionstyp f; 7 8 9 // und an f einen Lambda-Ausdruck zuweisen: f = x -> x * x; 10 11 12 13 // Test - Achtung, man muss die Methode aufrufen! int y = f.exec(5); System.out.println(y); f ==> null f ==> $Lambda$6/327177752@56ef9176 y ==> 25 25 18.3.3 Java 8: Lambda-Ausdruck ohne Interface • Zwei Lambda-Ausdrücke: Vergleich bei Filter, Ausdrucken – Vorsicht, Seiteneffekt! 1 import java.util.stream.Stream; 2 3 4 5 6 7 class Lambda { public static void main (String[] args) { Stream.of(1954, 1974, 1990, 2014).filter(x -> x>1980).forEach(x -> Sys } } -> System.out.println(x)); 1990 2014 Stream • Klasse, um funktionale Ansätze auf Folgen von Daten zu unterstützen • Wichtige Methoden: filter, forEach, findAny, map, of • Siehe Referenz 6 Liste von Definitionen u.ä. 18.3.4 Java 8: Lambda vs. Closures Zitat: A closure is a lambda expression paired with an environment that binds each of its free variables to a value. In Java, lambda expressions will be implemented by means of closures, so the two terms have come to be used interchangeably in the community. Aber nur, weil die Java community den Unterschied nicht versteht! 18.4 Generizität 18.4.1 Generizität • Bisher: Alle Methoden hatten feste Typen • Den gleichen Code immer wieder schreiben, nur weil sich ein Typ ändert? – Sortieralgorithmus für Zahlen, einen anderen für Strings, . . . ? – Sortieren ist immer gleich – nur das Vergleichen und Kopieren unterscheidet sich • Optionen: – Man fällt auf Object zurück (ggf. durch Boxing) * Nachteil: Wie konvertiert man in eigentlichen Typ zurück? (Z.B. Element aus Liste entnommen?) * Nachteil: In eine Liste für Strings können auch Zahlen abgelegt werden – Man erfindet generische Typen 18.4.2 Generische Typen • Idee: Man lässt bei einer Klasse einen Typ als Parameter zu! – Damit eigentlich eine Familie von Klassen definiert! • Beim Instatiieren eines Objekts: Konkreten Typ für den Parameter nennen • Beispiel: allgemeine Klasse für Liste, durch Typ parametriert 1 2 3 4 5 6 7 class Liste<T> { T[] data; void add (T x) { ... }; T remove() {...}; void sort() {... /* Vergleich von T Objekte */ ... } } 18.5. Pakete 8 9 Liste<String> textliste = new Liste<String>(); textliste.add("Hallo"); 10 11 12 // das gibt Fehler: textliste.add(42); 18.5 Pakete 18.5.1 Pakete • Zusammenfassung von Klassen zu größeren Einheiten: Paketen • Zuordnung einer Klasse zu Paket Paketname: – Anweisung package Paketname; im Kopf der .java-Datei der Klasse • Beispiel UML Abbildung 18.1: Beispiel einer UML-Darstellung eines einfachen Paketes mit zwei Klassen 18.5.2 Pakete und Verzeichnisse • Klassen: Dateien – Klasse C in Datei C.java • Pakete: Verzeichnisse! – Klassen eines Paketes P in Verzeichnis P – Beispiel oben: In Verzeichnis graphics die Dateien Circle.java und Rectangle.java 18.5.3 Pakete von Paketen, Verzeichnisse in Verzeichnissen • Pakete zu Paketen zusammenfassen • Dateien liegen in Unterverzeichnissen von Verzeichnissen 18.5.4 Klassen, Pakete - wo gesucht? • Suche beginnt ab aktuellem Verzeichnis 7 8 Liste von Definitionen u.ä. Abbildung 18.2: Pakete von Paketen; UML-Darstellung • Angenommen, static void main ist ein MyApp.java, was Teil des Pakets graphics ist, was Teil des Pakets utilities ist • Dann Übersetzen (javac) bzw. Starten (java) – Ab Verzeichnis oberhalb von Utilities – javac utilities/graphics/MyApp.java – java utilities/graphics/MyApp • Zustätzliche Suche ab Verzeichnissen in Umgebungsvariable CLASSPATH • Eine häufige Fehlerquelle! 18.5.5 Explizites Importieren aus Paketen • Tpyischerweise: Klassen aus Paketen importieren • Anweisung: import – Direkt nach Anweisung package – Folge der Paketnamen und Klassenname! – Durch Punkt getrennt – Fügt Klasse dem Namensraum hinzu • Beispiel: import utilities.graphics.Circles – Dann: Circle c = new Circle() 18.5.6 Implizites Importieren • Klassen auch nutzbar durch Angabe des vollständig qualifizierten Paketnamens – Ohne import • Beispiel: – utilities.graphics.Circle c = new utilities.graphics.Circle() 18.5.7 Sichtbarkeit bzgl. Paketen • Java ist ja bei der Sichtbarkeit von Methoden einer Klasse schon paranoid • Das ist bei Sichtbarkeit von Klassen in Paketen nicht anders – Klassen können mit public etc. versehen werden – Default: Package private – Zugriff nur von innerhalb des Pakets – Siehe auch Stack Overflow Diskussion • Wir präzisieren obige Tabelle: 18.6. Standardpakete 9 – Die beiden Spalten Paket und Unterklasse (gleiches Paket) sind natpürlich gleich; das soll nur Unterschied zu Unterklasse in anderem Paket verdeutlichen Annotation Klasse selbst Paket Ja Ja Ja Unterklasse (gleiches Paket) Ja Ja Ja Unterklasse (anderes Paket) Ja Ja Nein Andere Klasse/von aussen Ja Nein Nein public Ja protectedJa keine An- Ja gabe private Ja Nein Nein Nein Nein Anmerkung: keine Angabe entspricht einer Art package – • Das gibt es aber nicht als Schlüsselwort 18.6 Standardpakete 18.6.1 Standardpakete • java.lang: Standardklassen wie String • java.io: Klassen für Ein-/Ausgabe in Dateien, Tastatur, . . . • java.util: Hilfsklasse wie Random, Date, . . . sowie die das Collection Paket (siehe unten) • javax.swing: Paket für graphische Benutzeroberfläche 18.6.2 Standardpakete: java.util.Collection • Wichtiges Paket für Standard-Datentypen: Listen, Mengen, Dictionaries, ... – Als generische Typen – Samt Iteratoren • Details z.B. Kapitel 23, Mössenböck • Kern: Interface Collection – Von den meisten Klassen dieses Pakets implementiert 18.6.3 Standardpakete: java.util.Collection – Interface Collection • Typische Methoden für alle Collections: 10 Liste von Definitionen u.ä. – – – – – 18.6.4 add remove clear contains size Standardpakete: java.util.Collection – Interface Iterator • Iterator bietet Methoden: – hasNext – next – remove (aus Sammlung entfernen) • Generisch, passend zum Typ der in Collection gespeichert ist 18.6.5 1 Standardpakete: java.util.Collection – Beispiel ArrayList ArrayList<String> liste = new ArrayList<String>(); 2 3 4 liste.add("Hallo"); liste.add("GP1"); 5 6 7 // Mit for iterieren: for (String s: liste) System.out.println(s); 8 9 10 11 // Mit einem expliziten Itertor iterieren: Iterator<String> it = liste.iterator(); while (it.hasNext()) System.out.println(it.next()); liste ==> [] $2 ==> true $3 ==> true Hallo GP1 it ==> java.util.ArrayList$Itr@56ef9176 Hallo GP1 18.6.6 Standardpakete: java.util.Collection – Beispiel FileInputStream • Datenstrom: Abstraktion einer (potentiell unendlichen) Folge von Daten – Ein- oder Ausgabe – Unterschiedlich granular: Bytes, . . . – Unterschiedliche Ziele: Dateien, . . . 18.7. Zusammenfassung • Beispiel: Datei zeichenweise kopieren 1 import java.io.*; 2 3 4 5 6 7 8 9 10 11 12 class CharacterwiseCopying { public static void main (String[] args) throws IOException { Reader r = new FileReader(args[0]); Writer w = new FileWriter(args[1]); int ch = r.read(); while (ch >= 0) { w.write(ch); ch = re.read(); } r.close(); w.closer(); } } 18.7 Zusammenfassung 18.7.1 Zusammenfassung • Mit Java 8 versucht die Sprache, Anschluss an sinnvolle Konzepte zu halten • Für praktische Programmierung wichtige Konzepte vorhanden – Generizität – Eine sinnvolle Sammlung von Standardpaketen • Insgesamt: Java zahlt einen hohen Preis für die statische Typisierung! 11