[EN] Beyond Java 8 Examples

Julian | Sep 25, 2024 min read

Now that we have clarified the theory in the first part, we now add some practice. Here are code examples and explanations for the key features of each Java version from 8 to 23:

Java 8 (March 2014)

Lambdas & Functional Interfaces

Code:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));

Explanation: Lambda expressions allow functions to be passed as parameters, making code shorter and more concise. Here a list of names is run through and each name is output.

Stream API

Code:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream()
                                  .filter(name -> name.startsWith("A"))
                                  .collect(Collectors.toList());

Explanation: The Stream API allows processing sequences of elements in a declarative manner. Here a list is filtered so that only names starting with “A” are returned.

Optional Class

Code:

Optional<String> name = Optional.ofNullable(null);
System.out.println(name.orElse("Default Name"));

Explanation: The Optional class helps avoid NullPointerExceptions by providing an optional container class. Here a default name is returned if the original name is null.

Date and Time API

Code:

LocalDate date = LocalDate.now();
System.out.println(date);

Explanation: The new Date and Time API is much more comprehensive and error-resistant than the old one. The current date is displayed here.

Java 9 (September 2017)

Project Jigsaw (Module System)

Code: (module-info.java)

module com.example {
    requires java.base;
    exports com.example;
}

Explanation: The module system improves the maintainability and security of applications through modularization. Here a simple module is defined that requires another module and exports a package.

JShell (REPL)

Explanation: JShell provides an interactive command line for testing Java code. It helps in quick experimentation without having to write a complete class.

Stream API improvements

Code:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
     .takeWhile(name -> !name.isEmpty())
     .forEach(System.out::println);

Explanation: New methods such as takeWhile provide additional options for processing streams. All non-empty names are output here.

Factory Methods for Collections

Code:

List<String> names = List.of("Alice", "Bob", "Charlie");
System.out.println(names);

Explanation: These new methods make initializing immutable collections easier and safer.

Java 10 (March 2018)

Local-Variable Type Inference

Code:

var name = "Alice";
System.out.println(name);

Explanation: var can be used to declare local variables with the type automatically inferred. This increases the readability of the code.

Java 11 (September 2018)

New string methods

Code:

String text = " Hello World ";
System.out.println(text.strip());
System.out.println(text.isBlank());
System.out.println("Hello\nWorld".lines().count());

Explanation: Additional methods such as strip(), isBlank(), and lines() make working with strings much easier.

Lambda syntax for anonymous classes

Code:

Callable<String> callable = () -> "Hello, World!";
System.out.println(callable.call());

Explanation: Lambda expressions can now also be used on anonymous classes, making the code shorter and more concise.

HTTP Client API

Code:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
                                 .uri(URI.create("https://example.com"))
                                 .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

Explanation: The new HTTP Client API makes it easier to send HTTP requests.

Java 12 (March 2019)

Switch Expressions (Preview)

Code:

int num = 2;
String result = switch (num) {
    case 1 -> "one";
    case 2 -> "two";
    default -> "many";
};
System.out.println(result);

Explanation: Switch expressions allow values ​​to be returned directly, making code shorter and more concise.

Java 13 (September 2019)

Text Blocks (Preview)

Code:

String textBlock = """
    Hello,
    World!
    """;
System.out.println(textBlock);

Explanation: Text blocks allow you to easily write multi-line string text and improve the readability of large text.

Java 14 (March 2020)

Switch Expressions (Final)

Similar to Java 12

Records (Preview)

Code:

record Point(int x, int y) {}
Point point = new Point(1, 2);
System.out.println(point.x());

Explanation: Records are a new type of class that mainly carries data and does not require any additional code.

Java 15 (September 2020)

Sealed Classes (Preview)

Code:

public abstract sealed class Shape permits Circle, Square {}
public final class Circle extends Shape {}
public final class Square extends Shape {}

Explanation: Sealed classes make it possible to control the interfaces hierarchically and to define which classes are allowed to extend a class.

Java 16 (March 2021)

Pattern Matching for instanceof

Code:

Object obj = "Hello, World!";
if (obj instanceof String s) {
    System.out.println(s.toUpperCase());
}

Explanation: Pattern matching for instanceof simplifies casting and using objects.

Java 17 (September 2021)

Sealed Classes (Final)

See Java 15

Pattern Matching for switch (Preview)

Code:

Object obj = "Hello";
switch (obj) {
    case Integer i -> System.out.println("Integer: " + i);
    case String s -> System.out.println("String: " + s);
    default -> System.out.println("Unknown type");
}

Explanation: Allows the use of patterns within switch statements.

Java 18 (March 2022)

Simple Web Server

Code:

com.sun.net.httpserver.HttpServer server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/test", (exchange -> {
    String response = "This is the response";
    exchange.sendResponseHeaders(200, response.getBytes().length);
    OutputStream os = exchange.getResponseBody();
    os.write(response.getBytes());
    os.close();
}));
server.start();

Explanation: Easy to set up a web server for development purposes.

Java 19 (September 2022)

Virtual Threads (Preview)

Code:

Thread.startVirtualThread(() -> {
    System.out.println("Hello from virtual thread");
});

Explanation: Lightweight threads that allow massively parallel applications to be written efficiently.

Java 20 (March 2023)

Enhancements to ARM

Code:

// Kein spezifisches Code-Beispiel erforderlich, verbesserte Architekturunterstützung

Explanation: Improving the architecture for modern ARM processors.

Java 21 (September 2023)

String Templates (Preview)

Code:

String language = "Java";
String template = STR."This is ${language}!";
System.out.println(template);

Explanation: String templates enable safe and clean inclusion of expression data in strings.

Java 22 (March 2024)

Vector API (Incubator)

Code:

import jdk.incubator.vector.FloatVector;
import jdk.incubator.vector.VectorSpecies;

public class VectorExample {
    private static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

    public static void main(String[] args) {
        float[] a = {1.0f, 2.0f, 3.0f, 4.0f};
        float[] b = {5.0f, 6.0f, 7.0f, 8.0f};
        FloatVector va = FloatVector.fromArray(SPECIES, a, 0);
        FloatVector vb = FloatVector.fromArray(SPECIES, b, 0);
        FloatVector vc = va.add(vb);
        vc.intoArray(a, 0);
        System.out.println(Arrays.toString(a)); // [6.0, 8.0, 10.0, 12.0]
    }
}

Explanation: Allows the use of vector operations to speed up numerical calculations.

Java 23 (September 2024)

Enhanced Primitive Type Patterns

Code:

Object value = 42;
switch (value) {
    case Integer i -> System.out.println("Integer: " + i);
    case Double d -> System.out.println("Double: " + d);
    default -> System.out.println("Unknown type");
}

Explanation: Provides patterns for primitive data types, making these types easier to work with.

Flexible Constructor Bodies

Code:

class Point {
    int x, y;
    Point(int x, int y) {
        this.x = (x < 0) ? 0 : x;
        this.y = (y < 0) ? 0 : y;
    }
}

Explanation: Allows constructors to flexibly initialize instantiated objects.

Simplified Module Imports

Code:

// Vor Java 23
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
// Java 23 Language Preview
//java --enable-preview --source 23 Helloworld.java
import module java.base;

Explanation: Simplifies importing and managing modules in projects.

Structured Concurrency

Code:

// Beispiel für strukturierte Concurrency
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Future<String> result1 = scope.fork(() -> task1());
    Future<String> result2 = scope.fork(() -> task2());
    scope.join();              // Warten auf alle
    scope.throwIfFailed();     // Ausnahmen behandeln
    var results = List.of(result1.resultNow(), result2.resultNow());
    results.forEach(System.out::println);
}

Explanation: Simplifies parallel programming through structured and reliable thread handling.

Class-File API Update

Code:

// Beispiel für Class-File API Update

Explanation: Improvements to the API for reading and writing Java class files.

These examples and explanations should help you understand and apply the key features and changes in each Java version from Java 8 to the current version 23.