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