SlideShare a Scribd company logo
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
From Small Enhancement to Major Feature
From Small Enhancement to Major Feature
Hanno Embregts @hannotify
Pattern Matching: From Small Enhancement to Major Feature (talk from JavaLand 2021)
Small Enhancement
Small Enhancement
Small Enhancement
Small Enhancement
Small Enhancement
https://gph.is/g/ZPJNoPQ
Major Feature
Major Feature
Major Feature
Major Feature
Major Feature
https://thumbs.gfycat.com/De antElasticGadwall.webp
Pattern
Pattern
Pattern
Pattern
Pattern
Matching for
Matching for
Matching for
Matching for
Matching for
instanceof
instanceof
instanceof
instanceof
instanceof
https://pxhere.com/en/photo/752901
https://pxhere.com/en/photo/548063
Instanceof-and-cast
Instanceof-and-cast
if (product instanceof Guitar) {
Guitar lesPaul =
(Guitar) product;
// use lesPaul
}
1
2
3
4
5
Instanceof-and-cast
Instanceof-and-cast
if (product instanceof Guitar) { // 1. is product a Guitar?
1
Guitar lesPaul =
2
(Guitar) product;
3
// use lesPaul
4
}
5
Instanceof-and-cast
Instanceof-and-cast
(Guitar) product; // 2. perform conversion
if (product instanceof Guitar) { // 1. is product a Guitar?
1
Guitar lesPaul =
2
3
// use lesPaul
4
}
5
Instanceof-and-cast
Instanceof-and-cast
Guitar lesPaul = // 3. declare variable, bind value
if (product instanceof Guitar) { // 1. is product a Guitar?
1
2
(Guitar) product; // 2. perform conversion
3
// use lesPaul
4
}
5
Improve the situation
Improve the situation
if (product instanceof Guitar) { // 1. is product a Guitar?
Guitar lesPaul = // 3. declare variable, bind value
(Guitar) product; // 2. perform conversion
// use lesPaul
}
1
2
3
4
5
Improve the situation
Improve the situation
if (product instanceof Guitar lesPaul) {
// use lesPaul
}
1
2
3
Type pattern
Type pattern
Type pattern
Type pattern
Type pattern
Consists of a predicate that speci es
a type, along with a single binding
variable.
https://www.pexels.com/photo/person-holding-white-chalk-625219/
Pattern matching
Pattern matching
Pattern matching
Pattern matching
Pattern matching
Allows the conditional extraction of
components from objects to be
expressed more concisely and safely.
https://www.pexels.com/photo/person-holding-white-chalk-625219/
Declaring 'in the
Declaring 'in the
middle'
middle'
if (product instanceof Guitar lesPaul) {
// use lesPaul
}
1
2
3
Scoping
Scoping
'Regular' local variable ('block scoping')
'Regular' local variable ('block scoping')
The block in which it is declared.
void playTunedGuitar() {
Guitar lesPaul = new Guitar("Les Paul");
if (!lesPaul.isInTune()) {
Guitar fenderStrat = new Guitar("Fender Stratocaster");
fenderStrat.play();
}
}
1
2
3
4
5
6
7
8
Scoping
Scoping
'Regular' local variable ('block scoping')
'Regular' local variable ('block scoping')
The block in which it is declared.
void playTunedGuitar() {
Guitar lesPaul = new Guitar("Les Paul");
if (!lesPaul.isInTune()) {
Guitar fenderStrat = new Guitar("Fender Stratocaster");
fenderStrat.play();
// fenderStrat is in scope
}
// fenderStrat is not in scope
}
1
2
3
4
5
6
7
8
9
10
Scoping
Scoping
Pattern binding variable (' ow scoping')
Pattern binding variable (' ow scoping')
The set of places where it would de nitely be
assigned.
if (product instanceof Guitar lesPaul) {
// can use lesPaul here
} else {
// can't use lesPaul here
}
1
2
3
4
5
Scoping
Scoping
Pattern binding variable (' ow scoping')
Pattern binding variable (' ow scoping')
The set of places where it would de nitely be
assigned.
if (product instanceof Guitar lesPaul && lesPaul.isInTune()) {
// can use lesPaul here
} else {
// can't use lesPaul here
}
1
2
3
4
5
Scoping
Scoping
Pattern binding variable (' ow scoping')
Pattern binding variable (' ow scoping')
The set of places where it would de nitely be
assigned.
boolean isTunedGuitar(Object product) {
if (!(product instanceof Guitar lesPaul)) {
return false;
}
return lesPaul.isInTune();
}
1
2
3
4
5
6
7
Scoping
Scoping
Pattern binding variable (' ow scoping')
Pattern binding variable (' ow scoping')
The set of places where it would de nitely be
assigned.
boolean isTunedGuitar(Object product) {
if (!(product instanceof Guitar lesPaul)) {
return false;
}
// This code is only reachable if 'product' is
// a Guitar, so 'lesPaul' is in scope.
return lesPaul.isInTune();
}
1
2
3
4
5
6
7
8
9
Pattern Matching: From Small Enhancement to Major Feature (talk from JavaLand 2021)
Scoping
Scoping
Pattern binding variable (' ow scoping')
Pattern binding variable (' ow scoping')
The set of places where it would de nitely be
assigned.
void test(Effect effect) {
if (effect instanceof Reverb stockEffect)
stockEffect.setRoomSize(25);
else if (effect instanceof Delay stockEffect)
stockEffect.setTimeInMs(200);
}
1
2
3
4
5
6
Pattern Matching: From Small Enhancement to Major Feature (talk from JavaLand 2021)
Demo
Demo
Simplify implementation of equals
Loop through a set of Effects and apply 'pattern
matching for instanceof'
https://pxhere.com/en/photo/1458897
Bene ts
Bene ts
Nearly 100% of casts will just disappear!
More concise
Eliminates cut/paste errors
instanceof
instanceof grammar
grammar
The
The instanceof
instanceof grammar is extended accordingly:
grammar is extended accordingly:
RelationalExpression instanceof Pattern
Pattern:
ReferenceType Identifier
RelationalExpression:
1
...
2
RelationalExpression instanceof ReferenceType
3
4
5
6
7
https://openjdk.java.net/jeps/305
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
type pattern
Guitar lesPaul
https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
Feature Status
Feature Status
Java version Feature status JEP
14 Preview
15 Second preview
16 Final
JEP 305
JEP 375
JEP 394
Why so serious?
Why so serious?
Surely a less invasive approach exists?
Flow typing has been considered.
It infers re ned types based on past conditionals.
But... it is suited for instanceof checks only.
And pattern matching can be useful for more
language concepts!
https://pxhere.com/en/photo/835435
Pattern
Pattern
Pattern
Pattern
Pattern
Matching for
Matching for
Matching for
Matching for
Matching for
switch
switch
switch
switch
switch
https://pxhere.com/en/photo/752901
Disclaimer
Disclaimer
Disclaimer
Disclaimer
Disclaimer
I can't tell you when the following
features are coming to Java.
Also: syntax and implementation
speci cs may still change.
https://pxhere.com/en/photo/1359311
Pattern Matching: From Small Enhancement to Major Feature (talk from JavaLand 2021)
String apply(Effect effect) {
String formatted = "";
if (effect instanceof Delay) {
Delay de = (Delay) effect;
formatted = String.format("Delay active of %d ms.", de.getTim
} else if (effect instanceof Reverb) {
Reverb re = (Reverb) effect;
formatted = String.format("Reverb active of type %s and roomS
} else if (effect instanceof Overdrive) {
Overdrive ov = (Overdrive) effect;
formatted = String.format("Overdrive active with gain %d.", ov
} else if (effect instanceof Tremolo) {
Tremolo tr = (Tremolo) effect;
formatted = String.format("Tremolo active with depth %d and r
} else if (effect instanceof Tuner) {
Tuner tu = (Tuner) effect;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
formatted = String.format("Delay active of %d ms.", de.getTim
formatted = String.format("Reverb active of type %s and roomS
formatted = String.format("Overdrive active with gain %d.", ov
formatted = String.format("Tremolo active with depth %d and r
String apply(Effect effect) {
1
String formatted = "";
2
if (effect instanceof Delay) {
3
Delay de = (Delay) effect;
4
5
} else if (effect instanceof Reverb) {
6
Reverb re = (Reverb) effect;
7
8
} else if (effect instanceof Overdrive) {
9
Overdrive ov = (Overdrive) effect;
10
11
} else if (effect instanceof Tremolo) {
12
Tremolo tr = (Tremolo) effect;
13
14
} else if (effect instanceof Tuner) {
15
Tuner tu = (Tuner) effect;
16
String apply(Effect effect) {
String formatted = "";
if (effect instanceof Delay de) {
formatted = String.format("Delay active of %d ms.", de.getTim
} else if (effect instanceof Reverb re) {
formatted = String.format("Reverb active of type %s and roomS
} else if (effect instanceof Overdrive ov) {
formatted = String.format("Overdrive active with gain %d.", ov
} else if (effect instanceof Tremolo tr) {
formatted = String.format("Tremolo active with depth %d and r
} else if (effect instanceof Tuner tu) {
formatted = String.format("Tuner active with pitch %d. Muting
} else if (effect instanceof EffectLoop el) {
formatted = el.getEffects().stream().map(this::apply).collect
} else {
formatted = String format("Unknown effect active: %s " effect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
formatted = String.format("Delay active of %d ms.", de.getTim
formatted = String.format("Reverb active of type %s and roomS
formatted = String.format("Overdrive active with gain %d.", ov
formatted = String.format("Tremolo active with depth %d and r
formatted = String.format("Tuner active with pitch %d. Muting
formatted = el.getEffects().stream().map(this::apply).collect
formatted = String format("Unknown effect active: %s " effect
String apply(Effect effect) {
1
String formatted = "";
2
if (effect instanceof Delay de) {
3
4
} else if (effect instanceof Reverb re) {
5
6
} else if (effect instanceof Overdrive ov) {
7
8
} else if (effect instanceof Tremolo tr) {
9
10
} else if (effect instanceof Tuner tu) {
11
12
} else if (effect instanceof EffectLoop el) {
13
14
} else {
15
16
Switch expression
Switch expression
String apply(Effect effect) {
return switch(effect) {
default -> String.format("Unknown effect active: %s
};
}
1
2
3
4
5
Switch expression
Switch expression
case Delay de -> String.format("Delay active of %d ms.",
case Reverb re -> String.format("Reverb active of type %s
String apply(Effect effect) {
1
return switch(effect) {
2
3
4
default -> String.format("Unknown effect active: %s
5
};
6
}
7
Switch expression
Switch expression
case Overdrive ov -> String.format("Overdrive active with ga
case Tremolo tr -> String.format("Tremolo active with depth
case Tuner tu -> String.format("Tuner active with pitch
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.",
3
case Reverb re -> String.format("Reverb active of type %s
4
5
6
7
default -> String.format("Unknown effect active: %
8
};
9
}
10
Switch expression
Switch expression
case EffectLoop el -> el.getEffects().stream().map(this::apply
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.",
3
case Reverb re -> String.format("Reverb active of type %s
4
case Overdrive ov -> String.format("Overdrive active with ga
5
case Tremolo tr -> String.format("Tremolo active with depth
6
case Tuner tu -> String.format("Tuner active with pitch
7
8
default -> String.format("Unknown effect active: %
9
};
10
}
11
Switch expression
Switch expression
String apply(Effect effect) {
return switch(effect) {
case Delay de -> String.format("Delay active of %d ms.",
case Reverb re -> String.format("Reverb active of type %s
case Overdrive ov -> String.format("Overdrive active with ga
case Tremolo tr -> String.format("Tremolo active with depth
case Tuner tu -> String.format("Tuner active with pitch
case EffectLoop el -> el.getEffects().stream().map(this::apply
default -> String.format("Unknown effect active: %
};
}
1
2
3
4
5
6
7
8
9
10
11
Bene ts
Bene ts
A single expression instead of many assignments
Less error-prone (in adding cases)
More concise
Safer - the compiler can check for missing cases
switch
switch grammar
grammar
SwitchBlock:
{ SwitchRule {SwitchRule} }
{ {SwitchBlockStatementGroup} {SwitchLabel :} }
SwitchRule:
SwitchLabel -> Expression ;
SwitchLabel -> Block
SwitchLabel -> ThrowStatement
SwitchBlockStatementGroup:
SwitchLabel : {SwitchLabel :} BlockStatements
SwitchLabel:
case CaseConstant {, CaseConstant}
default
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-14.11
switch
switch grammar
grammar
case CaseConstant {, CaseConstant}
SwitchBlock:
1
{ SwitchRule {SwitchRule} }
2
{ {SwitchBlockStatementGroup} {SwitchLabel :} }
3
4
SwitchRule:
5
SwitchLabel -> Expression ;
6
SwitchLabel -> Block
7
SwitchLabel -> ThrowStatement
8
9
SwitchBlockStatementGroup:
10
SwitchLabel : {SwitchLabel :} BlockStatements
11
12
SwitchLabel:
13
14
default
15
16
https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-14.11
switch
switch grammar
grammar
case Pattern {, Pattern}
SwitchBlock:
1
{ SwitchRule {SwitchRule} }
2
{ {SwitchBlockStatementGroup} {SwitchLabel :} }
3
4
SwitchRule:
5
SwitchLabel -> Expression ;
6
SwitchLabel -> Block
7
SwitchLabel -> ThrowStatement
8
9
SwitchBlockStatementGroup:
10
SwitchLabel : {SwitchLabel :} BlockStatements
11
12
SwitchLabel:
13
14
default
15
16
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
constant pattern
GuitarType.TELECASTER
https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
Feature Status
Feature Status
Java
version
Feature
status
JEP
n/a Draft JEP draft
8213076
https://openjdk.java.net/jeps/8213076
Why so serious?
Why so serious?
Surely a less invasive approach exists?
Type switching has been considered.
It enables case labels to specify types, as well as
constants.
But... it is suited for switch statements only.
And pattern matching can be useful for more
language concepts!
https://pxhere.com/en/photo/835435
Deconstruction
Deconstruction
Deconstruction
Deconstruction
Deconstruction
Patterns
Patterns
Patterns
Patterns
Patterns
https://pxhere.com/en/photo/752901
Here be dragons!
Here be dragons!
Here be dragons!
Here be dragons!
Here be dragons!
We can't be sure at all that the
following features will appear in Java
as depicted. They can change a lot in
the meantime.
https://www.pexels.com/photo/dragon-festival-during-nighttime-6068535/
Deconstruction patterns
Deconstruction patterns
String apply(Effect effect) {
return switch(effect) {
case Delay de -> String.format("Delay active of %d ms.",
case Reverb re -> String.format("Reverb active of type %s
case Overdrive ov -> String.format("Overdrive active with ga
case Tremolo tr -> String.format("Tremolo active with depth
case Tuner tu -> String.format("Tuner active with pitch
case EffectLoop el -> el.getEffects().stream().map(this::apply
default -> String.format("Unknown effect active: %
};
}
1
2
3
4
5
6
7
8
9
10
11
Deconstruction patterns
Deconstruction patterns
case Overdrive(int gain) -> String.format("Overdrive active w
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.",
3
case Reverb re -> String.format("Reverb active of type %s
4
5
case Tremolo tr -> String.format("Tremolo active with depth
6
case Tuner tu -> String.format("Tuner active with pitch
7
case EffectLoop el -> el.getEffects().stream().map(this::apply
8
default -> String.format("Unknown effect active: %
9
};
10
}
11
Pattern de nition
Pattern de nition
public class Overdrive implements Effect {
private final int gain;
public Overdrive(int gain) {
this.gain = gain;
}
}
1
2
3
4
5
6
7
Pattern de nition
Pattern de nition
public pattern Overdrive(int gain) {
gain = this.gain;
}
public class Overdrive implements Effect {
1
private final int gain;
2
3
public Overdrive(int gain) {
4
this.gain = gain;
5
}
6
7
8
9
10
}
11
Deconstruction patterns
Deconstruction patterns
case Overdrive(int gain) -> String.format("Overdrive active w
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.",
3
case Reverb re -> String.format("Reverb active of type %s
4
5
case Tremolo tr -> String.format("Tremolo active with depth
6
case Tuner tu -> String.format("Tuner active with pitch
7
case EffectLoop el -> el.getEffects().stream().map(this::apply
8
default -> String.format("Unknown effect active: %
9
};
10
}
11
Deconstruction patterns
Deconstruction patterns
String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d
case Reverb(String name, int roomSize) -> String.format("Reve
case Overdrive(int gain) -> String.format("Overdrive active w
case Tremolo(int depth, int rate) -> String.format("Tremolo ac
case Tuner(int pitchInHz) -> String.format("Tuner active with
case EffectLoop(Set<Effect> effects) -> effects.stream().map(t
default -> String.format("Unknown effect active: %s.", effect
};
}
1
2
3
4
5
6
7
8
9
10
11
Pattern composition
Pattern composition
static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef
}
1
2
3
Pattern composition
Pattern composition
static boolean containsReverbAndDelayWithEqualProperties(EffectLoop e
return effectLoop.getEffects().stream()
.filter(e -> e instanceof Delay || e instanceof Reverb)
.map(dr -> {
if (dr instanceof Delay d) {
return d.getTimeInMs();
} else {
Reverb r = (Reverb) dr;
return r.getRoomSize();
}
}).distinct().count() == 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
Pattern composition
Pattern composition
static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef
if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(St
return timeInMs == roomSize;
}
return false;
}
1
2
3
4
5
6
Var and any patterns
Var and any patterns
// Pre-Java 10
Guitar telecaster = new Guitar("Fender Telecaster Baritone Blacktop", G
// Java 10
var telecaster = new Guitar("Fender Telecaster Baritone Blacktop", Gui
1
2
3
4
5
https://openjdk.java.net/jeps/286
Var and any patterns
Var and any patterns
static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef
if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(St
return timeInMs == roomSize;
}
return false;
}
1
2
3
4
5
6
Var and any patterns
Var and any patterns
if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(v
static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef
1
2
return timeInMs == roomSize;
3
}
4
return false;
5
}
6
http://gph.is/2lFlHIK
Var and any patterns
Var and any patterns
static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef
if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(_
return timeInMs == roomSize;
}
return false;
}
1
2
3
4
5
6
Optimization
Optimization
String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d
case Reverb(String name, int roomSize) -> String.format("Reve
case Overdrive(int gain) -> String.format("Overdrive active w
case Tremolo(int depth, int rate) -> String.format("Tremolo ac
case Tuner(int pitchInHz) -> String.format("Tuner active with
case EffectLoop(Set<Effect> effects) -> effects.stream().map(t
default -> String.format("Unknown effect active: %s.", effect
};
}
1
2
3
4
5
6
7
8
9
10
11
Optimization
Optimization
case EffectLoop(Set<Effect> effects) -> effects.stream().map(t
String apply(Effect effect) {
1
return switch(effect) {
2
// ...
3
4
default -> String.format("Unknown effect active: %s.", effect)
5
};
6
}
7
Optimization
Optimization
case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The
case EffectLoop(Set<Effect> effects) -> effects.stream().map(t
String apply(Effect effect) {
1
return switch(effect) {
2
// ...
3
4
5
default -> String.format("Unknown effect active: %s.", effect)
6
};
7
}
8
Bene ts
Bene ts
Better encapsulation
a case branch only receives data that it actually references.
More elegant logic
by using pattern composition
Optimization
through the use of any patterns
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
deconstruction pattern
Delay(int timeInMs)
https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
var pattern
var timeInMs
https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
It's a kind of Pattern
any pattern
_
https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
Feature Status
Feature Status
Java
version
Feature status JEP
n/a Exploratory
document
Pattern Matching
for Java
https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
Pattern Matching Plays
Pattern Matching Plays
Nice With
Nice With
Sealed Types
Sealed Types
Sealed Types
Sealed Types
Sealed Types
and Records
and Records
and Records
and Records
and Records
https://pxhere.com/en/photo/752901
Demo
Demo
Convert e ect classes to a record
Acquire constructor, accessor methods etc.
https://pxhere.com/en/photo/1458897
Records
Records
Input:
Input:
Commit to the class being a transparent carrier for
its data.
Records
Records
Input:
Input:
Commit to the class being a transparent carrier for
its data.
Output:
Output:
constructors
accessor methods
equals()-implementation
hashCode()-implementation
toString()-implementation
deconstruction pattern
Demo
Demo
Make Effect a sealed type
Make subclasses final, sealed or non sealed
https://pxhere.com/en/photo/1458897
Exhaustiveness
Exhaustiveness
String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d
case Reverb(String name, int roomSize) -> String.format("Reve
case Overdrive(int gain) -> String.format("Overdrive active w
case Tremolo(int depth, int rate) -> String.format("Tremolo ac
case Tuner(int pitchInHz) -> String.format("Tuner active with
case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The
case EffectLoop(Set<Effect> effects) -> effects.stream().map(t
default -> String.format("Unknown effect active: %s.", effect
};
}
1
2
3
4
5
6
7
8
9
10
11
12
Exhaustiveness
Exhaustiveness
String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d
case Reverb(String name, int roomSize) -> String.format("Reve
case Overdrive(int gain) -> String.format("Overdrive active w
case Tremolo(int depth, int rate) -> String.format("Tremolo ac
case Tuner(int pitchInHz) -> String.format("Tuner active with
case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The
case EffectLoop(Set<Effect> effects) -> effects.stream().map(t
};
}
1
2
3
4
5
6
7
8
9
10
11
https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
Feature Status
Feature Status
Records
Records
Java version Feature status JEP
14 Preview
15 Second preview
16 Final
JEP 359
JEP 384
JEP 395
Feature Status
Feature Status
Sealed Types
Sealed Types
Java version Feature status JEP
15 Preview
16 Second preview
17 Final ...
JEP 360
JEP 397
A Better
A Better
A Better
A Better
A Better
Serialization
Serialization
Serialization
Serialization
Serialization
?
?
?
?
?
Here be dragons!
Here be dragons!
Here be dragons!
Here be dragons!
Here be dragons!
We can't be sure at all that the
following features will appear in Java
as depicted. They can change a lot in
the meantime.
https://www.pexels.com/photo/dragon-festival-during-nighttime-6068535/
Opposites
Opposites
Deconstruction pattern
Deconstruction pattern
transforms an object into a set of typed elds
Constructor
Constructor
transforms a set of typed elds into an object
Serialization
Serialization
very important feature
but many people hate its current implementation
Drawbacks
Drawbacks
it undermines the accessibility model
serialization logic is not 'readable code'
it bypasses constructors and data validation
Serialization
Serialization
public class EffectLoop implements Effect {
private String name;
private Set<Effect> effects;
public EffectLoop(String name) {
this.name = name;
this.effects = new HashSet<>();
}
}
1
2
3
4
5
6
7
8
9
Serialization
Serialization
public pattern EffectLoop(String name, Effect[] effects) {
name = this.name;
effects = this.effects.toArray();
}
public class EffectLoop implements Effect {
1
private String name;
2
private Set<Effect> effects;
3
4
public EffectLoop(String name) {
5
this.name = name;
6
this.effects = new HashSet<>();
7
}
8
9
10
11
12
13
}
14
Serialization
Serialization
public static Effectloop deserialize(String name, Effect[] effect
EffectLoop effectLoop = new EffectLoop(name);
for (Effect effect : effects) {
this.effects.add(effect);
}
return effectLoop;
public class EffectLoop implements Effect {
1
private String name;
2
private Set<Effect> effects;
3
4
public EffectLoop(String name) {
5
this.name = name;
6
this.effects = new HashSet<>();
7
}
8
9
10
11
12
13
14
15
}
16
Serialization
Serialization
public class EffectLoop implements Effect {
private String name;
private Set<Effect> effects;
public EffectLoop(String name) {
this.name = name;
this.effects = new HashSet<>();
}
@Deserializer
public static Effectloop deserialize(String name, Effect[] effect
EffectLoop effectLoop = new EffectLoop(name);
for (Effect effect : effects) {
this.effects.add(effect);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Some challenges remain
Some challenges remain
Q:
Q: How to support multiple versions of one class?
How to support multiple versions of one class?
A: @Serializer and @Deserializer annotations
could get a property version in the future.
Feature Status
Feature Status
Java
version
Feature status JEP
n/a Exploratory
document
Towards Better
Serialization
https://cr.openjdk.java.net/~briangoetz/amber/serialization.html
Future
Future
Future
Future
Future
Expansions
Expansions
Expansions
Expansions
Expansions
https://pxhere.com/en/photo/752901
Here be super dragons!
Here be super dragons!
Here be super dragons!
Here be super dragons!
Here be super dragons!
We can't be sure that the following
features will appear in Java as
depicted, if at all.
Proceed with caution!
https://www.pexels.com/photo/dragon-festival-during-nighttime-6068535/
Pattern bind statements
Pattern bind statements
var reverb = new Reverb("ChamberReverb", 2);
__let Reverb(String name, int roomSize) = reverb;
// do something with name & roomSize
1
2
3
4
5
https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
Pattern bind statements
Pattern bind statements
else throw new IllegalArgumentException("not a Reverb!");
var reverb = new Reverb("ChamberReverb", 2);
1
2
__let Reverb(String name, int roomSize) = reverb;
3
4
5
// do something with name & roomSize
6
Guards
Guards
String apply(Effect effect, Guitar guitar) {
1
return switch(effect) {
2
// (...)
3
case Tremolo tr-> String.format("Tremolo active with depth %d
4
case Tuner tu -> String.format("Tuner active with pitch %d. Mut
5
case EffectLoop el -> el.getEffects().stream().map(this::apply
6
default -> String.format("Unknown effect active: %s.", effect)
7
};
8
}
9
https://openjdk.java.net/jeps/8213076
Guards
Guards
case Tuner tu && !tu.isInTune(guitar) -> String.format("Guitar
String apply(Effect effect, Guitar guitar) {
1
return switch(effect) {
2
// (...)
3
case Tremolo tr-> String.format("Tremolo active with depth %d
4
5
case EffectLoop el -> el.getEffects().stream().map(this::apply
6
default -> String.format("Unknown effect active: %s.", effect)
7
};
8
}
9
Other ideas
Other ideas
Array patterns
Varargs patterns
AND patterns
Patterns in catch clauses
Collection patterns
Record patterns
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-January/002758.html
Pattern
Pattern
Pattern
Pattern
Pattern
Kinds and
Kinds and
Kinds and
Kinds and
Kinds and
Contexts
Contexts
Contexts
Contexts
Contexts
Pattern Kinds
Pattern Kinds
Pattern kind Example Purpose
type pattern Guitar lesPaul Perform an instanceof test,
cast the target, and bind it
to a pattern variable.
constant
pattern
GuitarType.TELECASTER Test the target for equality
with a constant.
deconstruction
pattern
Delay(int timeInMs) Perform an instanceof test,
cast the target, destructure
the target and recursively
match the components to
subpatterns.
var pattern var timeInMs Match anything and bind its
target.
any pattern _ Match anything, but bind
nothing.
Pattern Contexts
Pattern Contexts
Pattern
context
Example Purpose
instanceof
predicate
product instanceof
Guitar guitar
Test if target matches the
indicated pattern.
switch
statement or
expression
switch (effect) {
    case Delay d
}
Test if target matches one
(or more) of the indicated
patterns.
bind
statement
let Reverb(var
name, var roomSize) =
reverb;
Destructure a target using a
pattern.
Wrap-up
Wrap-up
Wrap-up
Wrap-up
Wrap-up
https://pxhere.com/en/photo/752901
Pattern matching...
Pattern matching...
is a rich feature arc that will play out over several
versions.
allows us to use type patterns in instanceof.
improves switch expressions.
makes destructuring objects as easy (and more
similar to) constructing them.
holds the potential to simplify and streamline much
of the code we write today.
Major Feature
Major Feature
Major Feature
Major Feature
Major Feature
Thank you! ☺
Thank you! ☺
bit.do/javaland-pattern-
matching
github.com/hannotify/pattern-
matching-music-store
hannotify.github.io
@hannotify

More Related Content

PDF
Pattern Matching: Small Enhancement or Major Feature? (talk from jLove 2021)
PDF
Pattern Matching: Small Enhancement or Major Feature?
PDF
Mc Squared
PDF
Geeks Anonymes - Le langage Go
PPTX
A Prettier Printer
PDF
Unit testing with PHPUnit
Pattern Matching: Small Enhancement or Major Feature? (talk from jLove 2021)
Pattern Matching: Small Enhancement or Major Feature?
Mc Squared
Geeks Anonymes - Le langage Go
A Prettier Printer
Unit testing with PHPUnit

What's hot (10)

PPTX
Load-time Hacking using LD_PRELOAD
PPT
Concurrency in go
PDF
Grammatical Optimization
PDF
Input and Output
PDF
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
PPT
Functional Programming In Java
PDF
Perl Testing
PDF
Control Flow
PDF
Functional programming in java
Load-time Hacking using LD_PRELOAD
Concurrency in go
Grammatical Optimization
Input and Output
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
Functional Programming In Java
Perl Testing
Control Flow
Functional programming in java
Ad

Similar to Pattern Matching: From Small Enhancement to Major Feature (talk from JavaLand 2021) (20)

PDF
Pattern Matching: Small Enhancement or Major Feature?
PDF
Pattern Matching - Small Enhancement or Major Feature? from Developer Week 202
ODP
What's new in Perl 5.10?
ODP
Ast transformations
ODP
AST Transformations at JFokus
PDF
How I learned to stop fucking and love MarionetteJS
PDF
Symfony 4 Workshop - Limenius
PPTX
Android & Kotlin - The code awakens #03
PPTX
Groovy
PDF
Real life-coffeescript
ODP
Naïveté vs. Experience
PPT
Filmstrip testing
PDF
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
PPT
Os Secoske
PDF
7 Common Mistakes in Go (2015)
PDF
Einführung in TypeScript
KEY
PDF
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
PPT
JSConf: All You Can Leet
PPTX
Ultimate Node.js countdown: the coolest Application Express examples
Pattern Matching: Small Enhancement or Major Feature?
Pattern Matching - Small Enhancement or Major Feature? from Developer Week 202
What's new in Perl 5.10?
Ast transformations
AST Transformations at JFokus
How I learned to stop fucking and love MarionetteJS
Symfony 4 Workshop - Limenius
Android & Kotlin - The code awakens #03
Groovy
Real life-coffeescript
Naïveté vs. Experience
Filmstrip testing
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Os Secoske
7 Common Mistakes in Go (2015)
Einführung in TypeScript
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
JSConf: All You Can Leet
Ultimate Node.js countdown: the coolest Application Express examples
Ad

More from 🎤 Hanno Embregts 🎸 (16)

PDF
"Will Git Be Around Forever? A List of Possible Successors" from Devoxx 2022
PDF
"Will Git Be Around Forever? A List of Possible Successors" from FrontMania 2022
PDF
JCON 2021 talk - "Wil Git Be Around Forever? A List of Possible Successors"
PDF
"Will Git Be Around Forever? A List of Possible Successors" at UtrechtJUG
PDF
Entering the Fourth Dimension of OCR with Tesseract
PDF
The Soft Side of Software Development / Devoxx 2019
PDF
Beware of Survivorship Bias! (conference talk at J-Fall 2019)
PDF
Will Git Be Around Forever? A List of Possible Successors
PDF
Entering the Fourth Dimension of OCR with Tesseract - Talk from Voxxed Days B...
PDF
QWERTY or DVORAK? Debunking the Keyboard Layout Myths -- from GeeCON 2018
PDF
Building a Spring Boot 2 Application - Ask the Audience! (from Voxxed Days Vi...
PDF
Building a Spring Boot Application - Ask the Audience! (from JVMCon 2018)
PDF
Building a Spring Boot Application - Ask the Audience!
PDF
QWERTY or DVORAK? Debunking the Keyboard Layout Myths
PDF
Building a Spring Boot Application - Ask the Audience! (from JavaLand 2017)
PDF
Migrating 25K lines of Ant scripting to Gradle
"Will Git Be Around Forever? A List of Possible Successors" from Devoxx 2022
"Will Git Be Around Forever? A List of Possible Successors" from FrontMania 2022
JCON 2021 talk - "Wil Git Be Around Forever? A List of Possible Successors"
"Will Git Be Around Forever? A List of Possible Successors" at UtrechtJUG
Entering the Fourth Dimension of OCR with Tesseract
The Soft Side of Software Development / Devoxx 2019
Beware of Survivorship Bias! (conference talk at J-Fall 2019)
Will Git Be Around Forever? A List of Possible Successors
Entering the Fourth Dimension of OCR with Tesseract - Talk from Voxxed Days B...
QWERTY or DVORAK? Debunking the Keyboard Layout Myths -- from GeeCON 2018
Building a Spring Boot 2 Application - Ask the Audience! (from Voxxed Days Vi...
Building a Spring Boot Application - Ask the Audience! (from JVMCon 2018)
Building a Spring Boot Application - Ask the Audience!
QWERTY or DVORAK? Debunking the Keyboard Layout Myths
Building a Spring Boot Application - Ask the Audience! (from JavaLand 2017)
Migrating 25K lines of Ant scripting to Gradle

Recently uploaded (20)

PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
assetexplorer- product-overview - presentation
PDF
top salesforce developer skills in 2025.pdf
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Digital Strategies for Manufacturing Companies
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
history of c programming in notes for students .pptx
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
System and Network Administraation Chapter 3
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
medical staffing services at VALiNTRY
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Softaken Excel to vCard Converter Software.pdf
assetexplorer- product-overview - presentation
top salesforce developer skills in 2025.pdf
Upgrade and Innovation Strategies for SAP ERP Customers
How to Choose the Right IT Partner for Your Business in Malaysia
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Design an Analysis of Algorithms I-SECS-1021-03
Odoo Companies in India – Driving Business Transformation.pdf
Digital Strategies for Manufacturing Companies
Design an Analysis of Algorithms II-SECS-1021-03
Navsoft: AI-Powered Business Solutions & Custom Software Development
history of c programming in notes for students .pptx
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
System and Network Administraation Chapter 3
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Wondershare Filmora 15 Crack With Activation Key [2025
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
medical staffing services at VALiNTRY

Pattern Matching: From Small Enhancement to Major Feature (talk from JavaLand 2021)

  • 3. Small Enhancement Small Enhancement Small Enhancement Small Enhancement Small Enhancement https://gph.is/g/ZPJNoPQ
  • 4. Major Feature Major Feature Major Feature Major Feature Major Feature https://thumbs.gfycat.com/De antElasticGadwall.webp
  • 5. Pattern Pattern Pattern Pattern Pattern Matching for Matching for Matching for Matching for Matching for instanceof instanceof instanceof instanceof instanceof https://pxhere.com/en/photo/752901
  • 7. Instanceof-and-cast Instanceof-and-cast if (product instanceof Guitar) { Guitar lesPaul = (Guitar) product; // use lesPaul } 1 2 3 4 5
  • 8. Instanceof-and-cast Instanceof-and-cast if (product instanceof Guitar) { // 1. is product a Guitar? 1 Guitar lesPaul = 2 (Guitar) product; 3 // use lesPaul 4 } 5
  • 9. Instanceof-and-cast Instanceof-and-cast (Guitar) product; // 2. perform conversion if (product instanceof Guitar) { // 1. is product a Guitar? 1 Guitar lesPaul = 2 3 // use lesPaul 4 } 5
  • 10. Instanceof-and-cast Instanceof-and-cast Guitar lesPaul = // 3. declare variable, bind value if (product instanceof Guitar) { // 1. is product a Guitar? 1 2 (Guitar) product; // 2. perform conversion 3 // use lesPaul 4 } 5
  • 11. Improve the situation Improve the situation if (product instanceof Guitar) { // 1. is product a Guitar? Guitar lesPaul = // 3. declare variable, bind value (Guitar) product; // 2. perform conversion // use lesPaul } 1 2 3 4 5
  • 12. Improve the situation Improve the situation if (product instanceof Guitar lesPaul) { // use lesPaul } 1 2 3
  • 13. Type pattern Type pattern Type pattern Type pattern Type pattern Consists of a predicate that speci es a type, along with a single binding variable. https://www.pexels.com/photo/person-holding-white-chalk-625219/
  • 14. Pattern matching Pattern matching Pattern matching Pattern matching Pattern matching Allows the conditional extraction of components from objects to be expressed more concisely and safely. https://www.pexels.com/photo/person-holding-white-chalk-625219/
  • 15. Declaring 'in the Declaring 'in the middle' middle' if (product instanceof Guitar lesPaul) { // use lesPaul } 1 2 3
  • 16. Scoping Scoping 'Regular' local variable ('block scoping') 'Regular' local variable ('block scoping') The block in which it is declared. void playTunedGuitar() { Guitar lesPaul = new Guitar("Les Paul"); if (!lesPaul.isInTune()) { Guitar fenderStrat = new Guitar("Fender Stratocaster"); fenderStrat.play(); } } 1 2 3 4 5 6 7 8
  • 17. Scoping Scoping 'Regular' local variable ('block scoping') 'Regular' local variable ('block scoping') The block in which it is declared. void playTunedGuitar() { Guitar lesPaul = new Guitar("Les Paul"); if (!lesPaul.isInTune()) { Guitar fenderStrat = new Guitar("Fender Stratocaster"); fenderStrat.play(); // fenderStrat is in scope } // fenderStrat is not in scope } 1 2 3 4 5 6 7 8 9 10
  • 18. Scoping Scoping Pattern binding variable (' ow scoping') Pattern binding variable (' ow scoping') The set of places where it would de nitely be assigned. if (product instanceof Guitar lesPaul) { // can use lesPaul here } else { // can't use lesPaul here } 1 2 3 4 5
  • 19. Scoping Scoping Pattern binding variable (' ow scoping') Pattern binding variable (' ow scoping') The set of places where it would de nitely be assigned. if (product instanceof Guitar lesPaul && lesPaul.isInTune()) { // can use lesPaul here } else { // can't use lesPaul here } 1 2 3 4 5
  • 20. Scoping Scoping Pattern binding variable (' ow scoping') Pattern binding variable (' ow scoping') The set of places where it would de nitely be assigned. boolean isTunedGuitar(Object product) { if (!(product instanceof Guitar lesPaul)) { return false; } return lesPaul.isInTune(); } 1 2 3 4 5 6 7
  • 21. Scoping Scoping Pattern binding variable (' ow scoping') Pattern binding variable (' ow scoping') The set of places where it would de nitely be assigned. boolean isTunedGuitar(Object product) { if (!(product instanceof Guitar lesPaul)) { return false; } // This code is only reachable if 'product' is // a Guitar, so 'lesPaul' is in scope. return lesPaul.isInTune(); } 1 2 3 4 5 6 7 8 9
  • 23. Scoping Scoping Pattern binding variable (' ow scoping') Pattern binding variable (' ow scoping') The set of places where it would de nitely be assigned. void test(Effect effect) { if (effect instanceof Reverb stockEffect) stockEffect.setRoomSize(25); else if (effect instanceof Delay stockEffect) stockEffect.setTimeInMs(200); } 1 2 3 4 5 6
  • 25. Demo Demo Simplify implementation of equals Loop through a set of Effects and apply 'pattern matching for instanceof' https://pxhere.com/en/photo/1458897
  • 26. Bene ts Bene ts Nearly 100% of casts will just disappear! More concise Eliminates cut/paste errors
  • 27. instanceof instanceof grammar grammar The The instanceof instanceof grammar is extended accordingly: grammar is extended accordingly: RelationalExpression instanceof Pattern Pattern: ReferenceType Identifier RelationalExpression: 1 ... 2 RelationalExpression instanceof ReferenceType 3 4 5 6 7 https://openjdk.java.net/jeps/305
  • 28. It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern type pattern Guitar lesPaul https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
  • 29. Feature Status Feature Status Java version Feature status JEP 14 Preview 15 Second preview 16 Final JEP 305 JEP 375 JEP 394
  • 30. Why so serious? Why so serious? Surely a less invasive approach exists? Flow typing has been considered. It infers re ned types based on past conditionals. But... it is suited for instanceof checks only. And pattern matching can be useful for more language concepts! https://pxhere.com/en/photo/835435
  • 31. Pattern Pattern Pattern Pattern Pattern Matching for Matching for Matching for Matching for Matching for switch switch switch switch switch https://pxhere.com/en/photo/752901
  • 32. Disclaimer Disclaimer Disclaimer Disclaimer Disclaimer I can't tell you when the following features are coming to Java. Also: syntax and implementation speci cs may still change. https://pxhere.com/en/photo/1359311
  • 34. String apply(Effect effect) { String formatted = ""; if (effect instanceof Delay) { Delay de = (Delay) effect; formatted = String.format("Delay active of %d ms.", de.getTim } else if (effect instanceof Reverb) { Reverb re = (Reverb) effect; formatted = String.format("Reverb active of type %s and roomS } else if (effect instanceof Overdrive) { Overdrive ov = (Overdrive) effect; formatted = String.format("Overdrive active with gain %d.", ov } else if (effect instanceof Tremolo) { Tremolo tr = (Tremolo) effect; formatted = String.format("Tremolo active with depth %d and r } else if (effect instanceof Tuner) { Tuner tu = (Tuner) effect; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 35. formatted = String.format("Delay active of %d ms.", de.getTim formatted = String.format("Reverb active of type %s and roomS formatted = String.format("Overdrive active with gain %d.", ov formatted = String.format("Tremolo active with depth %d and r String apply(Effect effect) { 1 String formatted = ""; 2 if (effect instanceof Delay) { 3 Delay de = (Delay) effect; 4 5 } else if (effect instanceof Reverb) { 6 Reverb re = (Reverb) effect; 7 8 } else if (effect instanceof Overdrive) { 9 Overdrive ov = (Overdrive) effect; 10 11 } else if (effect instanceof Tremolo) { 12 Tremolo tr = (Tremolo) effect; 13 14 } else if (effect instanceof Tuner) { 15 Tuner tu = (Tuner) effect; 16
  • 36. String apply(Effect effect) { String formatted = ""; if (effect instanceof Delay de) { formatted = String.format("Delay active of %d ms.", de.getTim } else if (effect instanceof Reverb re) { formatted = String.format("Reverb active of type %s and roomS } else if (effect instanceof Overdrive ov) { formatted = String.format("Overdrive active with gain %d.", ov } else if (effect instanceof Tremolo tr) { formatted = String.format("Tremolo active with depth %d and r } else if (effect instanceof Tuner tu) { formatted = String.format("Tuner active with pitch %d. Muting } else if (effect instanceof EffectLoop el) { formatted = el.getEffects().stream().map(this::apply).collect } else { formatted = String format("Unknown effect active: %s " effect 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 37. formatted = String.format("Delay active of %d ms.", de.getTim formatted = String.format("Reverb active of type %s and roomS formatted = String.format("Overdrive active with gain %d.", ov formatted = String.format("Tremolo active with depth %d and r formatted = String.format("Tuner active with pitch %d. Muting formatted = el.getEffects().stream().map(this::apply).collect formatted = String format("Unknown effect active: %s " effect String apply(Effect effect) { 1 String formatted = ""; 2 if (effect instanceof Delay de) { 3 4 } else if (effect instanceof Reverb re) { 5 6 } else if (effect instanceof Overdrive ov) { 7 8 } else if (effect instanceof Tremolo tr) { 9 10 } else if (effect instanceof Tuner tu) { 11 12 } else if (effect instanceof EffectLoop el) { 13 14 } else { 15 16
  • 38. Switch expression Switch expression String apply(Effect effect) { return switch(effect) { default -> String.format("Unknown effect active: %s }; } 1 2 3 4 5
  • 39. Switch expression Switch expression case Delay de -> String.format("Delay active of %d ms.", case Reverb re -> String.format("Reverb active of type %s String apply(Effect effect) { 1 return switch(effect) { 2 3 4 default -> String.format("Unknown effect active: %s 5 }; 6 } 7
  • 40. Switch expression Switch expression case Overdrive ov -> String.format("Overdrive active with ga case Tremolo tr -> String.format("Tremolo active with depth case Tuner tu -> String.format("Tuner active with pitch String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", 3 case Reverb re -> String.format("Reverb active of type %s 4 5 6 7 default -> String.format("Unknown effect active: % 8 }; 9 } 10
  • 41. Switch expression Switch expression case EffectLoop el -> el.getEffects().stream().map(this::apply String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", 3 case Reverb re -> String.format("Reverb active of type %s 4 case Overdrive ov -> String.format("Overdrive active with ga 5 case Tremolo tr -> String.format("Tremolo active with depth 6 case Tuner tu -> String.format("Tuner active with pitch 7 8 default -> String.format("Unknown effect active: % 9 }; 10 } 11
  • 42. Switch expression Switch expression String apply(Effect effect) { return switch(effect) { case Delay de -> String.format("Delay active of %d ms.", case Reverb re -> String.format("Reverb active of type %s case Overdrive ov -> String.format("Overdrive active with ga case Tremolo tr -> String.format("Tremolo active with depth case Tuner tu -> String.format("Tuner active with pitch case EffectLoop el -> el.getEffects().stream().map(this::apply default -> String.format("Unknown effect active: % }; } 1 2 3 4 5 6 7 8 9 10 11
  • 43. Bene ts Bene ts A single expression instead of many assignments Less error-prone (in adding cases) More concise Safer - the compiler can check for missing cases
  • 44. switch switch grammar grammar SwitchBlock: { SwitchRule {SwitchRule} } { {SwitchBlockStatementGroup} {SwitchLabel :} } SwitchRule: SwitchLabel -> Expression ; SwitchLabel -> Block SwitchLabel -> ThrowStatement SwitchBlockStatementGroup: SwitchLabel : {SwitchLabel :} BlockStatements SwitchLabel: case CaseConstant {, CaseConstant} default 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-14.11
  • 45. switch switch grammar grammar case CaseConstant {, CaseConstant} SwitchBlock: 1 { SwitchRule {SwitchRule} } 2 { {SwitchBlockStatementGroup} {SwitchLabel :} } 3 4 SwitchRule: 5 SwitchLabel -> Expression ; 6 SwitchLabel -> Block 7 SwitchLabel -> ThrowStatement 8 9 SwitchBlockStatementGroup: 10 SwitchLabel : {SwitchLabel :} BlockStatements 11 12 SwitchLabel: 13 14 default 15 16 https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-14.11
  • 46. switch switch grammar grammar case Pattern {, Pattern} SwitchBlock: 1 { SwitchRule {SwitchRule} } 2 { {SwitchBlockStatementGroup} {SwitchLabel :} } 3 4 SwitchRule: 5 SwitchLabel -> Expression ; 6 SwitchLabel -> Block 7 SwitchLabel -> ThrowStatement 8 9 SwitchBlockStatementGroup: 10 SwitchLabel : {SwitchLabel :} BlockStatements 11 12 SwitchLabel: 13 14 default 15 16
  • 47. It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern constant pattern GuitarType.TELECASTER https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
  • 48. Feature Status Feature Status Java version Feature status JEP n/a Draft JEP draft 8213076 https://openjdk.java.net/jeps/8213076
  • 49. Why so serious? Why so serious? Surely a less invasive approach exists? Type switching has been considered. It enables case labels to specify types, as well as constants. But... it is suited for switch statements only. And pattern matching can be useful for more language concepts! https://pxhere.com/en/photo/835435
  • 51. Here be dragons! Here be dragons! Here be dragons! Here be dragons! Here be dragons! We can't be sure at all that the following features will appear in Java as depicted. They can change a lot in the meantime. https://www.pexels.com/photo/dragon-festival-during-nighttime-6068535/
  • 52. Deconstruction patterns Deconstruction patterns String apply(Effect effect) { return switch(effect) { case Delay de -> String.format("Delay active of %d ms.", case Reverb re -> String.format("Reverb active of type %s case Overdrive ov -> String.format("Overdrive active with ga case Tremolo tr -> String.format("Tremolo active with depth case Tuner tu -> String.format("Tuner active with pitch case EffectLoop el -> el.getEffects().stream().map(this::apply default -> String.format("Unknown effect active: % }; } 1 2 3 4 5 6 7 8 9 10 11
  • 53. Deconstruction patterns Deconstruction patterns case Overdrive(int gain) -> String.format("Overdrive active w String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", 3 case Reverb re -> String.format("Reverb active of type %s 4 5 case Tremolo tr -> String.format("Tremolo active with depth 6 case Tuner tu -> String.format("Tuner active with pitch 7 case EffectLoop el -> el.getEffects().stream().map(this::apply 8 default -> String.format("Unknown effect active: % 9 }; 10 } 11
  • 54. Pattern de nition Pattern de nition public class Overdrive implements Effect { private final int gain; public Overdrive(int gain) { this.gain = gain; } } 1 2 3 4 5 6 7
  • 55. Pattern de nition Pattern de nition public pattern Overdrive(int gain) { gain = this.gain; } public class Overdrive implements Effect { 1 private final int gain; 2 3 public Overdrive(int gain) { 4 this.gain = gain; 5 } 6 7 8 9 10 } 11
  • 56. Deconstruction patterns Deconstruction patterns case Overdrive(int gain) -> String.format("Overdrive active w String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", 3 case Reverb re -> String.format("Reverb active of type %s 4 5 case Tremolo tr -> String.format("Tremolo active with depth 6 case Tuner tu -> String.format("Tuner active with pitch 7 case EffectLoop el -> el.getEffects().stream().map(this::apply 8 default -> String.format("Unknown effect active: % 9 }; 10 } 11
  • 57. Deconstruction patterns Deconstruction patterns String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d case Reverb(String name, int roomSize) -> String.format("Reve case Overdrive(int gain) -> String.format("Overdrive active w case Tremolo(int depth, int rate) -> String.format("Tremolo ac case Tuner(int pitchInHz) -> String.format("Tuner active with case EffectLoop(Set<Effect> effects) -> effects.stream().map(t default -> String.format("Unknown effect active: %s.", effect }; } 1 2 3 4 5 6 7 8 9 10 11
  • 58. Pattern composition Pattern composition static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef } 1 2 3
  • 59. Pattern composition Pattern composition static boolean containsReverbAndDelayWithEqualProperties(EffectLoop e return effectLoop.getEffects().stream() .filter(e -> e instanceof Delay || e instanceof Reverb) .map(dr -> { if (dr instanceof Delay d) { return d.getTimeInMs(); } else { Reverb r = (Reverb) dr; return r.getRoomSize(); } }).distinct().count() == 1; } 1 2 3 4 5 6 7 8 9 10 11 12 13
  • 60. Pattern composition Pattern composition static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(St return timeInMs == roomSize; } return false; } 1 2 3 4 5 6
  • 61. Var and any patterns Var and any patterns // Pre-Java 10 Guitar telecaster = new Guitar("Fender Telecaster Baritone Blacktop", G // Java 10 var telecaster = new Guitar("Fender Telecaster Baritone Blacktop", Gui 1 2 3 4 5 https://openjdk.java.net/jeps/286
  • 62. Var and any patterns Var and any patterns static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(St return timeInMs == roomSize; } return false; } 1 2 3 4 5 6
  • 63. Var and any patterns Var and any patterns if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(v static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef 1 2 return timeInMs == roomSize; 3 } 4 return false; 5 } 6
  • 65. Var and any patterns Var and any patterns static boolean containsReverbAndDelayWithEqualProperties(EffectLoop ef if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(_ return timeInMs == roomSize; } return false; } 1 2 3 4 5 6
  • 66. Optimization Optimization String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d case Reverb(String name, int roomSize) -> String.format("Reve case Overdrive(int gain) -> String.format("Overdrive active w case Tremolo(int depth, int rate) -> String.format("Tremolo ac case Tuner(int pitchInHz) -> String.format("Tuner active with case EffectLoop(Set<Effect> effects) -> effects.stream().map(t default -> String.format("Unknown effect active: %s.", effect }; } 1 2 3 4 5 6 7 8 9 10 11
  • 67. Optimization Optimization case EffectLoop(Set<Effect> effects) -> effects.stream().map(t String apply(Effect effect) { 1 return switch(effect) { 2 // ... 3 4 default -> String.format("Unknown effect active: %s.", effect) 5 }; 6 } 7
  • 68. Optimization Optimization case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The case EffectLoop(Set<Effect> effects) -> effects.stream().map(t String apply(Effect effect) { 1 return switch(effect) { 2 // ... 3 4 5 default -> String.format("Unknown effect active: %s.", effect) 6 }; 7 } 8
  • 69. Bene ts Bene ts Better encapsulation a case branch only receives data that it actually references. More elegant logic by using pattern composition Optimization through the use of any patterns
  • 70. It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern deconstruction pattern Delay(int timeInMs) https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
  • 71. It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern var pattern var timeInMs https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
  • 72. It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern It's a kind of Pattern any pattern _ https://www.pexels.com/photo/gray-metal-statue-of-man-raising-hand-near-dock-825430/
  • 73. Feature Status Feature Status Java version Feature status JEP n/a Exploratory document Pattern Matching for Java https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
  • 74. Pattern Matching Plays Pattern Matching Plays Nice With Nice With Sealed Types Sealed Types Sealed Types Sealed Types Sealed Types and Records and Records and Records and Records and Records https://pxhere.com/en/photo/752901
  • 75. Demo Demo Convert e ect classes to a record Acquire constructor, accessor methods etc. https://pxhere.com/en/photo/1458897
  • 76. Records Records Input: Input: Commit to the class being a transparent carrier for its data.
  • 77. Records Records Input: Input: Commit to the class being a transparent carrier for its data. Output: Output: constructors accessor methods equals()-implementation hashCode()-implementation toString()-implementation deconstruction pattern
  • 78. Demo Demo Make Effect a sealed type Make subclasses final, sealed or non sealed https://pxhere.com/en/photo/1458897
  • 79. Exhaustiveness Exhaustiveness String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d case Reverb(String name, int roomSize) -> String.format("Reve case Overdrive(int gain) -> String.format("Overdrive active w case Tremolo(int depth, int rate) -> String.format("Tremolo ac case Tuner(int pitchInHz) -> String.format("Tuner active with case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The case EffectLoop(Set<Effect> effects) -> effects.stream().map(t default -> String.format("Unknown effect active: %s.", effect }; } 1 2 3 4 5 6 7 8 9 10 11 12
  • 80. Exhaustiveness Exhaustiveness String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d case Reverb(String name, int roomSize) -> String.format("Reve case Overdrive(int gain) -> String.format("Overdrive active w case Tremolo(int depth, int rate) -> String.format("Tremolo ac case Tuner(int pitchInHz) -> String.format("Tuner active with case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The case EffectLoop(Set<Effect> effects) -> effects.stream().map(t }; } 1 2 3 4 5 6 7 8 9 10 11 https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
  • 81. Feature Status Feature Status Records Records Java version Feature status JEP 14 Preview 15 Second preview 16 Final JEP 359 JEP 384 JEP 395
  • 82. Feature Status Feature Status Sealed Types Sealed Types Java version Feature status JEP 15 Preview 16 Second preview 17 Final ... JEP 360 JEP 397
  • 83. A Better A Better A Better A Better A Better Serialization Serialization Serialization Serialization Serialization ? ? ? ? ?
  • 84. Here be dragons! Here be dragons! Here be dragons! Here be dragons! Here be dragons! We can't be sure at all that the following features will appear in Java as depicted. They can change a lot in the meantime. https://www.pexels.com/photo/dragon-festival-during-nighttime-6068535/
  • 85. Opposites Opposites Deconstruction pattern Deconstruction pattern transforms an object into a set of typed elds Constructor Constructor transforms a set of typed elds into an object
  • 86. Serialization Serialization very important feature but many people hate its current implementation Drawbacks Drawbacks it undermines the accessibility model serialization logic is not 'readable code' it bypasses constructors and data validation
  • 87. Serialization Serialization public class EffectLoop implements Effect { private String name; private Set<Effect> effects; public EffectLoop(String name) { this.name = name; this.effects = new HashSet<>(); } } 1 2 3 4 5 6 7 8 9
  • 88. Serialization Serialization public pattern EffectLoop(String name, Effect[] effects) { name = this.name; effects = this.effects.toArray(); } public class EffectLoop implements Effect { 1 private String name; 2 private Set<Effect> effects; 3 4 public EffectLoop(String name) { 5 this.name = name; 6 this.effects = new HashSet<>(); 7 } 8 9 10 11 12 13 } 14
  • 89. Serialization Serialization public static Effectloop deserialize(String name, Effect[] effect EffectLoop effectLoop = new EffectLoop(name); for (Effect effect : effects) { this.effects.add(effect); } return effectLoop; public class EffectLoop implements Effect { 1 private String name; 2 private Set<Effect> effects; 3 4 public EffectLoop(String name) { 5 this.name = name; 6 this.effects = new HashSet<>(); 7 } 8 9 10 11 12 13 14 15 } 16
  • 90. Serialization Serialization public class EffectLoop implements Effect { private String name; private Set<Effect> effects; public EffectLoop(String name) { this.name = name; this.effects = new HashSet<>(); } @Deserializer public static Effectloop deserialize(String name, Effect[] effect EffectLoop effectLoop = new EffectLoop(name); for (Effect effect : effects) { this.effects.add(effect); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 91. Some challenges remain Some challenges remain Q: Q: How to support multiple versions of one class? How to support multiple versions of one class? A: @Serializer and @Deserializer annotations could get a property version in the future.
  • 92. Feature Status Feature Status Java version Feature status JEP n/a Exploratory document Towards Better Serialization https://cr.openjdk.java.net/~briangoetz/amber/serialization.html
  • 94. Here be super dragons! Here be super dragons! Here be super dragons! Here be super dragons! Here be super dragons! We can't be sure that the following features will appear in Java as depicted, if at all. Proceed with caution! https://www.pexels.com/photo/dragon-festival-during-nighttime-6068535/
  • 95. Pattern bind statements Pattern bind statements var reverb = new Reverb("ChamberReverb", 2); __let Reverb(String name, int roomSize) = reverb; // do something with name & roomSize 1 2 3 4 5 https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
  • 96. Pattern bind statements Pattern bind statements else throw new IllegalArgumentException("not a Reverb!"); var reverb = new Reverb("ChamberReverb", 2); 1 2 __let Reverb(String name, int roomSize) = reverb; 3 4 5 // do something with name & roomSize 6
  • 97. Guards Guards String apply(Effect effect, Guitar guitar) { 1 return switch(effect) { 2 // (...) 3 case Tremolo tr-> String.format("Tremolo active with depth %d 4 case Tuner tu -> String.format("Tuner active with pitch %d. Mut 5 case EffectLoop el -> el.getEffects().stream().map(this::apply 6 default -> String.format("Unknown effect active: %s.", effect) 7 }; 8 } 9 https://openjdk.java.net/jeps/8213076
  • 98. Guards Guards case Tuner tu && !tu.isInTune(guitar) -> String.format("Guitar String apply(Effect effect, Guitar guitar) { 1 return switch(effect) { 2 // (...) 3 case Tremolo tr-> String.format("Tremolo active with depth %d 4 5 case EffectLoop el -> el.getEffects().stream().map(this::apply 6 default -> String.format("Unknown effect active: %s.", effect) 7 }; 8 } 9
  • 99. Other ideas Other ideas Array patterns Varargs patterns AND patterns Patterns in catch clauses Collection patterns Record patterns https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-January/002758.html
  • 100. Pattern Pattern Pattern Pattern Pattern Kinds and Kinds and Kinds and Kinds and Kinds and Contexts Contexts Contexts Contexts Contexts
  • 101. Pattern Kinds Pattern Kinds Pattern kind Example Purpose type pattern Guitar lesPaul Perform an instanceof test, cast the target, and bind it to a pattern variable. constant pattern GuitarType.TELECASTER Test the target for equality with a constant. deconstruction pattern Delay(int timeInMs) Perform an instanceof test, cast the target, destructure the target and recursively match the components to subpatterns. var pattern var timeInMs Match anything and bind its target. any pattern _ Match anything, but bind nothing.
  • 102. Pattern Contexts Pattern Contexts Pattern context Example Purpose instanceof predicate product instanceof Guitar guitar Test if target matches the indicated pattern. switch statement or expression switch (effect) {     case Delay d } Test if target matches one (or more) of the indicated patterns. bind statement let Reverb(var name, var roomSize) = reverb; Destructure a target using a pattern.
  • 104. Pattern matching... Pattern matching... is a rich feature arc that will play out over several versions. allows us to use type patterns in instanceof. improves switch expressions. makes destructuring objects as easy (and more similar to) constructing them. holds the potential to simplify and streamline much of the code we write today.
  • 105. Major Feature Major Feature Major Feature Major Feature Major Feature
  • 106. Thank you! ☺ Thank you! ☺ bit.do/javaland-pattern- matching github.com/hannotify/pattern- matching-music-store hannotify.github.io @hannotify