Java 8 Programmiermethodik Eva Zangerle, Nikolaus Krismer Universität Innsbruck Überblick Einführung Java – Ein erster Überblick Objektorientierung Vererbung und Polymorphismus Ausnahmebehandlung Pakete und Javadoc Spezielle Themen Generische Programmierung Java Collection-Framework Streams Unit-Tests Entwurfsmuster - Eine Einführung GUI-Programmierung Java Virtual Machine Ausblick Programmiermethodik - Java 8 Java 8 2 Java 8 (1) • Java 8 wurde von Oracle am 18. März 2014 veröffentlicht • Damit wurden einige Features umgesetzt, welche ursprünglich schon für Java 7 geplant waren (etwa Lambdas) • Neben Bugfixes wurden weitreichende Änderungen an der Java-Syntax vorgenommen • Seit JDK 1.5 ist Java8 das wohl umfangreichste Release Hier werden nur die wichtigsten Änderungen/Erweiterungen aufgeführt Programmiermethodik - Java 8 3 Java 8 (2) • Neu in Java 8 Lambdas Default Methoden Streams Optional Type Annotations Repeating Annotations • Änderungen mit Java 8 Nashorn (ersetzt Rhino) Date & Time APIs JavaFX Metaspace (Garbage Collection) Programmiermethodik - Java 8 4 Neu in Java 8 Lambdas (1) • Bekannt als „Project Lambda“ • Hauptfeature von Java 8 • Dient vor allem der Vereinfachung des Programmcodes etwa beim Sortieren von Collections • Lambdas sind „objektlose Methoden“ • Syntax: „parameters -> body“ • Weitere Information unter http://openjdk.java.net/projects/lambda/ Programmiermethodik - Java 8 6 Lambdas (2) • Beispiele: (String s1, String s2) -> {return s2.length() - s1.length();} (String str) -> System.out.println(str) • Parameter-Typ-Deklaration ist optional; bei einem einzigen Parameter auch die Klammerung: str -> System.out.println(str) () -> System.out.println(this) • Bei Verwendung eines einzigen Statements im Body, kann die Block-Definition und return weggelassen werden: (s1, s2) -> s2.length() - s1.length() Programmiermethodik - Java 8 7 Lambdas (3) • Scopes: import static java.lang.System.out; public class HelloWorld { Runnable r1 = () -> out.println(this); Runnable r2 = () -> out.println(toString()); public String toString() { return "Hello, world!"; } public static void main(String[] args) { new HelloWorld().r1.run(); // Hello, world! new HelloWorld().r2.run(); // Hello, world! } } Programmiermethodik - Java 8 8 Lambdas (4) • Scopes: { // ... String sql = “DELETE * FROM user"; getHibernateTemplate().execute(session -> session.createSQLQuery(sql).uniqueResult()); // ... } Programmiermethodik - Java 8 9 Lambdas (5) • Durch die Einführung von Lambdas werden MethodenReferenzen möglich. Diese sind definiert für: Statische Methoden Instanz-Methoden Methoden einer bestimmten Instanz Konstruktoren (etwa TreeSet::new) • Methoden-Referenzen werden mit Hilfe von „::“ angegeben • Beispiel (mit java.nio.file.Files.lines): Files.lines(Paths.get("Nio.java")).map(String::trim) .forEach(System.out::println); • Weitere Informationen: http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html Programmiermethodik - Java 8 10 Lambdas (6) • Als weitere Erweiterung der Lambdas gibt es in Java 8 so genannte „Functional Interfaces“. • Das sind Interfaces, welche genau eine (abstrakte) Methode beinhalten (Ausnahme sind geerbte Methoden von Objekt sein – also etwa toString()) • Solche Interfaces können mit Lambdas einfach verwendet werden (siehe Beispiel) • Die Annotation „@FunctionalInterface“ kann auf solchen Interfaces verwendet werden, um CompilerFehlermeldungen zu erhalten Programmiermethodik - Java 8 11 Lambdas (7) • Beispiel: public class SimpleFuncInterfaceTest { public static void carryOutWork(SimpleFuncInterface sfi) { sfi.doWork(); } public static void main(String[] args) { carryOutWork(new SimpleFuncInterface() { @Override public void doWork() { System.out.println("Use anonymous inner class..."); } }); carryOutWork(() -> System.out.println("Use lambdaExp..")); } } Programmiermethodik - Java 8 12 Default Methoden (1) • Default Methoden sind Teile von Interfaces, welche eine Implementierung beinhalten • Neben Default-Methoden, können auch static Methoden ausprogrammiert werden • Der Hauptunterschied zu abstrakten Klassen ist darin zu sehen, dass es große Unterschiede bei der Vererbung gibt (eine Klasse kann mehrere Interfaces implementieren) • Es kommt zu einem Compiler-Fehler, wenn eine Subklasse zwei Interfaces implementiert, welche Default Methoden mit gleichem Namen beinhalten (siehe nächstes Beispiel) Programmiermethodik - Java 8 13 Default Methoden (2) • Beispiel: public interface A { default void foo() { System.out.println("Calling A.foo()"); } } public interface B { default void foo() { System.out.println("Calling B.foo()"); } } public class MySubclass implements A, B { // führt zu Compiler-Fehler } Programmiermethodik - Java 8 14 Default Methoden (3) • Beispiel: public interface A { default void foo() { System.out.println("Calling A.foo()"); } } public interface B { default void foo() { System.out.println("Calling B.foo()"); } } public class MySubclass implements A, B { default void foo() { A.super.foo(); // OK (jede Implementierung ist ok) } } Programmiermethodik - Java 8 15 Streams (1) • Mit Java5 wurde eine neue for-Schleife eingeführt List<String> myList = Arrays.asList("e0", "e1", ..., "e999"); for (String e: myList) { System.out.println(e); } • Diese forEach-Schleife hat den Nachteil, dass die Elemente nicht parallel, sondern sequentiell abgearbeitet werden (man müsste zuerst händisch das Array in Teile zerlegen und diese dann parallel abarbeiten) • Aus diesem Grund gibt es in Java 8 Streams und eine weitere forEach Schleife (das Interface Iterable wurde um eine default Methode „forEach“ erweitert) Programmiermethodik - Java 8 16 Streams (2) • Streams können auch ohne forEach verwendet werden. Dazu gibt es etwa die Collections.stream, Arrays.stream oder die Collections.parallelStream – Methoden • Streams wurden für viele Anwendungen definiert: Für das Arbeiten mit Dateien und Verzeichnissen (etwa mit Files.lines) Patterns (bei RegularExpressions) können gestreamt werden Die Klasse Stream kann für beliebige Typen verwendet werden (mit Hilfe der Methode Stream.of()) Unendliche Streams sind definiert (Stream.iterate(i, i -> i+1)) Programmiermethodik - Java 8 17 Streams (3) • Map/Filter/Reduce – Verfahren können nun einfach umgesetzt werden • Beispiel: PlayerPoints highestPlayer = names.stream() .map(name -> new PlayerPoints(name, getPoints(name))) .reduce(new PlayerPoints("", 0.0), (s1, s2) -> (s1.points > s2.points) ? s1 : s2 ); Programmiermethodik - Java 8 18 Optional (1) • Optional wurde als neue Klasse eingeführt, um NullPointerExceptions vorzubeugen • Beispiel (ohne Optional): String version = computer.getSoundcard().getUSB().getVersion(); • Alternative (??): String version = "UNKNOWN"; if(computer != null) { Soundcard soundcard = computer.getSoundcard(); if(soundcard != null) { USB usb = soundcard.getUSB(); if(usb != null) { version = usb.getVersion(); } } } Programmiermethodik - Java 8 19 Optional (2) • Optional.of() kann als Wrapper um einen Wert verwendet werden, um null zu vermeiden • Optional.isPresent() kann für bisherige Prüfungen verwendet werden • Optional.ifPresent(Consumer) wird verwendet, um eine Aktion durchzuführen, wenn Werte gesetzt sind: optionalSoundcard.map(Soundcard::getUSB) .filter(usb -> "3.0".equals(usb.getVersion()) .ifPresent(() -> System.out.println("ok")); Programmiermethodik - Java 8 20 Optional (3) • Weitere Vereinfachungen sind möglich (etwa mit Hilfe von flatMap(), was im Unterschied zu map() die doppelte Verwendung von Optional verhindert): final String version = computer .flatMap(Computer::getSoundcard) .flatMap(Soundcard::getUSB) .map(USB::getVersion) .orElse("UNKNOWN"); • Weitere Informationen: http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html Programmiermethodik - Java 8 21 Type Annotations • Type Annotations sind Annotationen, welche überall dort verwendet werden können, wo ansonsten Typen stehen. • Gedacht sind Type Annotations, um eine bessere Validierung zu ermöglichen (dafür gibt es etwa Frameworks, welche die Überprüfung übernehmen) • Beispiel: final String myString = (@NonNull String) str; Programmiermethodik - Java 8 22 Repeating Annotations • Mit Type Annotations wurden auch Repeating Annotations eingeführt. Damit kann ab Java8 kann die selbe Annotation mehrfach für eine Methode/Typ/Klasse verwendet werden • Bei selbst definierten Annotationen verwendet man dafür @Repeatable • Beispiel: @Schedule(dayOfWeek = “Friday") @Schedule(dayOfMonth = “last”) public void doPeriodicCleanup() { ... } • Weitere Informationen: http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html Programmiermethodik - Java 8 23 Änderungen mit Java 8 Nashorn (1) • Nashorn ersetzt Rhino als JavaScript-Interpreter. Damit wird es möglich JavaScript Code auf der JVM auszuführen • Nashorn verwendet invokedynamic und ermöglicht damit eine bessere Performance • Das Kommandozeilentool „jjs“ wurde in Java 8 eingeführt und ruft die Nashorn-Engine auf • Die Verwendung ist auch direkt im Java – Code möglich (siehe Beispiel) Programmiermethodik - Java 8 25 Nashorn (2) • Beispiel: import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; //… ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); //… engine.eval("function myPrint(s) { print(s); }"); engine.eval("myPrint('Hello Nashorn');"); Programmiermethodik - Java 8 26 Nashorn (3) • Beispiel (mit invokeFunction): import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; //… ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); //… Invocable inv = (Invocable) engine; engine.eval("function myPrint(s) { print(s); }"); inv.invokeFunction("myPrint", "Hello Nashorn2"); Programmiermethodik - Java 8 27 Nashorn (4) • Neben dem Ausführen von JavaScript Code ist auch das „Vermischen“ von Java und JavaScript möglich. Mit Nashorn ausgeführter JavaScript-Code kann auf Java-Klassen zugreifen: var imports = new JavaImporter(java.util, java.io, java.nio.file); with (imports) { var paths = new LinkedList(); print(paths instanceof LinkedList); // true paths.add(Paths.get("file1")); paths.add(Paths.get("file2")); paths.add(Paths.get("file3")); print(paths) // [file1, file2, file3] } Programmiermethodik - Java 8 28 Nashorn (5) • Weiterführende Integration zwischen JavaScript und Java ist möglich: Subklassen können in JavaScript erstellt werden, bei denen die Superklasse in Java implementiert ist • Weitere Informationen: http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html Programmiermethodik - Java 8 29 Date & Time API • Als ein Nachteil von Java kann die komplexe Arbeitsweise mit Datums- und Zeitfunktionen angesehen werden (etwa ist SimpleDateFormat nicht thread-safe) • Deshalb wurde eine neue API eingeführt, welche an die Library „Yoda Time“ angelehnt ist. • Für Datums- und Zeitoperationen können nun neue Klassen verwendet werden: LocalDate – Datum (also Tag, Monat, Jahr) LocalTime – Zeit (innerhalb eines Tages) LocalDateTime – Datum und Zeit Programmiermethodik - Java 8 30 JavaFX (1) • Für grafische Oberflächen sollte kein Swing mehr verwendet werden (AWT ist sogar schon länger als „deprecated“ eingestuft) • Ab Java8 finden sich alle benötigten Teile für JavaFX im JRE. Damit ist nun JavaFX8 die empfohlene Methode, grafische (Desktop)Applikationen umzusetzen • JavaFX8 nutzt verstärkt Lambdas und ermöglicht somit eine einfachere Programmierung von GUIs Programmiermethodik - Java 8 31 JavaFX (2) • Das Theme „Modena“ ist nun die Standarteinstellung, womit Oberflächen moderner aussehen als mit JavaFX2 (und/oder Swing, AWT) • Mit Java 8 erhielt JavaFX vollen 3D Support • Weitere Informationen http://www.oracle.com/technetwork/java/javase/overview/javafxoverview-2158620.html Programmiermethodik - Java 8 32 Metaspace • PermGen wurde abgelöst durch den so genannten Metaspace. Der nun verwendete Metaspace wird im nativem Speicher verwaltet. • Die Parameter „XX:PermSize” und “XX:MaxPermSize” sind nicht mehr verfügbar und werden ignoriert • Einstellungen für den Metaspace können vorgenommen werden (etwa ein Größenlimit), sind aber nur in Ausnahmefällen notwendig Programmiermethodik - Java 8 33 Ausblick Ausblick • Java 9 • Mögliche Änderungen Project „Jigsaw“ (ursprünglich für Java 8 geplant) ermöglicht verbesserte Modularisierung ähnlich zu OSGI mehr Information: http://openjdk.java.net/projects/jigsaw/ GPU Beschleunigung Cloud Support API für Money & Currency Programmiermethodik - Java 8 35 Literatur Literatur • [Davis 2014] Adam Davis, What’s new in Java8, 2014 • (Project Lambda) http://openjdk.java.net/projects/lambda/ • (Method References) http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html • (Optional) http://www.oracle.com/technetwork/articles/java/java8-optional2175753.html • (Repeating Annotations) http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html • (Nashorn) http://www.oracle.com/technetwork/articles/java/jf14-nashorn2126515.html • (JavaFX) http://www.oracle.com/technetwork/java/javase/overview/javafx-overview2158620.html • (Project Jigsaw) http://openjdk.java.net/projects/jigsaw/ Programmiermethodik - Java 8 37