Java 8: Umfassender Quick-Reference-Guide
Java 8 – Überblick
Java 8 ist ein Major-Feature-Release der Java-Programmiersprache. Die Erstveröffentlichung erfolgte am 18. März 2014. Mit Java 8 erhielt Java Unterstützung für funktionale Programmierung, eine neue JavaScript-Engine, neue APIs für Datums-/Zeitmanipulation, die neue Stream-API u.v.m.
Neue Features
Lambda-Ausdrücke – Fügen Java funktionale Verarbeitungsfähigkeit hinzu.
Methodenreferenzen – Funktionen über ihren Namen referenzieren statt direkt aufzurufen; Funktionen als Parameter nutzen.
Default-Methoden – Interfaces können Standardimplementierungen haben.
Neue Tools – Neue Compiler-Tools und Utilities wie
jdepsfür Abhängigkeitsanalyse.Stream API – Neue API für Pipeline-Verarbeitung.
Date Time API – Verbesserte Datums-/Zeit-API.
Optional – Fokus auf Best Practices im Umgang mit null-Werten.
Nashorn, JavaScript Engine – Java-basierte Engine zur Ausführung von JavaScript-Code.
Betrachten Sie folgendes Code-Snippet:
Live Demoimport java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
public class Java8Tester {
public static void main(String args[]) {
List<String> names1 = new ArrayList<>();
names1.add("Mahesh ");
names1.add("Suresh ");
names1.add("Ramesh ");
names1.add("Naresh ");
names1.add("Kalpesh ");
List<String> names2 = new ArrayList<>();
names2.add("Mahesh ");
names2.add("Suresh ");
names2.add("Ramesh ");
names2.add("Naresh ");
names2.add("Kalpesh ");
Java8Tester tester = new Java8Tester();
System.out.println("Sortierung mit Java 7 Syntax: ");
tester.sortUsingJava7(names1);
System.out.println(names1);
System.out.println("Sortierung mit Java 8 Syntax: ");
tester.sortUsingJava8(names2);
System.out.println(names2);
}
// Sortierung mit Java 7
private void sortUsingJava7(List<String> names) {
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
}
// Sortierung mit Java 8 (Lambda)
private void sortUsingJava8(List<String> names) {
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
}
}
Ausgabe:
Sortierung mit Java 7 Syntax: [ Kalpesh Mahesh Naresh Ramesh Suresh ] Sortierung mit Java 8 Syntax: [ Kalpesh Mahesh Naresh Ramesh Suresh ]
Die Methode sortUsingJava8() nutzt einen Lambda-Ausdruck als Sortierkriterium.
Java 8 – Umgebungseinrichtung
Lokale Umgebung
Führen Sie diese Schritte aus, um Ihre Java-Umgebung einzurichten:
Java SE kostenlos herunterladen:
https://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html
Version passend zum Betriebssystem wählen, .exe ausführen, installieren. Anschließend Umgebungsvariablen setzen, damit sie auf die Installationsverzeichnisse verweisen.
Pfad unter Windows 2000/XP einrichten
Angenommen, Java liegt in c:\Program Files\java\jdk:
- Rechtsklick auf „Arbeitsplatz“ → „Eigenschaften“.
- Reiter „Erweitert“ → Button „Umgebungsvariablen“.
- Variable „Path“ bearbeiten, Pfad zu
java\jdk\binanhängen (z. B.C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin).
Pfad unter Windows 95/98/ME
C:\autoexec.bat editieren, am Ende anhängen:
SET PATH=%PATH%;C:\Program Files\java\jdk\bin
Pfad unter Linux, UNIX, Solaris, FreeBSD
Umgebungsvariable PATH auf Java-Binaries setzen. Beispiel für bash in .bashrc:
export PATH=/path/to/java:$PATH
Beliebte Java-Editoren
Notepad – Einfacher Texteditor unter Windows (für dieses Tutorial empfohlen).
NetBeans – Open-Source-Java-IDE, kostenlos: https://netbeans.org/
Eclipse – Open-Source-Java-IDE: https://www.eclipse.org/
Java 8 – Lambda-Ausdrücke
Lambda-Ausdrücke sind das größte Feature von Java 8. Sie ermöglichen funktionale Programmierung und vereinfachen die Entwicklung erheblich.
Syntax
parameter -> expression body
Wichtige Eigenschaften:
Optionale Typdeklaration – Typ der Parameter muss nicht deklariert werden; Compiler inferiert ihn.
Optionale Klammern – Bei einem Parameter keine Klammern nötig; bei mehreren erforderlich.
Optionale geschweifte Klammern – Bei Single-Statement-Body entfallen.
Optionales return – Bei Single-Expression-Body gibt Compiler automatisch zurück; bei Block sind Klammern und
returnnötig.
Lambda-Beispiele
Java8Tester.java
Live Demopublic class Java8Tester {
public static void main(String args[]) {
Java8Tester tester = new Java8Tester();
// mit Typdeklaration
MathOperation addition = (int a, int b) -> a + b;
// ohne Typdeklaration
MathOperation subtraction = (a, b) -> a - b;
// mit return und Klammern
MathOperation multiplication = (int a, int b) -> { return a * b; };
// ohne return, ohne Klammern
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// ohne Klammern
GreetingService greetService1 = message -> System.out.println("Hello " + message);
// mit Klammern
GreetingService greetService2 = (message) -> System.out.println("Hello " + message);
greetService1.sayMessage("Mahesh");
greetService2.sayMessage("Suresh");
}
interface MathOperation { int operation(int a, int b); }
interface GreetingService { void sayMessage(String message); }
private int operate(int a, int b, MathOperation mathOperation) {
return mathOperation.operation(a, b);
}
}
Ergebnis prüfen
10 + 5 = 15 10 - 5 = 5 10 x 5 = 50 10 / 5 = 2 Hello Mahesh Hello Suresh
Wichtige Punkte:
- Lambdas definieren Inline-Implementierungen funktionaler Interfaces (Interfaces mit genau einer Methode).
- Lambdas ersetzen anonyme Klassen und geben Java einfache, mächtige funktionale Fähigkeiten.
Scope
Lambdas können auf final oder effectively final Variablen (nur einmal zugewiesen) zugreifen. Zweite Zuweisung führt zu Kompilierfehler.
Scope-Beispiel
public class Java8Tester {
final static String salutation = "Hello! ";
public static void main(String args[]) {
GreetingService greetService1 = message -> System.out.println(salutation + message);
greetService1.sayMessage("Mahesh");
}
interface GreetingService { void sayMessage(String message); }
}
Ausgabe
Hello! Mahesh
Java 8 – Methodenreferenzen
Methodenreferenzen verweisen über :: auf Methoden. Möglich für:
- Statische Methoden
- Instanzmethoden
- Konstruktoren via
new(z. B.TreeSet::new)
Beispiel
Java8Tester.java
import java.util.List;
import java.util.ArrayList;
public class Java8Tester {
public static void main(String args[]) {
List names = new ArrayList();
names.add("Mahesh");
names.add("Suresh");
names.add("Ramesh");
names.add("Naresh");
names.add("Kalpesh");
names.forEach(System.out::println);
}
}
Hier wird System.out::println als statische Methodenreferenz übergeben.
Ausgabe
Mahesh Suresh Ramesh Naresh Kalpesh
Java 8 – Funktionale Interfaces
Funktionale Interfaces haben genau eine abstrakte Methode. Java 8 definiert viele in java.util.function. Übersicht:
| Nr. | Interface & Beschreibung |
|---|---|
| 1 | BiConsumer<T,U> Operation mit zwei Eingaben, kein Ergebnis. |
| 2 | BiFunction<T,U,R> Funktion mit zwei Argumenten, produziert Ergebnis. |
| 3 | BinaryOperator<T> Operation auf zwei Operanden gleichen Typs, Ergebnis gleichen Typs. |
| 4 | BiPredicate<T,U> Prädikat (Boolean-Funktion) mit zwei Argumenten. |
| 5 | BooleanSupplier Lieferant für Boolean-Werte. |
| 6 | Consumer<T> Operation mit einem Argument, kein Ergebnis. |
| 7 | DoubleBinaryOperator Operation auf zwei double-Operanden, double-Ergebnis. |
| 8 | DoubleConsumer Operation mit einem double-Argument, kein Ergebnis. |
| 9 | DoubleFunction<R> Funktion mit double-Argument, produziert Ergebnis. |
| 10 | DoublePredicate Prädikat mit einem double-Argument. |
| 11 | DoubleSupplier Lieferant für double-Werte. |
| 12 | DoubleToIntFunction Funktion: double → int. |
| 13 | DoubleToLongFunction Funktion: double → long. |
| 14 | DoubleUnaryOperator Operation auf einem double-Operanden, double-Ergebnis. |
| 15 | Function<T,R> Funktion mit einem Argument, produziert Ergebnis. |
| 16 | IntBinaryOperator Operation auf zwei int-Operanden, int-Ergebnis. |
| 17 | IntConsumer Operation mit einem int-Argument, kein Ergebnis. |
| 18 | IntFunction<R> Funktion: int → Ergebnis. |
| 19 | IntPredicate Prädikat mit einem int-Argument. |
| 20 | IntSupplier Lieferant für int-Werte. |
| 21 | IntToDoubleFunction Funktion: int → double. |
| 22 | IntToLongFunction Funktion: int → long. |
| 23 | IntUnaryOperator Operation auf einem int-Operanden, int-Ergebnis. |
| 24 | LongBinaryOperator Operation auf zwei long-Operanden, long-Ergebnis. |
| 25 | LongConsumer Operation mit einem long-Argument, kein Ergebnis. |
| 26 | LongFunction<R> Funktion: long → Ergebnis. |
| 27 | LongPredicate Prädikat mit einem long-Argument. |
| 28 | LongSupplier Lieferant für long-Werte. |
| 29 | LongToDoubleFunction Funktion: long → double. |
| 30 | LongToIntFunction Funktion: long → int. |
| 31 | LongUnaryOperator Operation auf einem long-Operanden, long-Ergebnis. |
| 32 | ObjDoubleConsumer<T> Operation mit Objekt- und double-Argument, kein Ergebnis. |
| 33 | ObjIntConsumer<T> Operation mit Objekt- und int-Argument, kein Ergebnis. |
| 34 | ObjLongConsumer<T> Operation mit Objekt- und long-Argument, kein Ergebnis. |
| 35 | Predicate<T> Prädikat mit einem Argument. |
| 36 | Supplier<T> Lieferant für Ergebnisse. |
| 37 | ToDoubleBiFunction<T,U> Funktion mit zwei Argumenten, double-Ergebnis. |
| 38 | ToDoubleFunction<T> Funktion, die double-Ergebnis liefert. |
| 39 | ToIntBiFunction<T,U> Funktion mit zwei Argumenten, int-Ergebnis. |
| 40 | ToIntFunction<T> Funktion, die int-Ergebnis liefert. |
| 41 | ToLongBiFunction<T,U> Funktion mit zwei Argumenten, long-Ergebnis. |
| 42 | ToLongFunction<T> Funktion, die long-Ergebnis liefert. |
| 43 | UnaryOperator<T> Operation auf einem Operanden, Ergebnis gleichen Typs. |
Functional Interface Beispiel
Predicate<T> ist ein funktionales Interface mit Methode test(Object), die Boolean zurückgibt.
Java8Tester.java
Live Demoimport java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Java8Tester {
public static void main(String args[]) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println("Alle Zahlen:");
eval(list, n -> true);
System.out.println("Gerade Zahlen:");
eval(list, n -> n % 2 == 0);
System.out.println("Zahlen > 3:");
eval(list, n -> n > 3);
}
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for (Integer n : list) {
if (predicate.test(n)) {
System.out.print(n + " ");
}
}
System.out.println();
}
}
Ausgabe
Alle Zahlen: 1 2 3 4 5 6 7 8 9 Gerade Zahlen: 2 4 6 8 Zahlen > 3: 4 5 6 7 8 9
Java 8 – Default-Methoden
Java 8 führt Default-Methoden in Interfaces ein – für Abwärtskompatibilität, damit alte Interfaces Lambda-Fähigkeiten nutzen können.
Beispiel: List oder Collection hatten keine forEach-Methode. Eine Hinzufügung würde Implementierungen brechen. Default-Methode erlaubt Standardimplementierung, sodass implementierende Klassen sie nicht überschreiben müssen.
Syntax
public interface Vehicle {
default void print() {
System.out.println("I am a vehicle!");
}
}
Mehrere Defaults
Wenn eine Klasse zwei Interfaces mit gleicher Default-Methode implementiert, gibt es Mehrdeutigkeit. Lösungen:
1. Eigene Methode überschreibt Default:
public class Car implements Vehicle, FourWheeler {
public void print() {
System.out.println("I am a four wheeler car vehicle!");
}
}
2. Expliziter Aufruf via super:
public class Car implements Vehicle, FourWheeler {
public void print() {
Vehicle.super.print();
}
}
Statische Default-Methoden
Interfaces können seit Java 8 auch statische Hilfsmethoden haben.
public interface Vehicle {
default void print() { System.out.println("I am a vehicle!"); }
static void blowHorn() { System.out.println("Blowing horn!!!"); }
}
Default-Methoden-Beispiel
Java8Tester.java
Live Demopublic class Java8Tester {
public static void main(String args[]) {
Vehicle vehicle = new Car();
vehicle.print();
}
}
interface Vehicle {
default void print() { System.out.println("I am a vehicle!"); }
static void blowHorn() { System.out.println("Blowing horn!!!"); }
}
interface FourWheeler {
default void print() { System.out.println("I am a four wheeler!"); }
}
class Car implements Vehicle, FourWheeler {
public void print() {
Vehicle.super.print();
FourWheeler.super.print();
Vehicle.blowHorn();
System.out.println("I am a car!");
}
}
Ausgabe
I am a vehicle! I am a four wheeler! Blowing horn!!! I am a car!
Java 8 – Streams
Streams sind eine neue abstrakte Schicht in Java 8. Sie ermöglichen deklarative Datenverarbeitung ähnlich wie SQL. Beispiel SQL:
SELECT max(salary), employee_id, employee_name FROM Employee
Mit Collections musste der Entwickler Schleifen und Checks schreiben. Multicore-Prozessoren erforderten parallelen Code – fehleranfällig. Streams lösen dies: deklarative Verarbeitung, automatische Parallelisierung.
Was ist ein Stream?
Sequenz von Elementen – Stream liefert Elemente on-demand, speichert sie nicht.
Source – Collections, Arrays, I/O-Ressourcen.
Aggregate Operationen – filter, map, limit, reduce, find, match, …
Pipelining – Die meisten Operationen geben Stream zurück (intermediate operations).
collect()ist terminal.Automatische Iteration – Intern über Quell-Elemente, keine explizite Iteration nötig.
Streams erzeugen
Collection-Interface bietet:
stream()– sequentieller Stream.parallelStream()– paralleler Stream.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
forEach
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
map
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); List<Integer> squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
filter
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
int count = strings.stream().filter(s -> s.isEmpty()).count();
limit
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
Parallel Processing
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
long count = strings.parallelStream().filter(s -> s.isEmpty()).count();
Collectors
List<String> filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
String merged = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.joining(", "));
Statistics
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt(x -> x).summaryStatistics();
System.out.println("Max: " + stats.getMax());
System.out.println("Min: " + stats.getMin());
System.out.println("Sum: " + stats.getSum());
System.out.println("Average: " + stats.getAverage());
Stream-Beispiel (Vollständig)
Java8Tester.java
Live Demoimport java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;
public class Java8Tester {
public static void main(String args[]) {
System.out.println("Using Java 7: ");
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
System.out.println("List: " + strings);
long count = getCountEmptyStringUsingJava7(strings);
System.out.println("Empty Strings: " + count);
count = getCountLength3UsingJava7(strings);
System.out.println("Strings of length 3: " + count);
List<String> filtered = deleteEmptyStringsUsingJava7(strings);
System.out.println("Filtered List: " + filtered);
String mergedString = getMergedStringUsingJava7(strings, ", ");
System.out.println("Merged String: " + mergedString);
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
List<Integer> squaresList = getSquares(numbers);
System.out.println("Squares List: " + squaresList);
List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
System.out.println("List: " + integers);
System.out.println("Highest number: " + getMax(integers));
System.out.println("Lowest number: " + getMin(integers));
System.out.println("Sum: " + getSum(integers));
System.out.println("Average: " + getAverage(integers));
System.out.println("Random Numbers: ");
Random random = new Random();
for (int i = 0; i < 10; i++) {
System.out.println(random.nextInt());
}
System.out.println("\nUsing Java 8: ");
System.out.println("List: " + strings);
count = strings.stream().filter(s -> s.isEmpty()).count();
System.out.println("Empty Strings: " + count);
count = strings.stream().filter(s -> s.length() == 3).count();
System.out.println("Strings of length 3: " + count);
filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
mergedString = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
System.out.println("Squares List: " + squaresList);
System.out.println("List: " + integers);
IntSummaryStatistics stats = integers.stream().mapToInt(x -> x).summaryStatistics();
System.out.println("Highest number: " + stats.getMax());
System.out.println("Lowest number: " + stats.getMin());
System.out.println("Sum: " + stats.getSum());
System.out.println("Average: " + stats.getAverage());
System.out.println("Random Numbers: ");
random.ints().limit(10).sorted().forEach(System.out::println);
// parallel processing
count = strings.parallelStream().filter(s -> s.isEmpty()).count();
System.out.println("Empty Strings (parallel): " + count);
}
// ... Java-7-Hilfsmethoden (wie im Original) ...
}
Ausgabe (gekürzt)
Using Java 7: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] ... Using Java 8: ... Average of all numbers: 9.444444444444445 Random Numbers: -1009474951 -551240647 ... 1798939493 Empty Strings: 2
Java 8 – Optional Klasse
(Inhalt identisch mit Artikel 1001016161 – hier aus Platzgründen gekürzt. Siehe dort für vollständige Methoden-Tabelle und Beispiel.)
Java 8 – Nashorn JavaScript
(Inhalt identisch mit Artikel 1001016162 – hier gekürzt. Siehe dort für Details zu jjs, Java↔JS-Aufrufe.)
Java 8 – Neue Date/Time API
(Inhalt identisch mit Artikel 1001016163 – hier gekürzt. Siehe dort für Local, Zoned, ChronoUnit, Period/Duration, Adjusters, Backward Compatibility.)
Java 8 – Base64
(Inhalt identisch mit Artikel 1001016164 – hier gekürzt. Siehe dort für Simple/URL/MIME, Encoder/Decoder, Beispiel.)
Java
- Java Vector verstehen: Verwendung, Funktionen und Vergleich mit ArrayList
- CNC-Fräsmaschine Grundlagen: Schnelle Referenz für professionelle Bediener
- Vorbeugende & zustandsbasierte Instandhaltung meistern: Praktischer PM-Entwicklungsleitfaden
- Lieferkette absichern: Umfassende Versicherungsstrategien
- Expertenleitfaden zu Vierkantrohr-Biegemaschinen
- Kaltpressmaschinen: Umfassender Leitfaden für effizientes Metallumformen
- Planetengetriebe erklärt: Kompakt, hohes Drehmoment, präzise Drehzahlreduzierung
- Jet Mill Drill: Der ultimative Profi-Leitfaden für Kombimaschinen
- Servopressen: Funktionsweise & Vorteile gegenüber mechanischen Pressen
- Pneumatikzylinder: Professioneller Leitfaden – Schnell & Zuverlässig