Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Upcoming SlideShare
What to Upload to SlideShare
Next
Download to read offline and view in fullscreen.

Share

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

Download to read offline

At first it seemed to be just a small enhancement: the addition of “Pattern Matching for instanceof” (JEP 305) in Java 14. No more unnecessary casting after an instanceof, that ought to save us a few seconds a day! However, upon further investigation you’ll quickly discover that pattern matching is not just an enhancement, but rather a vital puzzle piece in the grander scheme of things.

Why were switch expressions added to Java, for example? To make them support pattern matching in a later release! And why did Java 14 bring us records and will Java 15 contain sealed types? Because they could work really well with pattern matching in a later release! These new concepts are the foundation upon which advanced pattern matching features will be built.

So attend this session to get all caught up! You’ll hear about type patterns, deconstruction patterns, nested patterns and even how pattern matching could improve serialization in the future. Live coding included, of course!

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to like this

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

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

At first it seemed to be just a small enhancement: the addition of “Pattern Matching for instanceof” (JEP 305) in Java 14. No more unnecessary casting after an instanceof, that ought to save us a few seconds a day! However, upon further investigation you’ll quickly discover that pattern matching is not just an enhancement, but rather a vital puzzle piece in the grander scheme of things. Why were switch expressions added to Java, for example? To make them support pattern matching in a later release! And why did Java 14 bring us records and will Java 15 contain sealed types? Because they could work really well with pattern matching in a later release! These new concepts are the foundation upon which advanced pattern matching features will be built. So attend this session to get all caught up! You’ll hear about type patterns, deconstruction patterns, nested patterns and even how pattern matching could improve serialization in the future. Live coding included, of course!

Views

Total views

160

On Slideshare

0

From embeds

0

Number of embeds

62

Actions

Downloads

4

Shares

0

Comments

0

Likes

0

×