From Java 9


Creative Commons License
This -From Java 9- tutorial is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
Preamble
Headlines
https://javaee.github.io/jaxb-v2/ JAXB no longer in Java 11 https://blog.invivoo.com/java-9-les-nouveautes/
The big picture: Java 9 key enhancement is the introduction of modules (module keyword) in order to rationalize the stuff present in the Java Virtual Machine (JVM) at execution time. Java 9-based design of an app. then arises from the “module” principle in the sense that developers have to isolate their code in execution-independent components.
Rule(s)

Modules

Rule(s)
Further detail on Java 9 modules here

Immutable collections

Rule(s)
Example From_Java_9.Java.zip 
Mammutidae m0 = new Mammutidae("Macron");
Mammutidae m1 = new Mammutidae("Poutine");
Mammutidae m2 = new Mammutidae("Trump");
// Immutable collections (e.g., a set):
try {
    java.util.Set.of(m1, m2).add(m0); // Poutine and Trump don't want Macron!
} catch (UnsupportedOperationException uoe) {
    System.err.println("In essence, immutable collections do not support changes like additions: " + uoe.toString());
}
Example From_Java_9.Java.zip 
java.util.Set<Integer> primes = new java.util.HashSet<>() { // <- Creation of an anonymous inner class, which extends 'java.util.HashSet'
    { // <- Block initializer
        add(2);
        add(3);
    }
};
try { // Java 10 'copyOf':
    java.util.Set.copyOf(primes).add(4);
} catch (UnsupportedOperationException uoe) {
    System.err.println("In essence, immutable collections do not support changes like additions: " + uoe.toString());
}

Streams improved…

Rule(s)
Example From_Java_9.Java.zip 
java.util.List<Integer> positives = java.util.Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
java.util.stream.Stream<Integer> stream = positives.stream().filter(p -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch(i -> (p % i == 0)));
System.out.println(stream.takeWhile(p -> !p.equals(7)).collect(java.util.stream.Collectors.toList())); // '[2, 3, 5]' is displayed...
java.util.stream.Stream<Integer> stream_ = positives.stream().filter(p -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch(i -> (p % i == 0)));
System.out.println(stream_.dropWhile(p -> !p.equals(7)).collect(java.util.stream.Collectors.toList())); // '[7, 11]' is displayed...
Rule(s)
Example From_Java_9.Java.zip 
java.util.List<Object> objects = java.util.Arrays.asList(new Object(), null, new Object());
java.util.stream.Stream<Object> stream__ = objects.stream().flatMap(o -> java.util.stream.Stream.ofNullable(o));
System.out.println(stream__.count()); // '2' is displayed...
As strongly typed programming language, Java imposes the typing of objects. Usages are then checked by the compiler in conformance with “announced” types. Contrary to JavaScript or Python, anomalies as potential execution errors are eliminated at compilation time (execution time for JavaScript or Python). Nonetheless, in many cases, “type announcement” creates no added value code. In this scope, type inference is the ability of the compiler to derive the type of an object. From Java 10, the var keyword forces the compiler to establish the type an object on its own.

var keyword (Java 10)

Example (“old” type inference based on diamond-based instantiation)
java.util.Map<Integer, Double> polynomial = new java.util.HashMap<>();
polynomial.put(1, -12.D);
polynomial.put(39, 8.D);
Example
var polynomial = new java.util.HashMap<Double, Double>();
polynomial.put(1, -12.D);
polynomial.put(39, 8.D);

var keyword in conjunction with lambda expression (Java 11)

Rule(s)
Example From_Java_9.Java.zip 
var positives = java.util.Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
var stream = positives.stream().filter((var p) -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch((var i) -> (p % i == 0)));
var primes = stream.collect(java.util.stream.Collectors.toList());
primes.forEach((var p) -> System.out.print(" " + p)); // '2 3 5 7 11' is displayed...
Rule(s)
Example (annotation imposes Integer and int as types of lambda expression parameters) From_Java_9.Java.zip 
@java.lang.annotation.Target(value = java.lang.annotation.ElementType.PARAMETER)
@interface Must_be_positive {
}
…
var stream = positives.stream().filter((@Must_be_positive Integer p) -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch((@Must_be_positive int i) -> (p % i == 0)));
…
primes.forEach((@Must_be_positive Integer p) -> System.out.print(" " + p)); // '2 3 5 7 11' is displayed...
Example (using var ejects Integer and int) From_Java_9.Java.zip 
…
var stream = positives.stream().filter((@Must_be_positive var p) -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch((@Must_be_positive var i) -> (p % i == 0)));
…
primes.forEach((@Must_be_positive var p) -> System.out.print(" " + p)); // '2 3 5 7 11' is displayed...
Java 12 comes with much flexibility with the use of the historical switchkeyword.
Rule(s)
Example From_Java_9.Java.zip 
enum Direction {
    East, South, West, North
}
…
var my_direction = Direction.East;
var next_direction = switch (my_direction) { // '--enable-preview'
    case East -> /* 'break' disappears! */ Direction.South; 
    case South, North -> /* 'break' disappears and multiple choices! */ Direction.East; 
    default -> my_direction;
};