Slide 1

Slide 1 text

Pattern Matching — И его воображаемые друзья Тагир Валеев

Slide 2

Slide 2 text

Disclaimer Ничего этого нет, это всё плод воображения! 2

Slide 3

Slide 3 text

3 Март: Java 12 2017 2018 2019 2020 Ноябрь: Java Language and Platform Futures: A Sneak Peek by Brian Goetz (Devoxx Belgium) Март: первое обсуждение в amber-dev Май: JEP draft: Pattern Matching Июнь: Submitted as JEP 305 2016 Сентябрь: Java 13 Сентябрь: обновлённые документы: Pattern Matching и Pattern Matching Semantics

Slide 4

Slide 4 text

4 1 год 2 года 3 года Реализовать pattern matching в Java

Slide 5

Slide 5 text

5 1 год 2 года 3 года Реализовать pattern matching в Java Выносить ребёнка Долететь от Земли до Юпитера Построить Дредноут

Slide 6

Slide 6 text

6 Паттерн матчинг: Есть паттерны, которые что-то матчат (или нет)

Slide 7

Slide 7 text

Какие бывают паттерны? (spoiler: разные) 7 ✓ Any pattern: ➢ _

Slide 8

Slide 8 text

Какие бывают паттерны? (spoiler: разные) 8 ✓ Any pattern: ➢ _ ✓ Constant pattern: ➢ 1 ➢ true ➢ TimeUnit.SECONDS ➢ null

Slide 9

Slide 9 text

Какие бывают паттерны? (spoiler: разные) 9 ✓ Any pattern: ➢ _ ✓ Constant pattern: ➢ 1 ➢ true ➢ TimeUnit.SECONDS ➢ null ✓ Type pattern: ➢ String s

Slide 10

Slide 10 text

Какие бывают паттерны? (spoiler: разные) 10 ✓ Any pattern: ➢ _ ✓ Constant pattern: ➢ 1 ➢ true ➢ TimeUnit.SECONDS ➢ null ✓ Type pattern: ➢ String s ✓ Var pattern: ➢ var x

Slide 11

Slide 11 text

Какие бывают паттерны? (spoiler: разные) 11 ✓ Any pattern: ➢ _ ✓ Constant pattern: ➢ 1 ➢ true ➢ TimeUnit.SECONDS ➢ null ✓ Type pattern: ➢ String s ✓ Var pattern: ➢ var x ✓ Deconstruction pattern: ➢ Optional(String s) ➢ Node(Node left, Node right)

Slide 12

Slide 12 text

12 Pattern matching Match operator

Slide 13

Slide 13 text

13 void test(Object obj) { if (obj matches _) { System.out.println("Are you crazy?"); } } Фи

Slide 14

Slide 14 text

14 void test(Object obj) { if (obj matches _) { System.out.println("Are you crazy?"); } if (obj matches var anotherObj) { System.out.println("Oh well... " + anotherObj); } } Фи

Slide 15

Slide 15 text

15 void test(Object obj) { if (obj matches _) { System.out.println("Are you crazy?"); } if (obj matches var anotherObj) { System.out.println("Oh well... " + anotherObj); } if (obj matches 42) { System.out.println("The Answer!"); } if (obj matches "Joker") { System.out.println("Joker!!!"); } } Фи

Slide 16

Slide 16 text

16 void test(Object obj) { if (obj matches _) { System.out.println("Are you crazy?"); } if (obj matches var anotherObj) { System.out.println("Oh well... " + anotherObj); } if (obj matches 42) { System.out.println("The Answer!"); } if (obj matches "Joker") { System.out.println("Joker!!!"); } if (obj matches Number n) { System.out.println(n.longValue()); } if (obj matches Optional(Number n)) { System.out.println("Wrapped "+n.longValue()); } } Фи Ня

Slide 17

Slide 17 text

17 void test(Object obj) { if (obj instanceof Number) { Number n = (Number) obj; System.out.println(n.longValue()); } } Java 1: Версия Java 1 Сколько раз пишем тип 3 2 1

Slide 18

Slide 18 text

18 void test(Object obj) { if (obj instanceof Number) { Number n = (Number) obj; System.out.println(n.longValue()); } if (obj instanceof Number) { var n = (Number) obj; System.out.println(n.longValue()); } } Java 1: Версия Java 1 Сколько раз пишем тип 3 2 1 Java 10: 10

Slide 19

Slide 19 text

19 void test(Object obj) { if (obj instanceof Number) { Number n = (Number) obj; System.out.println(n.longValue()); } if (obj instanceof Number) { var n = (Number) obj; System.out.println(n.longValue()); } if (obj matches Number n) { System.out.println(n.longValue()); } } Java 1: Java 10: Версия Java 1 Сколько раз пишем тип 3 2 1 10 100 Java 100:

Slide 20

Slide 20 text

20 void test(Object obj) { if (obj instanceof Number) { Number n = (Number) obj; System.out.println(n.longValue()); } if (obj instanceof Number) { var n = (Number) obj; System.out.println(n.longValue()); } if (obj instanceof Number n) { System.out.println(n.longValue()); } }

Slide 21

Slide 21 text

21 instanceof instanceof

Slide 22

Slide 22 text

22 instanceof instanceof void test(Object obj) { if (obj instanceof String) { } }

Slide 23

Slide 23 text

23 instanceof instanceof static final int String = 1; void test(Object obj) { if (obj instanceof String) { } } Problem, language designers?

Slide 24

Slide 24 text

24 instanceof instanceof instanceof

Slide 25

Slide 25 text

Консистентность Отдельный оператор matches Сломать старый instanceof

Slide 26

Slide 26 text

Консистентность

Slide 27

Slide 27 text

27 Консистентность

Slide 28

Slide 28 text

28 Pattern matching Match operator Scoping

Slide 29

Slide 29 text

29 if(obj instanceof Number n) { System.out.println(n.longValue()); }

Slide 30

Slide 30 text

30 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {}

Slide 31

Slide 31 text

31 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {} if(obj instanceof Number n || n.longValue() == 0) {}

Slide 32

Slide 32 text

32 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {} if(obj instanceof Number n || n.longValue() == 0) {}

Slide 33

Slide 33 text

33 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {} if(obj instanceof Number n || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) {}

Slide 34

Slide 34 text

34 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {} if(obj instanceof Number n || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) { System.out.println("Zero or not a number at all"); } else { System.out.println(n.longValue()); }

Slide 35

Slide 35 text

35 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {} if(obj instanceof Number n || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) { System.out.println("Zero or not a number at all"); } else { System.out.println(n.longValue()); }

Slide 36

Slide 36 text

36 if(obj instanceof Number n) { System.out.println(n.longValue()); } if(obj instanceof Number n && n.longValue() == 0) {} if(obj instanceof Number n || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) {} if(!(obj instanceof Number n) || n.longValue() == 0) { System.out.println("Zero or not a number at all"); } else { System.out.println(n.longValue()); } if(!(obj instanceof Number n) || n.longValue() == 0) { throw new RuntimeException("Zero or not a number at all"); } System.out.println(n.longValue());

Slide 37

Slide 37 text

37 private Number n = 10; void test(Object obj) { if(!(obj instanceof Number n) || n.longValue() == 0) { System.out.println(n.longValue()); } else { System.out.println(n.longValue()); } }

Slide 38

Slide 38 text

38 void test(Object obj) { if(obj instanceof Number) { System.out.println(obj.longValue()); } } Smart cast!

Slide 39

Slide 39 text

39 Pattern matching Match operator Scoping Deconstruction

Slide 40

Slide 40 text

40 void printShape(Shape shape) { if (shape instanceof Line(Point from, Point to)) { System.out.println("Line: "+from+" - "+to); } else if (shape instanceof Circle(Point(int x, int y), int radius)) { System.out.println("Circle with center "+x+", "+y+" and radius "+radius); } else { System.out.println("Unknown shape"); } }

Slide 41

Slide 41 text

41 void printShape(Shape shape) { if (shape instanceof Line(Point from, Point to)) { System.out.println("Line: "+from+" - "+to); } else if (shape instanceof Circle(Point(int x, int y), int radius)) { System.out.println("Circle with center "+x+", "+y+" and radius "+radius); } else { System.out.println("Unknown shape"); } }

Slide 42

Slide 42 text

42 object Person { def apply(name: String, age: Int, address: Address) = new Person(name, age, address) def unapply(p: Person): Option[Tuple3[String,Int,Address]] = Some((p.name, p.age, p.address)) ... } unapply Programming Scala, 2nd Edition by Alex Payne, Dean Wampler https://www.oreilly.com/library/view/programming-scala-2nd/9781491950135/ch04.html

Slide 43

Slide 43 text

43 unapply Programming Scala, 2nd Edition by Alex Payne, Dean Wampler https://www.oreilly.com/library/view/programming-scala-2nd/9781491950135/ch04.html Option[A] Tuple3[T1,T2,T3] Integer int value T1 _1 T2 _2 T3 _3 A value object Person { def apply(name: String, age: Int, address: Address) = new Person(name, age, address) def unapply(p: Person): Option[Tuple3[String,Int,Address]] = Some((p.name, p.age, p.address)) ... }

Slide 44

Slide 44 text

44 Deconstruct public class User { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public void Deconstruct(out string firstName, out string lastName) { firstName = FirstName; lastName = LastName; } public void Deconstruct(out string firstName, out string lastName, out int age) { firstName = FirstName; lastName = LastName; age = Age; } } Deconstructors for non-tuple types in C# 7.0 https://andrewlock.net/deconstructors-for-non-tuple-types-in-c-7-0/

Slide 45

Slide 45 text

45 componentX class Point(_x: Double, _y: Double) { var x: Double = _x var y: Double = _y operator fun component1() = x operator fun component2() = y }

Slide 46

Slide 46 text

46 componentX class Point(_x: Double, _y: Double) { var x: Double = _x var y: Double = _y fun rotate(angle: Double) { val _x = x*cos(angle)-y*sin(angle) val _y = x*sin(angle)+y*cos(angle) x = _x; y = _y; } operator fun component1() = x operator fun component2() = y }

Slide 47

Slide 47 text

47 componentX class Point(_x: Double, _y: Double) { var x: Double = _x var y: Double = _y fun rotate(angle: Double) { synchronized(this) { val _x = x * cos(angle) - y * sin(angle) val _y = x * sin(angle) + y * cos(angle) x = _x; y = _y; } } operator fun component1() = synchronized(this) { x } operator fun component2() = synchronized(this) { y } }

Slide 48

Slide 48 text

48 Язык Частичное применение JVM? Вложенность объектов Атомарность Перегрузка деконструкторов Имена в объявлении Scala ✓ ✓ 1-3 ✓   C#   0 ✓ +/- ✓ Kotlin  ✓ 0    Хочется ✓ ✓ 0 ✓ ✓ ✓

Slide 49

Slide 49 text

49 void construct(String path, URI uri) { File f1 = new File(path); File f2 = new File(uri); }

Slide 50

Slide 50 text

50 void construct(String path, URI uri) { File f1 = new File(path); File f2 = new File(uri); } void deconstruct(File f1, File f2) { if(f1 instanceof File(String path)) System.out.println(path); if(f2 instanceof File(URI uri)) System.out.println(uri); }

Slide 51

Slide 51 text

51 http://cr.openjdk.java.net/~briangoetz/amber/pattern-match-translation.html public interface __Pattern { /* A method handle used to preprocess a target into an intermediate carrier. The method handle accepts a match target and returns the intermediate carrier. If the isCarrierFree() method returns true, then this method need not be called, and null can be used for the carrier in other method handle */ MethodHandle preprocess(); /* A method handle used to determine if the match succeeds. It accepts the match target and the intermediate carrier returned by preprocess(), and returns a boolean indicating whether the match was successful. If the pattern is declared to always match, then this method need not be called. */ MethodHandle predicate(); /* A method handle to return the i'th component of a successful match. It accepts the match target and the intermediate carrier returned by preprocess(), and returns the component. */ MethodHandle component(int i); /* Indicates that this pattern does not make use of an intermediate carrier, and that the preprocess() method handle is a no-op. Combinators exploit carrier freedom to reduce unnecessary allocation. */ boolean isCarrierFree(); /* Returns the pattern descriptor, which is a MethodType whose return type is the match target, and whose parameter types are the components of the match. */ MethodType descriptor(); }

Slide 52

Slide 52 text

52 class Point { private int x, y; Point(int x, int y) { this.x = x; this.y = y; } extractor Point(int x, int y) { x = this.x; y = this.y; } }

Slide 53

Slide 53 text

53 class Point { private int x, y; Point(int x, int y) { this.x = x; this.y = y; } extractor Point(int x, int y) { x = this.x; y = this.y; } }

Slide 54

Slide 54 text

54 Pattern matching Deconstruction Match operator Scoping Record classes

Slide 55

Slide 55 text

55 record Point(int x, int y);

Slide 56

Slide 56 text

56 ✓ Как назвать геттеры? getX()? Или просто x()? ✓ Нужна ли изменяемость? ➢ Генерировать ли сеттеры (и как их назвать)? ➢ Что будет по умолчанию? Писать final для неизменяемых или non-final для изменяемых? ➢ Генерировать ли конструктор по умолчанию? ➢ Генерировать ли clone()? ✓ Можно ли добавлять дополнительные поля (кэш для вычисляемого значения)? ✓ Как установить инварианты (requireNonNull, a < b и т. д.)? ✓ Как нормализовать? (a < 0 -> a = 0) ✓ В каком порядке генерировать поля в equals? ✓ Как конкретно сравнивать? ➢ Поле-массив: Arrays.equals? ➢ Поле-double: ==? Double.compare? ✓ Может ли record реализовать интерфейс? ✓ Может ли record расширить (абстрактный) класс с полями? ✓ Можно ли расширить record другим record? ✓ Можно ли расширить record обычным классом?

Slide 57

Slide 57 text

57 ✓ Как назвать геттеры? getX()? Или просто x()? ✓ Нужна ли изменяемость? ➢ Генерировать ли сеттеры (и как их назвать)? ➢ Что будет по умолчанию? Писать final для неизменяемых или non-final для изменяемых? ➢ Генерировать ли конструктор по умолчанию? ➢ Генерировать ли clone()? ✓ Можно ли добавлять дополнительные поля (кэш для вычисляемого значения)? ✓ Как установить инварианты (requireNonNull, a < b и т. д.)? ✓ Как нормализовать? (a < 0 -> a = 0) ✓ В каком порядке генерировать поля в equals? ✓ Как конкретно сравнивать? ➢ Поле-массив: Arrays.equals? ➢ Поле-double: ==? Double.compare? ✓ Может ли record реализовать интерфейс? ✓ Может ли record расширить (абстрактный) класс с полями? ✓ Можно ли расширить record другим record? ✓ Можно ли расширить record обычным классом?

Slide 58

Slide 58 text

58 ✓ Как назвать геттеры? getX()? Или просто x()? ✓ Нужна ли изменяемость? ➢ Генерировать ли сеттеры (и как их назвать)? ➢ Что будет по умолчанию? Писать final для неизменяемых или non-final для изменяемых? ➢ Генерировать ли конструктор по умолчанию? ➢ Генерировать ли clone()? ✓ Можно ли добавлять дополнительные поля (кэш для вычисляемого значения)? ✓ Как установить инварианты (requireNonNull, a < b и т. д.)? ✓ Как нормализовать? (a < 0 -> a = 0) ✓ В каком порядке генерировать поля в equals? ✓ Как конкретно сравнивать? ➢ Поле-массив: Arrays.equals? ➢ Поле-double: ==? Double.compare? ✓ Может ли record реализовать интерфейс? ✓ Может ли record расширить (абстрактный) класс с полями? ✓ Можно ли расширить record другим record? ✓ Можно ли расширить record обычным классом?

Slide 59

Slide 59 text

59 Pattern matching Deconstruction Match operator Record classes Scoping Preconditions

Slide 60

Slide 60 text

60 record Range(int lo, int hi) { // Explicit default constructor @Override public Range(int lo, int hi) { // validation logic if (lo > hi) throw new IllegalArgumentException(...); // delegate to default constructor default.this(lo, hi); } }

Slide 61

Slide 61 text

61 Pattern matching Preconditions Deconstruction Match operator Record classes Scoping Static-before- this-super

Slide 62

Slide 62 text

62 class Point { int x, y; Point(int x, int y) { this.x = x; this.y = y; } } class NonNullPoint extends Point { NonNullPoint(int x, int y) { if (x == 0 && y == 0) throw new IllegalArgumentException(); super(x, y); } } http://hg.openjdk.java.net/amber/amber/branches -> stats-before-this-super

Slide 63

Slide 63 text

63 record Range(int lo, int hi) { // Explicit default constructor @Override public Range(int lo, int hi) { // validation logic if (lo > hi) throw new IllegalArgumentException(...); // delegate to default constructor default.this(lo, hi); } }

Slide 64

Slide 64 text

64 record Range(int lo, int hi) requires (lo <= hi) { }

Slide 65

Slide 65 text

65 record Range(int lo, int hi) { // Explicit default constructor @Override public Range(int lo, int hi) { // validation logic if (lo > hi) { int tmp = lo; lo = hi; hi = tmp; } // delegate to default constructor default.this(lo, hi); } }

Slide 66

Slide 66 text

66 void test(Point p) { if(p instanceof Point(int x, int y)) { System.out.println(x+"; "+y); } }

Slide 67

Slide 67 text

67 Pattern matching Static-before- this-super Preconditions Deconstruction Match operator Record classes Scoping Let operator

Slide 68

Slide 68 text

68 void test(Point p) { let Point(int x, int y) = p; System.out.println(x+"; "+y); }

Slide 69

Slide 69 text

69 void test(Object p) { let Point(int x, int y) = p; System.out.println(x+"; "+y); }

Slide 70

Slide 70 text

70 void test(Object p) { let Point(int x, int y) = p else throw new IllegalArgumentException("Oops"); System.out.println(x+"; "+y); }

Slide 71

Slide 71 text

71 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Scoping Enhanced switch

Slide 72

Slide 72 text

72 void printObject(Object obj) { switch(obj) { case String s: System.out.println("Строка-шмока: "+s.trim()); break; case Integer i: System.out.println("Целое-шмелое: "+i); break; case Number n: System.out.println("Число-шмисло: "+n); break; default: System.out.println("Что-то с чем-то"); } }

Slide 73

Slide 73 text

73 void printObject(Object obj) { switch(obj) { case String s: System.out.println("Строка-шмока: "+s.trim()); break; case Number n: System.out.println("Число-шмисло: "+n); break; case Integer i: System.out.println("Целое-шмелое: "+i); break; default: System.out.println("Что-то с чем-то"); } }

Slide 74

Slide 74 text

74 void printObject(Object obj) { switch(obj) { case String s: System.out.println("Строка-шмока: "+s.trim()); break; case Number n: System.out.println("Число-шмисло: "+n); break; case Integer i: System.out.println("Целое-шмелое: "+i); break; default:// == case _: System.out.println("Что-то с чем-то"); } }

Slide 75

Slide 75 text

75 void switchTest(int i) { switch (i) { case 1: System.out.println("One"); break; default: System.out.println("Other"); break; case 2: System.out.println("Two"); break; } }

Slide 76

Slide 76 text

Консистентность

Slide 77

Slide 77 text

77 Консистентность

Slide 78

Slide 78 text

78 Не мы такие, жизнь такая.

Slide 79

Slide 79 text

79 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Scoping Enhanced switch Guards

Slide 80

Slide 80 text

80 void quote(Object obj) { switch (obj) { case Integer i where i < 0: System.out.println("Вы не подскажете, сколько сейчас градусов ниже нуля?"); break; case Double d where Double.isInfinite(d): System.out.println("Бесконечность не предел!"); break; case Number n: System.out.println("Цифры никогда не врут"); } }

Slide 81

Slide 81 text

81 void quote(Object obj) { switch (obj) { case Integer i where i < 0: System.out.println("Вы не подскажете, сколько сейчас градусов ниже нуля?"); break; case Double d where Double.isInfinite(d): System.out.println("Бесконечность не предел!"); break; case Number n: System.out.println("Цифры никогда не врут"); } } obj = 5

Slide 82

Slide 82 text

82 void quote(Object obj) { switch (obj) { case Integer i: if (i < 0) { System.out.println("Вы не подскажете, сколько сейчас градусов ниже нуля?"); } break; case Double d: if (Double.isInfinite(d)) { System.out.println("Бесконечность не предел!"); } break; case Number n: System.out.println("Цифры никогда не врут"); } } obj = 5

Slide 83

Slide 83 text

83 void quote(Object obj) { switch (obj) { case Integer i: if (i >= 0) continue; System.out.println("Вы не подскажете, сколько сейчас градусов ниже нуля?"); break; case Double d: if (Double.isFinite(d)) continue; System.out.println("Бесконечность не предел!"); break; case Number n: System.out.println("Цифры никогда не врут"); } } Continue to the rescue!

Slide 84

Slide 84 text

84 for(int i=0; i<10; i++) { switch (i) { case 1: System.out.println("one"); continue; case 2: System.out.println("two"); break; default: System.out.println("other"); } }

Slide 85

Slide 85 text

85 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Scoping Enhanced switch Guards Nullability Матчит ли String s значение null?

Slide 86

Slide 86 text

86 if (obj instanceof String s) { System.out.println(s.length()); }

Slide 87

Slide 87 text

87 if (obj instanceof String s) { System.out.println(s.length()); } switch (obj) { case String s: System.out.println("String "+s); break; case Integer i: System.out.println("Integer "+i); break; default: System.out.println("other"); break; }

Slide 88

Slide 88 text

88 switch (str) { case "JPoint": System.out.println("Бордюр"); break; case "Joker": System.out.println("Поребрик"); break; default:// == case _: System.out.println("Загогулина вдоль дороги"); break; }

Slide 89

Slide 89 text

89 switch (str) { case "JPoint": System.out.println("Бордюр"); break; case "Joker": System.out.println("Поребрик"); break; case null: System.out.println("Тлен"); break; default:// == case _: System.out.println("Загогулина вдоль дороги"); break; }

Slide 90

Slide 90 text

Консистентность

Slide 91

Slide 91 text

91 Консистентность

Slide 92

Slide 92 text

92 switch (str) { case "JPoint": System.out.println("Бордюр"); break; case "Joker": System.out.println("Поребрик"); break; case null: default:// == case _: System.out.println("Загогулина вдоль дороги"); break; }

Slide 93

Slide 93 text

93 switch (str) { case "JPoint": System.out.println("Бордюр"); break; case "Joker": System.out.println("Поребрик"); break; case _: System.out.println("Загогулина вдоль дороги"); break; }

Slide 94

Slide 94 text

94 default – это…

Slide 95

Slide 95 text

95 default – это case Object _

Slide 96

Slide 96 text

96 default – это case Object _, если switch не по примитиву; case _, если switch по примитиву.

Slide 97

Slide 97 text

97 default – это case Object _, если switch не по примитиву; case _, если switch по примитиву. C is for Consistency

Slide 98

Slide 98 text

98 record Node(String name, Node left, Node right) requires name != null { }

Slide 99

Slide 99 text

99 record Node(String name, Node left, Node right) requires name != null { static Node leaf(String name) { return new Node(name, null, null); } }

Slide 100

Slide 100 text

100 record Node(String name, Node left, Node right) requires name != null { static Node leaf(String name) { return new Node(name, null, null); } } void printIfNode(Object obj) { if (obj instanceof Node(String name, Node left, Node right)){ System.out.println("Name = " + name); System.out.println("Left = " + left); System.out.println("Right = " + right); } }

Slide 101

Slide 101 text

101

Slide 102

Slide 102 text

102 НУЛЛОМАНИЯ ВЫХОД ЕСТЬ NULLABLE PATTERNS Реабилитация-Программистов.01 Бесплатные консультации тимлидам Телефон доверия 03

Slide 103

Slide 103 text

103 void printIfNode(Object obj) { if (obj instanceof Node(String name, Node? left, Node? right)){ System.out.println("Name = " + name); System.out.println("Left = " + left); System.out.println("Right = " + right); } }

Slide 104

Slide 104 text

104 Какая оригинальная мысль! void printIfNode(Object obj) { if (obj instanceof Node(String name, Node? left, Node? right)){ System.out.println("Name = " + name); System.out.println("Left = " + left); System.out.println("Right = " + right); } }

Slide 105

Slide 105 text

105 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Nullability Nullable patterns Scoping Enhanced switch Guards Switch expressions

Slide 106

Slide 106 text

106 void printObject(Object obj) { switch(obj) { case String s: System.out.println("Строка-шмока: "+s.trim()); break; case Integer i: System.out.println("Целое-шмелое: "+i); break; case Number n: System.out.println("Число-шмисло: "+n); break; default: System.out.println("Что-то с чем-то"); } }

Slide 107

Slide 107 text

107 void printObject(Object obj) { System.out.println(switch (obj) { case String s -> "Строка-шмока: " + s.trim(); case Integer i -> "Целое-шмелое: " + i; case Number n -> "Число-шмисло: " + n; default -> "Что-то с чем-то"; }); }

Slide 108

Slide 108 text

108 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> 0; }; }

Slide 109

Slide 109 text

109 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> 0; }; } void test(Object obj) { Number n = obj instanceof Integer ? (Integer)obj : obj instanceof Double ? (Double)obj : 0; }

Slide 110

Slide 110 text

110 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> 0; }; } void test(Object obj) { Number n = (Double) (obj instanceof Integer ? (double)(int)(Integer)obj : obj instanceof Double ? (double)(Double)obj : (double) 0); } Это заботливо добавит компилятор

Slide 111

Slide 111 text

Консистентность

Slide 112

Slide 112 text

112 Консистентность

Slide 113

Slide 113 text

113 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> … }; }

Slide 114

Slide 114 text

114 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> throw new IllegalArgumentException(); }; }

Slide 115

Slide 115 text

115 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> throw new IllegalArgumentException(); }; } void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: throw new IllegalArgumentException(); }; }

Slide 116

Slide 116 text

116 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> throw new IllegalArgumentException(); }; } void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: throw new IllegalArgumentException(); }; }

Slide 117

Slide 117 text

117 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: LOG.debug("Внезапно!"); 0.0; } }

Slide 118

Slide 118 text

118 final Map errorCounts = new HashMap<>(); void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: this.errorCounts.merge("Unexpected value", 1, Integer::sum); // А нолик написать и забыли :( } }

Slide 119

Slide 119 text

119 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: LOG.debug("Внезапно!"); return 0.0; } }

Slide 120

Slide 120 text

120 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: LOG.debug("Внезапно!"); return 0.0; } } void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default -> { LOG.debug("Внезапно!"); return 0.0; } } }

Slide 121

Slide 121 text

121 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Nullability Nullable patterns Scoping Enhanced switch Guards Switch expressions Break-return

Slide 122

Slide 122 text

122 void test(Object obj) { Number n = switch (obj) { case Integer i -> i; case Double d -> d; default: LOG.debug("Внезапно!"); break 0.0; } }

Slide 123

Slide 123 text

123 OOPS_I_DID_IT_AGAIN: for(int i=0; i<10; i++) { int OOPS_I_DID_IT_AGAIN = 5; System.out.println(switch(i) { case 1 -> 10; default: break OOPS_I_DID_IT_AGAIN; }); }

Slide 124

Slide 124 text

124 enum Size { L, M, S } String asString(Size size) { return switch(size) { case L -> "Large"; case M -> "Middle"; case S -> "Small"; }; }

Slide 125

Slide 125 text

125 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Nullability Nullable patterns Scoping Enhanced switch Guards Switch expressions Break-return Exhaustiveness

Slide 126

Slide 126 text

126 abstract class JavaConference {} final class Joker extends JavaConference {} final class JPoint extends JavaConference {} String asString(JavaConference conf) { return switch(conf) { case Joker c -> "Joker: "+c; case JPoint c -> "JPoint: "+c; }; }

Slide 127

Slide 127 text

127 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Nullability Nullable patterns Scoping Enhanced switch Guards Exhaustiveness Switch expressions Break-return Sealed types

Slide 128

Slide 128 text

128 abstract sealed class JavaConference { class Joker extends JavaConference {} class JPoint extends JavaConference {} } String asString(JavaConference conf) { return switch(conf) { case Joker c -> "Joker: "+c; case JPoint c -> "JPoint: "+c; }; }

Slide 129

Slide 129 text

129 Pattern matching Static-before- this-super Preconditions Deconstruction Let operator Match operator Record classes Nullability Nullable patterns Scoping Enhanced switch Guards Sealed types Exhaustiveness Switch expressions Break-return

Slide 130

Slide 130 text

Что почитать: 130 JEP 305: Pattern Matching http://openjdk.java.net/jeps/305 JEP 325: Switch Expressions (Preview) http://openjdk.java.net/jeps/325 Data Classes for Java http://cr.openjdk.java.net/~briangoetz/amber/datum.html Pattern Matching for Java http://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html Pattern Matching for Java -- Semantics http://cr.openjdk.java.net/~briangoetz/amber/pattern-semantics.html Pattern Matching for Java -- Runtime and Translation http://cr.openjdk.java.net/~briangoetz/amber/pattern-match-translation.html The Amber Expert Group mailing list http://mail.openjdk.java.net/pipermail/amber-spec-experts/

Slide 131

Slide 131 text

https://twitter.com/tagir_valeev https://habrahabr.ru/users/lany https://github.com/amaembo [email protected] Спасибо за внимание — jetbrains.com 131