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

What's hot (14)

PPTX
Load-time Hacking using LD_PRELOAD
Dharmalingam Ganesan
 
PDF
Hidden Gems of Ruby 1.9
Aaron Patterson
 
PDF
Test driven node.js
Jay Harris
 
PDF
On Reflection in OO Programming Languages (v1.5.2, 14/04/14)
Yann-Gaël Guéhéneuc
 
PDF
Input and Output
Marieswaran Ramasamy
 
PPT
Concurrency in go
borderj
 
PDF
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
Johannes Hoppe
 
PDF
Grammatical Optimization
adil raja
 
PDF
Artificial Neural Network in a Tic Tac Toe Symfony Console Application - Symf...
aferrandini
 
PDF
Control Flow
Marieswaran Ramasamy
 
PDF
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays
 
PDF
Perl Testing
lichtkind
 
PPT
Array
mussawir20
 
Load-time Hacking using LD_PRELOAD
Dharmalingam Ganesan
 
Hidden Gems of Ruby 1.9
Aaron Patterson
 
Test driven node.js
Jay Harris
 
On Reflection in OO Programming Languages (v1.5.2, 14/04/14)
Yann-Gaël Guéhéneuc
 
Input and Output
Marieswaran Ramasamy
 
Concurrency in go
borderj
 
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
Johannes Hoppe
 
Grammatical Optimization
adil raja
 
Artificial Neural Network in a Tic Tac Toe Symfony Console Application - Symf...
aferrandini
 
Control Flow
Marieswaran Ramasamy
 
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays
 
Perl Testing
lichtkind
 
Array
mussawir20
 

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

PDF
Pattern Matching: Small Enhancement or Major Feature?
🎤 Hanno Embregts 🎸
 
PDF
Pattern Matching - Small Enhancement or Major Feature? from Developer Week 202
🎤 Hanno Embregts 🎸
 
ODP
What's new in Perl 5.10?
acme
 
PDF
How I learned to stop fucking and love MarionetteJS
Kamol Treewatchararat
 
ODP
Ast transformations
HamletDRC
 
PPT
Introducere In Java Jx
danielnastase
 
PDF
Top 10 php classic traps DPC 2020
Damien Seguy
 
TXT
Bililite range2
65macchupka
 
PPTX
Ultimate Node.js countdown: the coolest Application Express examples
Alan Arentsen
 
PDF
JavaFX Overview
José Maria Silveira Neto
 
ODP
AST Transformations at JFokus
HamletDRC
 
PDF
Practical JavaScript Programming - Session 6/8
Wilson Su
 
PPT
New syntax elements of java 7
Orange and Bronze Software Labs
 
PDF
What can be done with Java, but should better be done with Erlang (@pavlobaron)
Pavlo Baron
 
PDF
Good Evils In Perl
Kang-min Liu
 
PDF
Java 8 Puzzlers as it was presented at Codemash 2017
Baruch Sadogursky
 
PPT
JSConf: All You Can Leet
johndaviddalton
 
PPTX
Android & Kotlin - The code awakens #03
Omar Miatello
 
PDF
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
PDF
I need to write a java program about translating the DNA sequenc.pdf
infoeyecare
 
Pattern Matching: Small Enhancement or Major Feature?
🎤 Hanno Embregts 🎸
 
Pattern Matching - Small Enhancement or Major Feature? from Developer Week 202
🎤 Hanno Embregts 🎸
 
What's new in Perl 5.10?
acme
 
How I learned to stop fucking and love MarionetteJS
Kamol Treewatchararat
 
Ast transformations
HamletDRC
 
Introducere In Java Jx
danielnastase
 
Top 10 php classic traps DPC 2020
Damien Seguy
 
Bililite range2
65macchupka
 
Ultimate Node.js countdown: the coolest Application Express examples
Alan Arentsen
 
JavaFX Overview
José Maria Silveira Neto
 
AST Transformations at JFokus
HamletDRC
 
Practical JavaScript Programming - Session 6/8
Wilson Su
 
New syntax elements of java 7
Orange and Bronze Software Labs
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
Pavlo Baron
 
Good Evils In Perl
Kang-min Liu
 
Java 8 Puzzlers as it was presented at Codemash 2017
Baruch Sadogursky
 
JSConf: All You Can Leet
johndaviddalton
 
Android & Kotlin - The code awakens #03
Omar Miatello
 
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
I need to write a java program about translating the DNA sequenc.pdf
infoeyecare
 
Ad

More from 🎤 Hanno Embregts 🎸 (16)

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

Recently uploaded (20)

PDF
Salesforce Pricing Update 2025: Impact, Strategy & Smart Cost Optimization wi...
GetOnCRM Solutions
 
PDF
WatchTraderHub - Watch Dealer software with inventory management and multi-ch...
WatchDealer Pavel
 
PDF
MiniTool Power Data Recovery Crack New Pre Activated Version Latest 2025
imang66g
 
PPTX
Role Of Python In Programing Language.pptx
jaykoshti048
 
PDF
Enhancing Security in VAST: Towards Static Vulnerability Scanning
ESUG
 
PDF
Virtual Threads in Java: A New Dimension of Scalability and Performance
Tier1 app
 
PDF
Download iTop VPN Free 6.1.0.5882 Crack Full Activated Pre Latest 2025
imang66g
 
PPT
Activate_Methodology_Summary presentatio
annapureddyn
 
PDF
Applitools Platform Pulse: What's New and What's Coming - July 2025
Applitools
 
PPTX
TRAVEL APIs | WHITE LABEL TRAVEL API | TOP TRAVEL APIs
philipnathen82
 
PPTX
Farrell__10e_ch04_PowerPoint.pptx Programming Logic and Design slides
bashnahara11
 
PDF
Using licensed Data Loss Prevention (DLP) as a strategic proactive data secur...
Q-Advise
 
PDF
Adobe Illustrator Crack Full Download (Latest Version 2025) Pre-Activated
imang66g
 
PDF
Why Are More Businesses Choosing Partners Over Freelancers for Salesforce.pdf
Cymetrix Software
 
PDF
What companies do with Pharo (ESUG 2025)
ESUG
 
PDF
ChatPharo: an Open Architecture for Understanding How to Talk Live to LLMs
ESUG
 
PPTX
Employee salary prediction using Machine learning Project template.ppt
bhanuk27082004
 
PDF
Troubleshooting Virtual Threads in Java!
Tier1 app
 
PPTX
GALILEO CRS SYSTEM | GALILEO TRAVEL SOFTWARE
philipnathen82
 
PDF
Balancing Resource Capacity and Workloads with OnePlan – Avoid Overloading Te...
OnePlan Solutions
 
Salesforce Pricing Update 2025: Impact, Strategy & Smart Cost Optimization wi...
GetOnCRM Solutions
 
WatchTraderHub - Watch Dealer software with inventory management and multi-ch...
WatchDealer Pavel
 
MiniTool Power Data Recovery Crack New Pre Activated Version Latest 2025
imang66g
 
Role Of Python In Programing Language.pptx
jaykoshti048
 
Enhancing Security in VAST: Towards Static Vulnerability Scanning
ESUG
 
Virtual Threads in Java: A New Dimension of Scalability and Performance
Tier1 app
 
Download iTop VPN Free 6.1.0.5882 Crack Full Activated Pre Latest 2025
imang66g
 
Activate_Methodology_Summary presentatio
annapureddyn
 
Applitools Platform Pulse: What's New and What's Coming - July 2025
Applitools
 
TRAVEL APIs | WHITE LABEL TRAVEL API | TOP TRAVEL APIs
philipnathen82
 
Farrell__10e_ch04_PowerPoint.pptx Programming Logic and Design slides
bashnahara11
 
Using licensed Data Loss Prevention (DLP) as a strategic proactive data secur...
Q-Advise
 
Adobe Illustrator Crack Full Download (Latest Version 2025) Pre-Activated
imang66g
 
Why Are More Businesses Choosing Partners Over Freelancers for Salesforce.pdf
Cymetrix Software
 
What companies do with Pharo (ESUG 2025)
ESUG
 
ChatPharo: an Open Architecture for Understanding How to Talk Live to LLMs
ESUG
 
Employee salary prediction using Machine learning Project template.ppt
bhanuk27082004
 
Troubleshooting Virtual Threads in Java!
Tier1 app
 
GALILEO CRS SYSTEM | GALILEO TRAVEL SOFTWARE
philipnathen82
 
Balancing Resource Capacity and Workloads with OnePlan – Avoid Overloading Te...
OnePlan Solutions
 

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