Contenu connexe Similaire à The Future of Java: Records, Sealed Classes and Pattern Matching (20) Plus de José Paumard (20) The Future of Java: Records, Sealed Classes and Pattern Matching1. The Future of Java: Records, Sealed Classes
and Pattern Matching
Among other things
José Paumard
Java Developer Advocate
Java Platform Group
7. Language
Type inference for locals (var)
Switch expressions
Text blocks
Record classes
Sealed classes
Pattern matching for instanceof
Compact String, Indify
Concatenation
JDK 17: New Features Since the JDK 8
Copyright © 2021, Oracle and/or its affiliates
7
Tools
jshell
jlink
jdeps
jpackage
java source code launcher
javadoc search + API history
JVM
Garbage Collectors: G1, ZGC
AArch64 support: Windows, Mac, Linux
Docker awareness
Class Data Sharing by default
Helpful NullPointerExceptions
Hidden classes
Libraries
HTTP client
Collection factories
Unix-domain sockets
Stack walker
Deserialization filtering
Pseudo-RNG, SHA-3, TLS 1.3
9. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
9
Do not call new Integer(...)
Stop Calling Wrapper Classes Constructors!
@Deprecated(since="9", forRemoval = true)
public Integer(int value) {
this.value = value;
}
@IntrinsicCandidate
public static Integer valueOf(int i) {
// some code
return new Integer(i);
}
10. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
10
Do not override finalize()
Stop Overriding Finalize!
@Deprecated(since="9")
protected void finalize() throws Throwable {
}
12. ?Record and Array Pattern Matching?
Record
Sealed Classes
Switch Expression
Constant Dynamic
Inner Classes
private in VM
Nestmates
Pattern Matching for instanceof
11
14
16
17 Switch on Patterns
19
14. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
14
Record Deconstruction
if (o instanceof Rectangle rectangle) {
int width = rectangle.width();
int height = rectangle.height();
// do something with width and height
}
15. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
15
This is record deconstruction
width are height are binding variables
Record Deconstruction
if (o instanceof Rectangle(int width, int height)) {
// do something with width and height
}
16. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
16
Three type patterns
Three pattern binding variables
One target operand
Pattern Matching for Switch
String formatted =
switch(number) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %d", d);
}
17. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
17
Pattern Matching for Switch
record Square(int edge) {}
record Circle(int radius) {}
double area = switch(shape) {
case Square(int edge) -> edge* edge;
case Circle(int radius) -> Math.PI*radius*radius;
default -> ...;
}
18. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
18
Array Pattern Matching
if (o instanceof String[] array && array.length() >= 2) {
// do something with array[0] and array[1]
}
19. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
19
Array Pattern Matching
if (o instanceof String[] {String s1, String s2}) {
// do something with s1 and s2
}
20. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
20
Array Pattern Matching
if (o instanceof Circle[] {Circle(var r1), Circle(var r3)}) {
// do something with r1 and r2
}
21. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
21
You can use var in patterns
Syntaxic Sugars
if (shape instanceof Circle(var center, var radius)) {
// center and radius are binding variables
}
record Point(int x, int y) {}
record Circle(Point center, int radius) implements Shape {}
22. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
22
You can tell that you do not need a binding variable
Syntaxic Sugars
if (shape instanceof Circle(var center, _)) {
// center and radius are binding variables
}
record Point(int x, int y) {}
record Circle(Point center, int radius) implements Shape {}
23. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
23
You can nest patterns (nested patterns)
Syntaxic Sugars
if (shape instanceof Circle(var center, _) &&
center instanceof Point(int x, int y)) {
// center and radius are binding variables
}
if (shape instanceof Circle(Point(int x, int y), _)) {
// center and radius are binding variables
}
24. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
24
The deconstruction uses the canonical constructor of a
record
What about:
- factory methods?
- classes that are not records?
Deconstruction
25. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
25
Deconstruction Using Factory Methods
interface Shape {
static Circle circle(double radius) {
return new Circle(radius);
}
static Square square(double edge) {
return new Square(edge);
}
}
record Circle(double radius) {}
record Square(double edge) {}
26. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
26
Then this code becomes possible:
Deconstruction Using Factory Methods
double area = switch(shape) {
case Shape.circle(double radius) -> Math.PI*radius*radius;
case Shape.square(double edge) -> edge*edge;
}
27. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
27
What About Your POJOs?
public class Point {
private int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public deconstructor(int x, int y) {
x = this.x;
y = this.y;
}
}
The binding variables
are the same
external state
description
Allows defensive copy
and overloading
28. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
28
You saw patterns with instanceof and switch
Let us see match !
Pattern with Match
record Point(int x, int y) {}
record Circle(Point center, int radius) implements Shape {}
Circle circle = ...;
match Circle(var center, var radius) = circle;
// center and radius are binding variables
29. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
29
If shape is in fact a rectangle…
You can throw an exception
Pattern with Match
Shape shape = ...;
match Circle(var center, var radius) = shape
else
throw new IllegalStateException("Not a circle");
// center and radius are binding variables
30. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
30
If shape is in fact a rectangle …
Or define default values
Pattern with Match
Shape shape = ...;
match Circle(Point center, int radius) = shape
else {
center = new Point(0, 0); // this is called
radius = 1d; // an anonymous matcher
}
// center and radius are binding variables
31. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
31
You can use match with more than one pattern…
… or use nested patterns
Pattern with Match
Shape shape = ...;
match Rectangle(var p1, var p2) = shape,
Point(var x0, var y0) = p1,
Point(var x1, var y2) = p2;
32. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
32
With factory methods
More Examples
if (opt instanceof Optional.of(var max)) {
// max is a binding variable
}
33. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
33
With factory methods
More Examples
if (s instanceof
String.format("%s is %d years old",
String name, Integer.valueOf(int age) {
// name and age are binding variables
}
34. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
34
You can create maps with factory methods
This is an extended form of Pattern Matching where you
check the value of a binding variable
More Examples
if (map instanceof Map.withMapping("name", var name) &&
map instanceof Map.withMapping("email", var email)) {
// name and email are binding variables
}
35. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
35
Pattern combination
More Examples
if (map instanceof Map.withMapping("name", var name) __AND
map instanceof Map.withMapping("email", var email)) {
// name and email are binding variables
}
__AND = pattern combination
36. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
36
More Examples
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address" : {
"street": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
}
}
if (json instanceof
stringKey("firstName", var firstName) __AND
stringKey("lastName", var lastName) __AND
intKey("age", var age) __AND
objectKey("address",
stringKey("stree", var street) __AND
stringKey("city", var city) __AND
stringKey("state", var state)
)) {
// firstName, lastName, age,
// street, city, state, ...
// are binding variables
}
37. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
37
If Java Embraces « Map Literals »
Map<String, String> map = {
"firstName": "John",
"lastName": "Smith",
"age": "25"
}
if (map instanceof
{
"firstName": var firstName,
"lastName": var lastName,
"age": Integer.toString(var age)
}) {
// firstName, lastName, age
// are binding variables
}
38. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
38
• Constant Patterns: checks the operand with a constant
value
• Type Patterns: checks if the operand has the right type,
casts it, and creates a binding variable
Patterns at a Glance
39. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
39
• Patterns + Deconstruction: checks the operand type,
casts it, bind the component to binding variables
• Patterns + Method: uses a factory method or a
deconstructor
• Patterns + Var: infers the right type, and creates the
binding variable
• Pattern + _: infers the right type, but does not create
the binding variable
Patterns at a Glance
40. 3/11/2022
Copyright © 2021, Oracle and/or its affiliates |
40
Where are we?
• Pattern Matching for instanceof
• Pattern Matching for Switch
• Record and Array Pattern Matching
• Match
• Literals
Patterns at a Glance