After 3 years, the third LTS version, Java 17, was released in September 2021. We all are very excited and keen to learn more about new changes it brings to us. However, many projects and products are still using Java 11, or even Java 8. In this session, we will not only focus on those amazing features, but also have a quick introduction on why we should migrate to Java 17 and how.
https://cyberjos.blog/java/seminar/jcconf-2021-java17-the-next-lts/
12. Briefing
JDK 17 is the latest Long Term Support version
Spring announces that Spring Framework 6 and Spring Boot
3 will support JDK 17 next year
JDK 18 will be released in March 2022
The interval between LTS versions is now two years instead
of three, making Java 21 (planned for September 2023)
probably the next LTS.
13. Benchmark of JDK 11, 16 and 17
Source: https://www.optaplanner.org/blog/2021/09/15/HowMuchFasterIsJava17.html
14. Benchmark of JDK 11, 16 and 17
Source: https://www.optaplanner.org/blog/2021/09/15/HowMuchFasterIsJava17.html
15. Performance Summary
On average, for OptaPlanner use cases, these benchmarks
indicate that:
Java 17 is 8.66% faster than Java 11 and 2.41% faster
than Java 16 for G1GC (default).
Java 17 is 6.54% faster than Java 11 and 0.37% faster
than Java 16 for ParallelGC.
The Parallel Garbage Collector is 16.39% faster than the
G1 Garbage Collector.
16. JDK 16 (2021-03-16)
Infrastructure
JEP 357: Migrate from Mercurial to Git
JEP 369: Migrate to GitHub
Implementation
JEP 347: Enable C++14 Language Features
JEP 376: ZGC: Concurrent Thread-Stack Processing
JEP 386: Alpine Linux Port
JEP 388: Windows/AArch64 Port
17. JDK 16 (2021-03-16) Cont.
JDK
JEP 387: Elastic Metaspace
JEP 392: Packaging Tool
SE
JEP 380: Unix-Domain Socket Channels
JEP 390: Warnings for Value-Based Classes
JEP 394: Pattern Matching for instanceof
JEP 395: Records
JEP 396: Strongly Encapsulate JDK Internals by Default
18. JDK 16 (2021-03-16) Cont.
Incubator
JEP 338: Vector API (Incubator)
JEP 389: Foreign Linker API (Incubator)
JEP 393: Foreign-Memory Access API (Third Incubator)
JEP 397: Sealed Classes (Second Preview)
19. JDK 17 (2021-09-14)
Infrastructure
None
Implementation
JEP 391: macOS/AArch64 Port
20. JDK 17 (2021-09-14) Cont.
JDK
JEP 382: New macOS Rendering Pipeline
SE
JEP 306: Restore Always-Strict Floating-Point Semantics
JEP 356: Enhanced Pseudo-Random Number Generators
JEP 403: Strongly Encapsulate JDK Internals
JEP 409: Sealed Classes
JEP 415: Context-Specific Deserialization Filters
21. JDK 17 (2021-09-14) Cont.
Incubator
JEP 406: Pattern Matching for switch (Preview)
JEP 412: Foreign Function & Memory API (Incubator)
JEP 414: Vector API (Second Incubator)
Removal
JEP 398: Deprecate the Applet API for Removal
JEP 407: Remove RMI Activation
JEP 410: Remove the Experimental AOT and JIT Compiler
JEP 411: Deprecate the Security Manager for Removal
24. Text Blocks
A multi-line string literal that avoids the need for most
escape sequences, automatically formats the string in a
predictable way, and gives the developer control over the
format when desired
The Java compiler applies a smart algorithm to strip
leading white space from the resulting string such that
The indentation that is relevant only for better readability of
the Java source code is removed
The indentation relevant to the string itself remains
untouched
25. Text Blocks Example
String json = """
{
"name":"Joseph",
"gender":"M"
}
""";
Shows ( . marks a white space)
{n
.."name":"Joseph",n
...."gender":"M"n
......}n
26. Text Blocks Example
String json = """
{
"name":"Joseph",
"gender":"M"
}
""";
Shows ( . marks a white space)
..{n
...."name":"Joseph",n
......"gender":"M"n
........}n
27. Text Blocks
The open """ and the closing """ need to be located at
different lines
Trailing white space is removed from every line
Uses "" to escape """
Uses "" at the end of lines to avoid from line breaks
The final line break can be removed by appending the
closing """ directly to the string's end
It can work with formatted method to insert variables
28. Text Blocks Example - Further
String str = """
String helloString =
"""
Hello %s!
;""".formatted("World");
Shows ( . marks a white space)
String.helloString.=n
...."""n
....Hello.Worls!.;
30. Switch Expressions
To extend switch to be either a statement or an expression
so that both forms can use
either traditional labels (with fall through) case ... :
or new labels (with no fall through) case ... ->
, with a further new statement for yielding a value from a
switch expression.
Uses "->" instead of ":"
Allows multiple constants per case
No full-through semantics (no break)
Makes variables defined inside a case branch local to
this branch
31. Switch Expressions Example - Statement
void showPlanetType(Planet planet) {
switch(planet) {
case EARTH, MARS -> System.out.println("Inner");
case JUPITER, SATURN -> System.out.println("Outer");
}
}
32. Switch Expressions Example - Assignment
enum Month {
JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
}
int getDay(Month month) {
return switch(month) {
case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
case APR, JUN, SEP, NOV -> 30;
case FEB -> 28;
};
}
33. Switch Expressions - yield
If a full block is needed, we can use the new yield
statement to yield a value, which becomes the value of the
enclosing switch expression.
When using a traditional switch block, values can also be
yielded by using the new yield statement.
34. Switch Expressions Example - yield
String result1 = switch (i) {
case 0 -> "Zero";
default -> {
String r = i % 2 == 0 ? "Even" : "Odd";
System.out.println("i = " + i + ", r = " + r);
yield r;
}
}
String result2 = switch (i) {
case 0: yield "Zero";
case 1: yield "One";
default: yield "Unknown";
}
36. Pattern Matching for instanceof
It enhances instanceof operators to allow common logic in
a program, namely the conditional extraction of
components from objects, to be expressed more concisely
and safely
It combines check, assign and cast actions
37. Pattern Matching for instanceof Example
// if (obj instanceof String) { String s = (String) obj; }
if (obj instanceof String s) { //only use s here
System.out.println("String: " + s);
} else if (obj instanceof Integer i) { //no s here
System.out.println("Integer: " + i);
} else if (obj instanceof Map m && !m.isEmpty()) {
// &&: PASS, ||: ERROR
System.out.println("Map: " + m);
}
39. Pattern Matching for switch
It enhances switch expressions and statements, along with
extensions to the language of patterns. Extending pattern
matching to switch allows an expression to be tested
against a number of patterns, each with a specific action,
so that complex data-oriented queries can be expressed
concisely and safely.
40. Pattern Matching for switch Example
switch(obj) {
case null -> System.out.println("NULL"); //default throw NPE
case String s -> System.out.println("String: " + s);
case Integer i -> System.out.println("Integer: " + i);
case Map m && !m.isEmpty() -> System.out.println("Map: " + m);
default -> obj.toString();
}
41. Pattern Matching for switch Future Work
int eval(Expr n) {
return switch(n) {
case IntExpr(int i) -> i;
case NegExpr(Expr n) -> -eval(n);
case AddExpr(Expr left, Expr right) ->
eval(left) + eval(right);
case MulExpr(Expr left, Expr right) ->
eval(left) * eval(right);
default -> throw new IllegalStateException();
};
}
43. Records
Classes that act as transparent carriers for immutable data.
Records can be thought of as nominal tuples.
This new kind of class is to declare that a small group of
variables is to be regarded as a new kind of entity. A record
declares its state (the group of variables) and commits to
an API that matches that state.
44. Records Members
For each component in the header: a public accessor
method with the same name and return type as the
component, and a private final field with the same type as
the component
A canonical constructor whose signature is the same as the
header
equals and hashCode methods which say that two records
are equal if they are of the same type/value
A toString method that returns a string representation of
all the record components along with their names
45. Records Restrictions
A record doesn't have an extends clause. The superclass is
always java.lang.Record, like enum
A record is implicitly final and cannot be abstract
A record cannot explicitly declare instance fields, and
cannot contain instance initializers.
The implicitly declared fields are final
A record cannot declare native methods
46. Records Behaviors
Instantiated with the new keyword
Can be declared top level or nested
Can declare static methods/fields/initializers
Can declare instance methods
Can implement interfaces
Can declare nested types, including nested records
Can be annotated
Can override constructor and accessors
47. Records Example
The declaration of a record specifies a name, a header and a
body. The header lists the components of the record, which
are the variables that make up its state.
record Point(int x, int y) implements Serializable {
// body
private static int counter;
public static int getCounter() { return counter; }
public static void addCounter() { counter++; }
public int plusX() { return counter * x;}
}
50. Sealed Classes
Sealed classes and interfaces restrict which other classes or
interfaces may extend or implement them.
Allow the author of a class or interface to control which
code is responsible for implementing it.
Provide a more declarative way than access modifiers to
restrict the use of a superclass
Support future directions in pattern matching by
underpinning the exhaustive analysis of patterns
51. Sealed Classes Example
public sealed interface Shape
permits Circle, Rectangle, Square {}
public final class Circle implements Shape {}
public sealed class Rectangle implements Shape
permits TransparentRectangle {
final class ChildRectangle extends Rectangle {}
}
public final class TransparentRectangle
extends Rectangle {}
public record Square(int x, int y)
implements Shape {}
52. Sealed Classes Example
Shape rotate(Shape shape, double angle) {
return switch (shape) { // pattern matching switch
case Circle c -> c;
case Rectangle r -> r.rotate(angle);
case Square s && isRightAngle(angle) -> s;
case Square s -> s.rotate(angle);
// no default needed!
}
}
54. Packaging Tool
Packages up the applications into a native format
corresponding to your current platform:
Linux: deb or rpm
Windows: msi or exe
macOS: pkg or dmg
jpackage --name demo --input ./lib --main-jar demo.jar
--main-class demo.Main
56. Helpful NullPointerExceptions
a.b.c.i = 99
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "c" because "a.b" is null
at Prog.main(Prog.java:5)
a[i][j][k] = 99
Exception in thread "main" java.lang.NullPointerException:
Cannot load from object array because "a[i][j]" is null
at Prog.main(Prog.java:5)
a.i = b.j
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "j" because "b" is null
at Prog.main(Prog.java:5)
58. Vector API Example
public void newVectorComputation(float[] a, float[] b, float[] c)
{
for (var i = 0; i < a.length; i += SPECIES.length()) {
var m = SPECIES.indexInRange(i, a.length);
var va = FloatVector.fromArray(SPECIES, a, i, m);
var vb = FloatVector.fromArray(SPECIES, b, i, m);
var vc = va.mul(vb);
vc.intoArray(c, i, m);
}
}
60. Enhanced PRNG
New interfaces and implementations for Pseudo-Random
Number Generators (PRNG)
Legacy random classes, such as java.util.Random,
SplittableRandom, and SecureRandom, now extend the new
RandomGenerator interface.
RandomGenerator: SplittableRandomGenerator,
JumpableRandomGenerator, LeapableRandomGenerator,
ArbitrarilyJumpableRandomGenerator
61. Enhanced PRNG Example
public IntStream getPseudoInts(String algorithm, int streamSize) {
// returns an IntStream with size @streamSize of random
// numbers generated using the @algorithm where the lower
// bound is 0 and the upper is 100 (exclusive)
return RandomGeneratorFactory.of(algorithm)
.create()
.ints(streamSize, 0, 100);
}