SlideShare a Scribd company logo
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Pattern
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Matching
Small Enhancement or Major Feature?
Small Enhancement or Major Feature?
Hanno Embregts
Peter Wessels
@hannotify
@PeterWessels
#JavaZone #PatternMatching @hannotify @PeterWessels
#JavaZone #PatternMatching @hannotify @PeterWessels
#JavaZone #PatternMatching @hannotify @PeterWessels
Small Enhancement
Small Enhancement
Small Enhancement
Small Enhancement
Small Enhancement
https://gph.is/g/ZPJNoPQ
#JavaZone #PatternMatching @hannotify @PeterWessels
Major Feature
Major Feature
Major Feature
Major Feature
Major Feature
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
https://pxhere.com/en/photo/548063
#JavaZone #PatternMatching @hannotify @PeterWessels
Instanceof-and-cast
Instanceof-and-cast
if (product instanceof Guitar) {
Guitar lesPaul =
(Guitar) product;
// use lesPaul
}
1
2
3
4
5
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
Improve the situation
Improve the situation
if (product instanceof Guitar lesPaul) {
1
2 // use lesPaul
3 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Type pattern
Type pattern
Type pattern
Type pattern
Type pattern
Consists of a predicate that specifies a type,
along with a single binding variable.
https://www.pexels.com/photo/person-holding-white-chalk-625219/
#JavaZone #PatternMatching @hannotify @PeterWessels
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/
#JavaZone #PatternMatching @hannotify @PeterWessels
Demo
Demo
Simplify implementation of equals
https://pxhere.com/en/photo/1458897
#JavaZone #PatternMatching @hannotify @PeterWessels
Declaring 'in the middle'
Declaring 'in the middle'
if (product instanceof Guitar lesPaul) {
// use lesPaul
}
1
2
3
#JavaZone #PatternMatching @hannotify @PeterWessels
Scoping
Scoping
Pattern binding variable ('flow scoping')
Pattern binding variable ('flow scoping')
The set of places where it would definitely be assigned.
if (product instanceof Guitar lesPaul && lesPaul.isInTune()) {
// can use lesPaul here
} else {
// can't use lesPaul here
}
1
2
3
4
5
#JavaZone #PatternMatching @hannotify @PeterWessels
Benefits
Benefits
Nearly 100% of casts will just disappear!
More concise
#JavaZone #PatternMatching @hannotify @PeterWessels
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
pattern example
type pattern Guitar lesPaul
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
Feature Status
Feature Status
Java version Feature status JEP
14 Preview
15 Second preview
16 Final
JEP 305
JEP 375
JEP 394
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
https://pxhere.com/en/photo/544037
#JavaZone #PatternMatching @hannotify @PeterWessels
https://pxhere.com/en/photo/853260
#JavaZone #PatternMatching @hannotify @PeterWessels
https://pxhere.com/en/photo/544037
#JavaZone #PatternMatching @hannotify @PeterWessels
String apply(Effect effect) {
String formatted = "";
if (effect instanceof Delay) {
Delay de = (Delay) effect;
formatted = String.format("Delay active of %d ms.", de.getTimeInMs());
} else if (effect instanceof Reverb) {
Reverb re = (Reverb) effect;
formatted = String.format("Reverb active of type %s and roomSize %d.", re.getName(
} else if (effect instanceof Overdrive) {
Overdrive ov = (Overdrive) effect;
formatted = String.format("Overdrive active with gain %d.", ov.getGain());
} else if (effect instanceof Tremolo) {
Tremolo tr = (Tremolo) effect;
formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth
} 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
#JavaZone #PatternMatching @hannotify @PeterWessels
g ( yp , g (
formatted = String.format("Overdrive active with gain %d.", ov.getGain());
formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth
formatted = String.format("Tuner active with pitch %d. Muting all signal!", tu.get
formatted = el.getEffects().stream().map(this::apply).collect(Collectors.joining(S
formatted = String.format("Unknown effect active: %s.", effect);
} 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
17
} else if (effect instanceof EffectLoop) {
18
EffectLoop el = (EffectLoop) effect;
19
20
} else {
21
22
}
23
#JavaZone #PatternMatching @hannotify @PeterWessels
String apply(Effect effect) {
String formatted = "";
if (effect instanceof Delay de) {
} else if (effect instanceof Reverb re) {
} else if (effect instanceof Overdrive ov) {
} else if (effect instanceof Tremolo tr) {
} else if (effect instanceof Tuner tu) {
} else if (effect instanceof EffectLoop el) {
1
2
3
4 formatted = String.format("Delay active of %d ms.", de.getTimeInMs());
5
6 formatted = String.format("Reverb active of type %s and roomSize %d.", re.getName(
7
8 formatted = String.format("Overdrive active with gain %d.", ov.getGain());
9
10 formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth
11
12 formatted = String.format("Tuner active with pitch %d. Muting all signal!", tu.get
13
14 formatted = el.getEffects().stream().map(this::apply).collect(Collectors.joining(S
15 } else {
16 formatted = String format("Unknown effect active: %s " effect);
#JavaZone #PatternMatching @hannotify @PeterWessels
formatted = String.format( Delay active of %d ms. , de.getTimeInMs());
formatted = String.format("Reverb active of type %s and roomSize %d.", re.getName(
formatted = String.format("Overdrive active with gain %d.", ov.getGain());
formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth
formatted = String.format("Tuner active with pitch %d. Muting all signal!", tu.get
formatted = el.getEffects().stream().map(this::apply).collect(Collectors.joining(S
formatted = String.format("Unknown effect active: %s.", effect);
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
}
17
return formatted;
18
}
19
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
1 String apply(Effect effect) {
2 return switch(effect) {
3 default -> String.format("Unknown effect active: %s.", effect);
4 };
5 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", re
String apply(Effect effect) {
1
return switch(effect) {
2
3
4
5 default -> String.format("Unknown effect active: %s.", effect);
6 };
7 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
1 String apply(Effect effect) {
2 return switch(effect) {
3 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
4 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
5 case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
6 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
7 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
8 default -> String.format("Unknown effect active: %s.", effect);
9 };
10 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
3
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
4
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
5
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
6
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
7
8
9 default -> String.format("Unknown effect active: %s.", effect);
10 };
11 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
String apply(Effect effect) {
return switch(effect) {
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
#JavaZone #PatternMatching @hannotify @PeterWessels
https://pxhere.com/en/photo/544037
#JavaZone #PatternMatching @hannotify @PeterWessels
Sensible operations to the effect loop
Sensible operations to the effect loop
apply()
setVolume(int volume)
contains(Effect... effect)
#JavaZone #PatternMatching @hannotify @PeterWessels
Nonsensical operations to the effect
Nonsensical operations to the effect
loop
loop
isTunerActive()
isDelayTimeEqualToReverbRoomSize()
isToneSuitableToPlayPrideInTheNameOfLove()
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
String apply(Effect effect) {
return switch(effect) {
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Switch expression
Switch expression
static String apply(Effect effect) {
return switch(effect) {
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
case EffectLoop el -> el.getEffects().stream().map(Effect::apply).collect(Collecto
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Benefits of pattern matching
Benefits of pattern matching
No need for the Visitor pattern or a common supertype
A single expression instead of many assignments
Less error-prone (in adding cases)
More concise
Safer - the compiler can check for missing cases
#JavaZone #PatternMatching @hannotify @PeterWessels
But what if
But what if effect
effect is
is null
null?
?
return switch(effect) { // throws NullPointerException!
static String apply(Effect effect) {
1
2
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
3
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
4
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
5
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
6
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
7
case EffectLoop el -> el.getEffects().stream().map(Effect::apply).collect(Collecto
8
default -> String.format("Unknown effect active: %s.", effect);
9
};
10
}
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Combining case labels
Combining case labels
case null, default -> String.format("Unknown or malfunctioning effect active: %s."
static String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
3
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
4
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
5
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
6
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
7
case EffectLoop el -> el.getEffects().stream().map(Effect::apply).collect(Collecto
8
9
};
10
}
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Demo
Demo
Guarded patterns
https://pxhere.com/en/photo/1458897
#JavaZone #PatternMatching @hannotify @PeterWessels
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
pattern example
guarded pattern Tuner tu && 

!tu.isInTune(guitar)
type pattern Guitar lesPaul
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
Feature Status
Feature Status
Java version Feature status JEP
17 Preview
18 Second preview 

JEP 406
JEP 420
#JavaZone #PatternMatching @hannotify @PeterWessels
Deconstruction
Deconstruction
Deconstruction
Deconstruction
Deconstruction
Patterns
Patterns
Patterns
Patterns
Patterns
https://pxhere.com/en/photo/752901
#JavaZone #PatternMatching @hannotify @PeterWessels
Disclaimer
Disclaimer
Disclaimer
Disclaimer
Disclaimer
We can't tell you when the following features
are coming to Java.
Also: syntax and
implementation specifics may still change.
https://pxhere.com/en/photo/1359311
#JavaZone #PatternMatching @hannotify @PeterWessels
Deconstruction patterns
Deconstruction patterns
String apply(Effect effect) {
return switch(effect) {
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain()
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Deconstruction patterns
Deconstruction patterns
case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain);
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
3
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
4
5
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
6
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
7
case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors
8
default -> String.format("Unknown effect active: %s.", effect);
9
};
10
}
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern definition
Pattern definition
public class Overdrive implements Effect {
private final int gain;
public Overdrive(int gain) {
this.gain = gain;
}
}
1
2
3
4
5
6
7
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern definition
Pattern definition
1 public class Overdrive implements Effect {
2 private final int gain;
3
4 public Overdrive(int gain) {
5 this.gain = gain;
6 }
7
public pattern Overdrive(int gain) {
8
gain = this.gain;
9
}
10
11 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Deconstruction patterns
Deconstruction patterns
case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain);
String apply(Effect effect) {
1
return switch(effect) {
2
case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs());
3
case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r
4
5
case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t
6
case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal
7
case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors
8
default -> String.format("Unknown effect active: %s.", effect);
9
};
10
}
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Deconstruction patterns
Deconstruction patterns
String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs);
case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s
case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain);
case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a
case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all
case EffectLoop(Set<Effect> effects) -> effects.stream().map(this::apply).collect(
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern composition
Pattern composition
static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) {
}
1
2
3
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern composition
Pattern composition
static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) {
if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(String name, int roomS
return timeInMs == roomSize;
1
2
3
}
4
return false;
5
6 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern composition
Pattern composition
1 static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) {
2 return effectLoop.getEffects().stream()
3 .filter(e -> e instanceof Delay || e instanceof Reverb)
4 .map(dr -> {
5 if (dr instanceof Delay d) {
6 return d.getTimeInMs();
} else {
7
Reverb r = (Reverb) dr;
8
return r.getRoomSize();
9
}
10
11
}).distinct().count() == 1;
12
13 }
#JavaZone #PatternMatching @hannotify @PeterWessels
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
pattern example
deconstruction pattern Delay(int timeInMs)
type pattern Guitar lesPaul
guarded pattern Tuner tu && 

!tu.isInTune(guitar)
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
Var and any patterns
Var and any patterns
// Pre-Java 10
Guitar telecaster = new Guitar("Fender Telecaster Baritone Blacktop", GuitarType.TELECASTER
// Java 10
var telecaster = new Guitar("Fender Telecaster Baritone Blacktop", GuitarType.TELECASTER);
1
2
3
4
5
https://openjdk.java.net/jeps/286
https://openjdk.java.net/jeps/286
#JavaZone #PatternMatching @hannotify @PeterWessels
Var and any patterns
Var and any patterns
static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) {
if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(String name, int roomS
return timeInMs == roomSize;
}
return false;
}
1
2
3
4
5
6
#JavaZone #PatternMatching @hannotify @PeterWessels
Var and any patterns
Var and any patterns
if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(var name, var roomSize
static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) {
1
2
return timeInMs == roomSize;
3
}
4
return false;
5
}
6
#JavaZone #PatternMatching @hannotify @PeterWessels
http://gph.is/2lFlHIK
#JavaZone #PatternMatching @hannotify @PeterWessels
Var and any patterns
Var and any patterns
static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) {
if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(_, var roomSize))) {
return timeInMs == roomSize;
}
return false;
}
1
2
3
4
5
6
#JavaZone #PatternMatching @hannotify @PeterWessels
Optimization
Optimization
static String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs);
case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s
case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain);
case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a
case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all
case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collec
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
#JavaZone #PatternMatching @hannotify @PeterWessels
Optimization
Optimization
1 static String apply(Effect effect) {
2 return switch(effect) {
3 // ...
4 case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collect
5 default -> String.format("Unknown effect active: %s.", effect);
6 };
7 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Optimization
Optimization
case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The EffectLoop contains
static String apply(Effect effect) {
1
return switch(effect) {
2
// ...
3
4
5 case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collect
6 default -> String.format("Unknown effect active: %s.", effect);
7 };
8 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Benefits
Benefits
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
#JavaZone #PatternMatching @hannotify @PeterWessels
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
pattern example
var pattern var timeInMs
type pattern Guitar lesPaul
guarded pattern Tuner tu && 

!tu.isInTune(guitar)
deconstruction pattern Delay(int timeInMs)
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
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
pattern example
any pattern _
type pattern Guitar lesPaul
guarded pattern Tuner tu && 

!tu.isInTune(guitar)
deconstruction pattern Delay(int timeInMs)
var pattern var timeInMs
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern Matching Plays Nice
Pattern Matching Plays Nice
With
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
#JavaZone #PatternMatching @hannotify @PeterWessels
Demo
Demo
Make Effect a sealed type
https://pxhere.com/en/photo/1458897
#JavaZone #PatternMatching @hannotify @PeterWessels
Sealed types yield completeness
Sealed types yield completeness
static String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs);
case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s
case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain);
case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a
case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all
case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The EffectLoop contains
case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collec
default -> String.format("Unknown effect active: %s.", effect);
};
}
1
2
3
4
5
6
7
8
9
10
11
12
#JavaZone #PatternMatching @hannotify @PeterWessels


Sealed types yield completeness
Sealed types yield completeness
static String apply(Effect effect) {
return switch(effect) {
case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs);
case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s
case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain);
case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a
case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all
case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The EffectLoop contains
case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collec
1
2
3
4
5
6
7
8
9
10 };
11 }
https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
Array patterns
Array patterns
record EffectLoop(String name, int volume, Effect... effects) { }
1
static String apply(EffectLoop effectLoop) {}
return switch(effectLoop) {
case EffectLoop(var name, var volume) -> "Effect loop contains no effects.";
}
}
1
2
3
4
5
#JavaZone #PatternMatching @hannotify @PeterWessels
Array patterns
Array patterns
record EffectLoop(String name, int volume, Effect... effects) { }
1
static String apply(EffectLoop effectLoop) {}
return switch(effectLoop) {
case EffectLoop(var name, var volume) -> "Effect loop contains no effects.";
case EffectLoop(_, _, var effect) -> "Effect loop contains exactly one effect.";
1
2
3
4
5 }
6 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Array patterns
Array patterns
record EffectLoop(String name, int volume, Effect... effects) { }
1
static String apply(EffectLoop effectLoop) {}
return switch(effectLoop) {
case EffectLoop(var name, var volume) -> "Effect loop contains no effects.";
case EffectLoop(_, _, var effect) -> "Effect loop contains exactly one effect.";
case EffectLoop(_, _, var effect, ...) -> "Effect loop contains more than one effec
1
2
3
4
5
6 }
7 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Array patterns
Array patterns
record EffectLoop(String name, int volume, Effect... effects) { }
1
static String apply(EffectLoop effectLoop) {}
return switch(effectLoop) {
case EffectLoop(var name, var volume) -> "Effect loop contains no effects.";
case EffectLoop(_, _, var effect) -> "Effect loop contains exactly one effect.";
case EffectLoop(_, _, var effect, ...) -> "Effect loop contains more than one effec
case EffectLoop(_, _, var effect1, var effect2) -> "Effect loop contains exactly tw
case EffectLoop(_, _, var effect1, var effect2, ...) -> "Effect loop contains more
1
2
3
4
5
6
7
8 }
9 }
#JavaZone #PatternMatching @hannotify @PeterWessels
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
pattern example
array pattern EffectLoop(var name, var effect, ...)
.. ..
var pattern var timeInMs
any pattern _
https://thumbs.gfycat.com/DefiantElasticGadwall.webp
#JavaZone #PatternMatching @hannotify @PeterWessels
Feature Status
Feature Status
Sealed Types
Sealed Types
Java version Feature status JEP
15 Preview
16 Second preview
17 Final
JEP 360
JEP 397
JEP 409
#JavaZone #PatternMatching @hannotify @PeterWessels
Feature Status
Feature Status
Completeness
Completeness
Java version Feature status JEP
17 Preview
18 Second preview 

JEP 406
JEP 420
#JavaZone #PatternMatching @hannotify @PeterWessels
Feature Status
Feature Status
Record Patterns
Record Patterns
Java version Feature status JEP
n/a Preview JEP 405
#JavaZone #PatternMatching @hannotify @PeterWessels
A Better
A Better
A Better
A Better
A Better
Serialization?
Serialization?
Serialization?
Serialization?
Serialization?
https://pxhere.com/en/photo/752901
#JavaZone #PatternMatching @hannotify @PeterWessels
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/
#JavaZone #PatternMatching @hannotify @PeterWessels
Opposites
Opposites
Deconstruction pattern
Deconstruction pattern
transforms an object into a set of typed fields
Constructor
Constructor
transforms a set of typed fields into an object
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
Serialization
Serialization
1 public class EffectLoop implements Effect {
2 private String name;
3 private Set<Effect> effects;
4
5 public EffectLoop(String name) {
6 this.name = name;
7 this.effects = new HashSet<>();
8 }
9
public pattern EffectLoop(String name, Effect[] effects) {
10
name = this.name;
11
effects = this.effects.toArray();
12
}
13
14 }
#JavaZone #PatternMatching @hannotify @PeterWessels
Serialization
Serialization
public EffectLoop(String name, Effect[] effects) {
this(name);
for (Effect effect : effects) {
this.effects.add(effect);
}
this.name = name;
6
this.effects = new HashSet<>();
7
}
8
9
10
11
12
13
14
15 }
16
17 public pattern EffectLoop(String name, Effect[] effects) {
18 name = this.name;
19 effects = this.effects.toArray();
}
20
21 }
#JavaZone #PatternMatching @hannotify @PeterWessels
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
1
2
3
4
5
6
7
8
9
10
11 public EffectLoop(String name, Effect[] effects) {
12 this(name);
13 for (Effect effect : effects) {
14 this.effects.add(effect);
15 }
16 }
#JavaZone #PatternMatching @hannotify @PeterWessels
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.
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
Future
Future
Future
Future
Future
Expansions
Expansions
Expansions
Expansions
Expansions
https://pxhere.com/en/photo/752901
#JavaZone #PatternMatching @hannotify @PeterWessels
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/
#JavaZone #PatternMatching @hannotify @PeterWessels
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
#JavaZone #PatternMatching @hannotify @PeterWessels
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
6 // do something with name & roomSize
#JavaZone #PatternMatching @hannotify @PeterWessels
Other ideas
Other ideas








AND patterns:

PatternOne&PatternTwo
Patterns in catch clauses:

(will most likely complement multi-catch blocks)
Collection patterns
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-January/002758.html
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-January/002758.html
#JavaZone #PatternMatching @hannotify @PeterWessels
Pattern
Pattern
Pattern
Pattern
Pattern
Contexts
Contexts
Contexts
Contexts
Contexts
https://pxhere.com/en/photo/752901
#JavaZone #PatternMatching @hannotify @PeterWessels
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.
#JavaZone #PatternMatching @hannotify @PeterWessels
Wrap-up
Wrap-up
Wrap-up
Wrap-up
Wrap-up
https://pxhere.com/en/photo/752901
#JavaZone #PatternMatching @hannotify @PeterWessels
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 as (and more similar to)
constructing them.
holds the potential to simplify and streamline much of the code
we write today.
#JavaZone #PatternMatching @hannotify @PeterWessels
Major Feature
Major Feature
Major Feature
Major Feature
Major Feature
#JavaZone #PatternMatching @hannotify @PeterWessels
Thank you! 😀
Thank you! 😀


github.com/hannotify/pattern-
matching-music-store
hanno.codes peterwessels.nl
@hannotify @PeterWessels

More Related Content

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

What's hot (14)

PPTX
Load-time Hacking using LD_PRELOAD
PDF
Hidden Gems of Ruby 1.9
PDF
Test driven node.js
PDF
On Reflection in OO Programming Languages (v1.5.2, 14/04/14)
PDF
Input and Output
PPT
Concurrency in go
PDF
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
PDF
Grammatical Optimization
PDF
Artificial Neural Network in a Tic Tac Toe Symfony Console Application - Symf...
PDF
Control Flow
PDF
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
PDF
Perl Testing
PPT
Array
Load-time Hacking using LD_PRELOAD
Hidden Gems of Ruby 1.9
Test driven node.js
On Reflection in OO Programming Languages (v1.5.2, 14/04/14)
Input and Output
Concurrency in go
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
Grammatical Optimization
Artificial Neural Network in a Tic Tac Toe Symfony Console Application - Symf...
Control Flow
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
Perl Testing
Array
Ad

Similar to Pattern Matching: Small Enhancement or Major Feature? (7)

PDF
Pattern Matching: Small Enhancement or Major Feature?
PDF
Pattern Matching - Small Enhancement or Major Feature? from Developer Week 202
PPTX
The Art of Java Type Patterns
PPTX
Pattern Matching in Java 14
PPTX
Modern_Java_Workshop manjunath np hj slave
PPTX
Java 8 Intro - Core Features
PDF
Introduction to Pattern Matching in Java [Free Meetup]
Pattern Matching: Small Enhancement or Major Feature?
Pattern Matching - Small Enhancement or Major Feature? from Developer Week 202
The Art of Java Type Patterns
Pattern Matching in Java 14
Modern_Java_Workshop manjunath np hj slave
Java 8 Intro - Core Features
Introduction to Pattern Matching in Java [Free Meetup]
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)

PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Introduction to Artificial Intelligence
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
ai tools demonstartion for schools and inter college
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
System and Network Administration Chapter 2
PDF
Digital Strategies for Manufacturing Companies
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Transform Your Business with a Software ERP System
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
Computer Software and OS of computer science of grade 11.pptx
Upgrade and Innovation Strategies for SAP ERP Customers
Navsoft: AI-Powered Business Solutions & Custom Software Development
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Reimagine Home Health with the Power of Agentic AI​
Introduction to Artificial Intelligence
PTS Company Brochure 2025 (1).pdf.......
Which alternative to Crystal Reports is best for small or large businesses.pdf
ai tools demonstartion for schools and inter college
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
CHAPTER 2 - PM Management and IT Context
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
2025 Textile ERP Trends: SAP, Odoo & Oracle
How to Choose the Right IT Partner for Your Business in Malaysia
System and Network Administration Chapter 2
Digital Strategies for Manufacturing Companies
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Transform Your Business with a Software ERP System
Design an Analysis of Algorithms I-SECS-1021-03
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Computer Software and OS of computer science of grade 11.pptx

Pattern Matching: Small Enhancement or Major Feature?

  • 1. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern Pattern Pattern Pattern Pattern Pattern Pattern Pattern Pattern Pattern Pattern Pattern Matching Matching Matching Matching Matching Matching Matching Matching Matching Matching Matching Matching Small Enhancement or Major Feature? Small Enhancement or Major Feature? Hanno Embregts Peter Wessels @hannotify @PeterWessels
  • 4. #JavaZone #PatternMatching @hannotify @PeterWessels Small Enhancement Small Enhancement Small Enhancement Small Enhancement Small Enhancement https://gph.is/g/ZPJNoPQ
  • 5. #JavaZone #PatternMatching @hannotify @PeterWessels Major Feature Major Feature Major Feature Major Feature Major Feature https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 6. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels https://pxhere.com/en/photo/548063
  • 8. #JavaZone #PatternMatching @hannotify @PeterWessels Instanceof-and-cast Instanceof-and-cast if (product instanceof Guitar) { Guitar lesPaul = (Guitar) product; // use lesPaul } 1 2 3 4 5
  • 9. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 10. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 11. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 12. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 13. #JavaZone #PatternMatching @hannotify @PeterWessels Improve the situation Improve the situation if (product instanceof Guitar lesPaul) { 1 2 // use lesPaul 3 }
  • 14. #JavaZone #PatternMatching @hannotify @PeterWessels Type pattern Type pattern Type pattern Type pattern Type pattern Consists of a predicate that specifies a type, along with a single binding variable. https://www.pexels.com/photo/person-holding-white-chalk-625219/
  • 15. #JavaZone #PatternMatching @hannotify @PeterWessels 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/
  • 16. #JavaZone #PatternMatching @hannotify @PeterWessels Demo Demo Simplify implementation of equals https://pxhere.com/en/photo/1458897
  • 17. #JavaZone #PatternMatching @hannotify @PeterWessels Declaring 'in the middle' Declaring 'in the middle' if (product instanceof Guitar lesPaul) { // use lesPaul } 1 2 3
  • 18. #JavaZone #PatternMatching @hannotify @PeterWessels Scoping Scoping Pattern binding variable ('flow scoping') Pattern binding variable ('flow scoping') The set of places where it would definitely be assigned. if (product instanceof Guitar lesPaul && lesPaul.isInTune()) { // can use lesPaul here } else { // can't use lesPaul here } 1 2 3 4 5
  • 19. #JavaZone #PatternMatching @hannotify @PeterWessels Benefits Benefits Nearly 100% of casts will just disappear! More concise
  • 20. #JavaZone #PatternMatching @hannotify @PeterWessels 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 pattern example type pattern Guitar lesPaul https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 21. #JavaZone #PatternMatching @hannotify @PeterWessels Feature Status Feature Status Java version Feature status JEP 14 Preview 15 Second preview 16 Final JEP 305 JEP 375 JEP 394
  • 22. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 23. #JavaZone #PatternMatching @hannotify @PeterWessels https://pxhere.com/en/photo/544037
  • 24. #JavaZone #PatternMatching @hannotify @PeterWessels https://pxhere.com/en/photo/853260
  • 25. #JavaZone #PatternMatching @hannotify @PeterWessels https://pxhere.com/en/photo/544037
  • 26. #JavaZone #PatternMatching @hannotify @PeterWessels String apply(Effect effect) { String formatted = ""; if (effect instanceof Delay) { Delay de = (Delay) effect; formatted = String.format("Delay active of %d ms.", de.getTimeInMs()); } else if (effect instanceof Reverb) { Reverb re = (Reverb) effect; formatted = String.format("Reverb active of type %s and roomSize %d.", re.getName( } else if (effect instanceof Overdrive) { Overdrive ov = (Overdrive) effect; formatted = String.format("Overdrive active with gain %d.", ov.getGain()); } else if (effect instanceof Tremolo) { Tremolo tr = (Tremolo) effect; formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth } 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
  • 27. #JavaZone #PatternMatching @hannotify @PeterWessels g ( yp , g ( formatted = String.format("Overdrive active with gain %d.", ov.getGain()); formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth formatted = String.format("Tuner active with pitch %d. Muting all signal!", tu.get formatted = el.getEffects().stream().map(this::apply).collect(Collectors.joining(S formatted = String.format("Unknown effect active: %s.", effect); } 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 17 } else if (effect instanceof EffectLoop) { 18 EffectLoop el = (EffectLoop) effect; 19 20 } else { 21 22 } 23
  • 28. #JavaZone #PatternMatching @hannotify @PeterWessels String apply(Effect effect) { String formatted = ""; if (effect instanceof Delay de) { } else if (effect instanceof Reverb re) { } else if (effect instanceof Overdrive ov) { } else if (effect instanceof Tremolo tr) { } else if (effect instanceof Tuner tu) { } else if (effect instanceof EffectLoop el) { 1 2 3 4 formatted = String.format("Delay active of %d ms.", de.getTimeInMs()); 5 6 formatted = String.format("Reverb active of type %s and roomSize %d.", re.getName( 7 8 formatted = String.format("Overdrive active with gain %d.", ov.getGain()); 9 10 formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth 11 12 formatted = String.format("Tuner active with pitch %d. Muting all signal!", tu.get 13 14 formatted = el.getEffects().stream().map(this::apply).collect(Collectors.joining(S 15 } else { 16 formatted = String format("Unknown effect active: %s " effect);
  • 29. #JavaZone #PatternMatching @hannotify @PeterWessels formatted = String.format( Delay active of %d ms. , de.getTimeInMs()); formatted = String.format("Reverb active of type %s and roomSize %d.", re.getName( formatted = String.format("Overdrive active with gain %d.", ov.getGain()); formatted = String.format("Tremolo active with depth %d and rate %d.", tr.getDepth formatted = String.format("Tuner active with pitch %d. Muting all signal!", tu.get formatted = el.getEffects().stream().map(this::apply).collect(Collectors.joining(S formatted = String.format("Unknown effect active: %s.", effect); 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 } 17 return formatted; 18 } 19
  • 30. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression 1 String apply(Effect effect) { 2 return switch(effect) { 3 default -> String.format("Unknown effect active: %s.", effect); 4 }; 5 }
  • 31. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", re String apply(Effect effect) { 1 return switch(effect) { 2 3 4 5 default -> String.format("Unknown effect active: %s.", effect); 6 }; 7 }
  • 32. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression 1 String apply(Effect effect) { 2 return switch(effect) { 3 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); 4 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r 5 case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() 6 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t 7 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal 8 default -> String.format("Unknown effect active: %s.", effect); 9 }; 10 }
  • 33. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); 3 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r 4 case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() 5 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t 6 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal 7 8 9 default -> String.format("Unknown effect active: %s.", effect); 10 }; 11 }
  • 34. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression String apply(Effect effect) { return switch(effect) { case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11
  • 35. #JavaZone #PatternMatching @hannotify @PeterWessels https://pxhere.com/en/photo/544037
  • 36. #JavaZone #PatternMatching @hannotify @PeterWessels Sensible operations to the effect loop Sensible operations to the effect loop apply() setVolume(int volume) contains(Effect... effect)
  • 37. #JavaZone #PatternMatching @hannotify @PeterWessels Nonsensical operations to the effect Nonsensical operations to the effect loop loop isTunerActive() isDelayTimeEqualToReverbRoomSize() isToneSuitableToPlayPrideInTheNameOfLove()
  • 38. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression String apply(Effect effect) { return switch(effect) { case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11
  • 39. #JavaZone #PatternMatching @hannotify @PeterWessels Switch expression Switch expression static String apply(Effect effect) { return switch(effect) { case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal case EffectLoop el -> el.getEffects().stream().map(Effect::apply).collect(Collecto default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11
  • 40. #JavaZone #PatternMatching @hannotify @PeterWessels Benefits of pattern matching Benefits of pattern matching No need for the Visitor pattern or a common supertype A single expression instead of many assignments Less error-prone (in adding cases) More concise Safer - the compiler can check for missing cases
  • 41. #JavaZone #PatternMatching @hannotify @PeterWessels But what if But what if effect effect is is null null? ? return switch(effect) { // throws NullPointerException! static String apply(Effect effect) { 1 2 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); 3 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r 4 case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() 5 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t 6 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal 7 case EffectLoop el -> el.getEffects().stream().map(Effect::apply).collect(Collecto 8 default -> String.format("Unknown effect active: %s.", effect); 9 }; 10 } 11
  • 42. #JavaZone #PatternMatching @hannotify @PeterWessels Combining case labels Combining case labels case null, default -> String.format("Unknown or malfunctioning effect active: %s." static String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); 3 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r 4 case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() 5 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t 6 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal 7 case EffectLoop el -> el.getEffects().stream().map(Effect::apply).collect(Collecto 8 9 }; 10 } 11
  • 43. #JavaZone #PatternMatching @hannotify @PeterWessels Demo Demo Guarded patterns https://pxhere.com/en/photo/1458897
  • 44. #JavaZone #PatternMatching @hannotify @PeterWessels 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 pattern example guarded pattern Tuner tu && !tu.isInTune(guitar) type pattern Guitar lesPaul https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 45. #JavaZone #PatternMatching @hannotify @PeterWessels Feature Status Feature Status Java version Feature status JEP 17 Preview 18 Second preview JEP 406 JEP 420
  • 46. #JavaZone #PatternMatching @hannotify @PeterWessels Deconstruction Deconstruction Deconstruction Deconstruction Deconstruction Patterns Patterns Patterns Patterns Patterns https://pxhere.com/en/photo/752901
  • 47. #JavaZone #PatternMatching @hannotify @PeterWessels Disclaimer Disclaimer Disclaimer Disclaimer Disclaimer We can't tell you when the following features are coming to Java. Also: syntax and implementation specifics may still change. https://pxhere.com/en/photo/1359311
  • 48. #JavaZone #PatternMatching @hannotify @PeterWessels Deconstruction patterns Deconstruction patterns String apply(Effect effect) { return switch(effect) { case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r case Overdrive ov -> String.format("Overdrive active with gain %d.", ov.getGain() case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11
  • 49. #JavaZone #PatternMatching @hannotify @PeterWessels Deconstruction patterns Deconstruction patterns case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain); String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); 3 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r 4 5 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t 6 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal 7 case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors 8 default -> String.format("Unknown effect active: %s.", effect); 9 }; 10 } 11
  • 50. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern definition Pattern definition public class Overdrive implements Effect { private final int gain; public Overdrive(int gain) { this.gain = gain; } } 1 2 3 4 5 6 7
  • 51. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern definition Pattern definition 1 public class Overdrive implements Effect { 2 private final int gain; 3 4 public Overdrive(int gain) { 5 this.gain = gain; 6 } 7 public pattern Overdrive(int gain) { 8 gain = this.gain; 9 } 10 11 }
  • 52. #JavaZone #PatternMatching @hannotify @PeterWessels Deconstruction patterns Deconstruction patterns case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain); String apply(Effect effect) { 1 return switch(effect) { 2 case Delay de -> String.format("Delay active of %d ms.", de.getTimeInMs()); 3 case Reverb re -> String.format("Reverb active of type %s and roomSize %d.", r 4 5 case Tremolo tr -> String.format("Tremolo active with depth %d and rate %d.", t 6 case Tuner tu -> String.format("Tuner active with pitch %d. Muting all signal 7 case EffectLoop el -> el.getEffects().stream().map(this::apply).collect(Collectors 8 default -> String.format("Unknown effect active: %s.", effect); 9 }; 10 } 11
  • 53. #JavaZone #PatternMatching @hannotify @PeterWessels Deconstruction patterns Deconstruction patterns String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs); case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain); case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all case EffectLoop(Set<Effect> effects) -> effects.stream().map(this::apply).collect( default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11
  • 54. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern composition Pattern composition static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) { } 1 2 3
  • 55. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern composition Pattern composition static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) { if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(String name, int roomS return timeInMs == roomSize; 1 2 3 } 4 return false; 5 6 }
  • 56. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern composition Pattern composition 1 static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) { 2 return effectLoop.getEffects().stream() 3 .filter(e -> e instanceof Delay || e instanceof Reverb) 4 .map(dr -> { 5 if (dr instanceof Delay d) { 6 return d.getTimeInMs(); } else { 7 Reverb r = (Reverb) dr; 8 return r.getRoomSize(); 9 } 10 11 }).distinct().count() == 1; 12 13 }
  • 57. #JavaZone #PatternMatching @hannotify @PeterWessels 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 pattern example deconstruction pattern Delay(int timeInMs) type pattern Guitar lesPaul guarded pattern Tuner tu && !tu.isInTune(guitar) https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 58. #JavaZone #PatternMatching @hannotify @PeterWessels Var and any patterns Var and any patterns // Pre-Java 10 Guitar telecaster = new Guitar("Fender Telecaster Baritone Blacktop", GuitarType.TELECASTER // Java 10 var telecaster = new Guitar("Fender Telecaster Baritone Blacktop", GuitarType.TELECASTER); 1 2 3 4 5 https://openjdk.java.net/jeps/286 https://openjdk.java.net/jeps/286
  • 59. #JavaZone #PatternMatching @hannotify @PeterWessels Var and any patterns Var and any patterns static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) { if (effectLoop instanceof EffectLoop(Delay(int timeInMs), Reverb(String name, int roomS return timeInMs == roomSize; } return false; } 1 2 3 4 5 6
  • 60. #JavaZone #PatternMatching @hannotify @PeterWessels Var and any patterns Var and any patterns if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(var name, var roomSize static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) { 1 2 return timeInMs == roomSize; 3 } 4 return false; 5 } 6
  • 61. #JavaZone #PatternMatching @hannotify @PeterWessels http://gph.is/2lFlHIK
  • 62. #JavaZone #PatternMatching @hannotify @PeterWessels Var and any patterns Var and any patterns static boolean isDelayTimeEqualToReverbRoomSize(EffectLoop effectLoop) { if (effectLoop instanceof EffectLoop(Delay(var timeInMs), Reverb(_, var roomSize))) { return timeInMs == roomSize; } return false; } 1 2 3 4 5 6
  • 63. #JavaZone #PatternMatching @hannotify @PeterWessels Optimization Optimization static String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs); case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain); case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collec default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11
  • 64. #JavaZone #PatternMatching @hannotify @PeterWessels Optimization Optimization 1 static String apply(Effect effect) { 2 return switch(effect) { 3 // ... 4 case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collect 5 default -> String.format("Unknown effect active: %s.", effect); 6 }; 7 }
  • 65. #JavaZone #PatternMatching @hannotify @PeterWessels Optimization Optimization case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The EffectLoop contains static String apply(Effect effect) { 1 return switch(effect) { 2 // ... 3 4 5 case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collect 6 default -> String.format("Unknown effect active: %s.", effect); 7 }; 8 }
  • 66. #JavaZone #PatternMatching @hannotify @PeterWessels Benefits Benefits 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
  • 67. #JavaZone #PatternMatching @hannotify @PeterWessels 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 pattern example var pattern var timeInMs type pattern Guitar lesPaul guarded pattern Tuner tu && !tu.isInTune(guitar) deconstruction pattern Delay(int timeInMs) https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 68. #JavaZone #PatternMatching @hannotify @PeterWessels 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 pattern example any pattern _ type pattern Guitar lesPaul guarded pattern Tuner tu && !tu.isInTune(guitar) deconstruction pattern Delay(int timeInMs) var pattern var timeInMs https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 69. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 70. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern Matching Plays Nice Pattern Matching Plays Nice With 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
  • 71. #JavaZone #PatternMatching @hannotify @PeterWessels Demo Demo Make Effect a sealed type https://pxhere.com/en/photo/1458897
  • 72. #JavaZone #PatternMatching @hannotify @PeterWessels Sealed types yield completeness Sealed types yield completeness static String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs); case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain); case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The EffectLoop contains case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collec default -> String.format("Unknown effect active: %s.", effect); }; } 1 2 3 4 5 6 7 8 9 10 11 12
  • 73. #JavaZone #PatternMatching @hannotify @PeterWessels Sealed types yield completeness Sealed types yield completeness static String apply(Effect effect) { return switch(effect) { case Delay(int timeInMs) -> String.format("Delay active of %d ms.", timeInMs); case Reverb(String name, int roomSize) -> String.format("Reverb active of type %s case Overdrive(int gain) -> String.format("Overdrive active with gain %d.", gain); case Tremolo(int depth, int rate) -> String.format("Tremolo active with depth %d a case Tuner(int pitchInHz) -> String.format("Tuner active with pitch %d. Muting all case EffectLoop(Tuner(int pitchInHz), _) -> String.format("The EffectLoop contains case EffectLoop(var effects) -> effects.stream().map(Effect::apply).collect(Collec 1 2 3 4 5 6 7 8 9 10 }; 11 } https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html
  • 74. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 75. #JavaZone #PatternMatching @hannotify @PeterWessels Array patterns Array patterns record EffectLoop(String name, int volume, Effect... effects) { } 1 static String apply(EffectLoop effectLoop) {} return switch(effectLoop) { case EffectLoop(var name, var volume) -> "Effect loop contains no effects."; } } 1 2 3 4 5
  • 76. #JavaZone #PatternMatching @hannotify @PeterWessels Array patterns Array patterns record EffectLoop(String name, int volume, Effect... effects) { } 1 static String apply(EffectLoop effectLoop) {} return switch(effectLoop) { case EffectLoop(var name, var volume) -> "Effect loop contains no effects."; case EffectLoop(_, _, var effect) -> "Effect loop contains exactly one effect."; 1 2 3 4 5 } 6 }
  • 77. #JavaZone #PatternMatching @hannotify @PeterWessels Array patterns Array patterns record EffectLoop(String name, int volume, Effect... effects) { } 1 static String apply(EffectLoop effectLoop) {} return switch(effectLoop) { case EffectLoop(var name, var volume) -> "Effect loop contains no effects."; case EffectLoop(_, _, var effect) -> "Effect loop contains exactly one effect."; case EffectLoop(_, _, var effect, ...) -> "Effect loop contains more than one effec 1 2 3 4 5 6 } 7 }
  • 78. #JavaZone #PatternMatching @hannotify @PeterWessels Array patterns Array patterns record EffectLoop(String name, int volume, Effect... effects) { } 1 static String apply(EffectLoop effectLoop) {} return switch(effectLoop) { case EffectLoop(var name, var volume) -> "Effect loop contains no effects."; case EffectLoop(_, _, var effect) -> "Effect loop contains exactly one effect."; case EffectLoop(_, _, var effect, ...) -> "Effect loop contains more than one effec case EffectLoop(_, _, var effect1, var effect2) -> "Effect loop contains exactly tw case EffectLoop(_, _, var effect1, var effect2, ...) -> "Effect loop contains more 1 2 3 4 5 6 7 8 } 9 }
  • 79. #JavaZone #PatternMatching @hannotify @PeterWessels 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 pattern example array pattern EffectLoop(var name, var effect, ...) .. .. var pattern var timeInMs any pattern _ https://thumbs.gfycat.com/DefiantElasticGadwall.webp
  • 80. #JavaZone #PatternMatching @hannotify @PeterWessels Feature Status Feature Status Sealed Types Sealed Types Java version Feature status JEP 15 Preview 16 Second preview 17 Final JEP 360 JEP 397 JEP 409
  • 81. #JavaZone #PatternMatching @hannotify @PeterWessels Feature Status Feature Status Completeness Completeness Java version Feature status JEP 17 Preview 18 Second preview JEP 406 JEP 420
  • 82. #JavaZone #PatternMatching @hannotify @PeterWessels Feature Status Feature Status Record Patterns Record Patterns Java version Feature status JEP n/a Preview JEP 405
  • 83. #JavaZone #PatternMatching @hannotify @PeterWessels A Better A Better A Better A Better A Better Serialization? Serialization? Serialization? Serialization? Serialization? https://pxhere.com/en/photo/752901
  • 84. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels Opposites Opposites Deconstruction pattern Deconstruction pattern transforms an object into a set of typed fields Constructor Constructor transforms a set of typed fields into an object
  • 86. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels Serialization Serialization 1 public class EffectLoop implements Effect { 2 private String name; 3 private Set<Effect> effects; 4 5 public EffectLoop(String name) { 6 this.name = name; 7 this.effects = new HashSet<>(); 8 } 9 public pattern EffectLoop(String name, Effect[] effects) { 10 name = this.name; 11 effects = this.effects.toArray(); 12 } 13 14 }
  • 89. #JavaZone #PatternMatching @hannotify @PeterWessels Serialization Serialization public EffectLoop(String name, Effect[] effects) { this(name); for (Effect effect : effects) { this.effects.add(effect); } this.name = name; 6 this.effects = new HashSet<>(); 7 } 8 9 10 11 12 13 14 15 } 16 17 public pattern EffectLoop(String name, Effect[] effects) { 18 name = this.name; 19 effects = this.effects.toArray(); } 20 21 }
  • 90. #JavaZone #PatternMatching @hannotify @PeterWessels 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 1 2 3 4 5 6 7 8 9 10 11 public EffectLoop(String name, Effect[] effects) { 12 this(name); 13 for (Effect effect : effects) { 14 this.effects.add(effect); 15 } 16 }
  • 91. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels 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
  • 93. #JavaZone #PatternMatching @hannotify @PeterWessels Future Future Future Future Future Expansions Expansions Expansions Expansions Expansions https://pxhere.com/en/photo/752901
  • 94. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels 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. #JavaZone #PatternMatching @hannotify @PeterWessels 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 6 // do something with name & roomSize
  • 97. #JavaZone #PatternMatching @hannotify @PeterWessels Other ideas Other ideas AND patterns: PatternOne&PatternTwo Patterns in catch clauses: (will most likely complement multi-catch blocks) Collection patterns https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-January/002758.html https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-January/002758.html
  • 98. #JavaZone #PatternMatching @hannotify @PeterWessels Pattern Pattern Pattern Pattern Pattern Contexts Contexts Contexts Contexts Contexts https://pxhere.com/en/photo/752901
  • 99. #JavaZone #PatternMatching @hannotify @PeterWessels 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.
  • 100. #JavaZone #PatternMatching @hannotify @PeterWessels Wrap-up Wrap-up Wrap-up Wrap-up Wrap-up https://pxhere.com/en/photo/752901
  • 101. #JavaZone #PatternMatching @hannotify @PeterWessels 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 as (and more similar to) constructing them. holds the potential to simplify and streamline much of the code we write today.
  • 102. #JavaZone #PatternMatching @hannotify @PeterWessels Major Feature Major Feature Major Feature Major Feature Major Feature
  • 103. #JavaZone #PatternMatching @hannotify @PeterWessels Thank you! 😀 Thank you! 😀 github.com/hannotify/pattern- matching-music-store hanno.codes peterwessels.nl @hannotify @PeterWessels