Java 8 - DBIS Informatik

Werbung
Java 8
Programmiermethodik
Eva Zangerle
Universität Innsbruck
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 Java 8 das wohl umfangreichste Release

Hier werden nur die wichtigsten Änderungen/Erweiterungen
aufgeführt
Programmiermethodik - Java 8
2
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
3
Funktionale Programmierung in Java
Funktionale Programmierung
• Programm wird als Aneinanderreihung von mathematischen
Funktionen repräsentiert
• Daten sind stets unveränderbar
• Frei von Seiteneffekten
• Funktionen können weitere Funktionen übergeben werden
(Code-as-Data)
• Vorteile:


Kürzerer, übersichtlicherer Code
Besser parallelisierbar  Seiteneffekte
Lambdas - Einführung
• Bekannt als „Project Lambda“
• Hauptfeature von Java 8
• Dient vor allem der Vereinfachung des Programmcodes

etwa beim Sortieren von Collections
• Lambdas sind „objektlose Methoden“
• Kommen nur einmal im Code vor
• Angelehnt an funktionale Programmierung (Programme
bestehen nur aus Funktionen, keine Seiteneffekte)
• Funktionen als Parameter
• Anonyme innere Klasse kapselt diese Verhalten
Programmiermethodik - Java 8
6
Lambdas (1)
• Syntax:


parameters -> body
(argument list) -> code
• Beispiele:
(String name, Address address) -> [Implementierung]
(name, adress) -> [Implementierung] Type inference
name -> [Implementierung]
() -> return 42
• Weitere Information unter
http://openjdk.java.net/projects/lambda/
Programmiermethodik – Java 8
7
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
9
Lambdas (3)
• Comparator mit inner class:
Comparator<String> ignoreCaseComparator_old = new
Comparator<String>() {
public int compare(String s1, String s2) {
return (s1.toLowerCase().compareTo(s2.toLowerCase()));
}
};
• Comparator mit Lambda:
Comparator<String> ignoreCaseComparator_new = (String s1,
String s2) -> (s1.toLowerCase().compareTo(s2.toLowerCase()));
Programmiermethodik – Java 8
10
Lambdas (4)
public class RunnableTest {
public static void main(String[] args) {
System.out.println("=== RunnableTest ===");
// Anonymous Runnable
Runnable r1 = new Runnable(){
@Override
public void run(){
System.out.println("Hello world one!");
}
};
// Lambda Runnable
Runnable r2 = () -> System.out.println("Hello world two!");
r1.run();
r2.run();
}
}
11
Lambdas (5)
List<Person> list =
list.add(new
list.add(new
list.add(new
new ArrayList<Person>();
Person("max", "mustermann", 20));
Person("jane", "doe", 44));
Person("john", "doe", 55));
Collections.sort(list,
(Person p1, Person p2) ->
p1.getLastName().compareTo(p2.getLastName()));
list.forEach(x -> x.increaseAge());
Programmiermethodik – Java 8
12
Methoden-Referenzen
• 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
Programmiermethodik - Java 8
13
Methoden-Referenzen
• Beispiel (statt list.forEach(x -> x.increaseAge()):
list.forEach(Person::increaseAge);
• Ausgabe aller Listenelemente:
list.forEach(System.out::println)
• Verschachteltes Beispiel (mit java.nio.file.Files.lines (NonBlocking IO)):
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
14
Functional Interfaces (1)
• 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())
• Auch Single Abstract Method interfaces (SAM) genannt
• Beispiele: Callable, Comparator, Runnable
Programmiermethodik - Java 8
15
Functional Interfaces (2)
• Lambdas können stets nur eine Methode definieren -> durch
Functional interfaces kann sichergestellt werden, dass
Lambdas verwendet werden können.
• Die Annotation „@FunctionalInterface“ kann auf solchen
Interfaces verwendet werden, um CompilerFehlermeldungen zu erhalten.
Programmiermethodik – Java 8
16
Functional Interfaces (2)
@FunctionalInterface
public interface Displayable {
public display();
}
public class DisplayableImplementation {
public static void main(String[] args) {
Displayable disp_anonymous = new Displayable() {
@Override
public void display() {
System.out.println("anonymous inner class");
}
};
disp_anonymous.display();
Displayable disp_lambda =
() -> System.out.println("lambda expression");
}
}
Programmiermethodik - Java 8
17
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
18
Streams (2)
• forEach-Schleife auf Streams basiert auf dem Consumable
functional interface, das die Implementierung einer accept
–Methode verlangt:
• Beispiele mit als Lambda implementiertem accept():


list.forEach(x -> x.increaseAge());
list.forEach(System.out::println)
Programmiermethodik – Java 8
19
Streams (3)
• 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
20
Streams (4)
• Map/Filter/Reduce – Verfahren können nun einfach
umgesetzt werden (und auch parallelisiert werden):
Input-Daten  [Ops]*  [Terminal Op]  Output-Daten
• Methoden, die angewendet werden können (Auszug):
Map
Filter
Aggregationen wie Sum
 …



• Methoden, die am Schluss auf den Stream angewendet
werden können (terminal ops):
forEach
 Reduce

Programmiermethodik - Java 8
21
Streams (4)
List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
if(t.getType() == Transaction.GROCERY){
groceryTransactions.add(t);
}
}
Collections.sort(groceryTransactions, new Comparator(){
public int compare(Transaction t1, Transaction t2){
return t2.getValue().compareTo(t1.getValue());
}
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
transactionsIds.add(t.getId());
}
Beispiel und Grafiken entnommen aus http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams2177646.html
Programmiermethodik – Java 8
22
Streams (4)
List<Integer> transactionsIds =
transactions.stream()
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
Beispiel und Grafiken entnommen aus http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams2177646.html
Programmiermethodik – Java 8
23
Streams (5)
Beispiel und Grafiken entnommen aus http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams2177646.html
Programmiermethodik – Java 8
24
Optional (1)
• Optional wurde als neue Klasse eingeführt, um
NullPointerExceptions vorzubeugen.
• Angelehnt an funktionale Programmiersprachen.
• 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();
}
}
} Beispiel entnommen aus http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Programmiermethodik - Java 8
25
Optional (2)
public class Computer {
private Optional<Soundcard> soundcard;
public Optional<Soundcard> getSoundcard() { ... }
...
}
public class Soundcard {
private Optional<USB> usb;
public Optional<USB> getUSB() { ... }
}
public class USB{
public String getVersion(){ ... }
}
Beispiel entnommen aus http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Programmiermethodik – Java 8
26
Optional (3)
• 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
27
Java 8: Nicht-funktionale Erweiterungen
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
29
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
30
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
31
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; z.B. das Checker Framework).
• Beispiel:
final String myString = (@NonNull String) str;
• Weitere Annotations: @ReadOnly, @NonNegative, Range Checks, etc.
Programmiermethodik - Java 8
32
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 (Cron-like):
@Schedule(dayOfWeek = “Friday")
@Schedule(dayOfMonth = “last”)
public void doPeriodicCleanup() { ... }
• Weitere Informationen:
http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
Programmiermethodik - Java 8
33
Ä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 (3-5 mal).
• 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
35
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
36
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
37
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
38
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
(gilt für Oracle Java, nicht für OpenJDK).
• 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
39
JavaFX (2)
• Das Theme „Modena“ ist nun die Standardeinstellung, 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
40
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
41
Ausblick
Ausblick
• Java 9-Release für Herbst 2016 geplant.
• Vermutete, neue Features:



Project Jigsaw - Modulsystem
Neue HTTP2-Client-API
Kulla:
 jshell als Read-Eval-Print-Loop
 Einfachen Programmcode direkt ausführen
Neuer Garbage-Collector (G1)
 Neue API zur Verwaltung von Betriebssystem-Prozessen
 JSON-API (Parsen von JSON-Streams) (mittlerweile fragwürdig)

Programmiermethodik - Java 8
43
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
45
Herunterladen