What's new in Java 19: The end of Kotlin? (KotlinConf 2019)

E68309f117985270285ade8082f4877d?s=47 Jake Wharton
December 06, 2019

What's new in Java 19: The end of Kotlin? (KotlinConf 2019)

Kotlin's introduction was a breath of fresh air at a time when the pace of innovation in Java felt glacial. Since that time, development of Java has rapidly increased with an emphasis on fixing the pain points of the language and the efficiency of data representation in the VM. Will Kotlin still have a place in the JVM language ecosystem in a few years?

This talk will compare and contrast how the two languages approach solving the same problems of today's Java. We'll look at data-carrying types, asynchronous programming, nullability, and more. For some of these, we'll also see how one language sometimes influenced the other. Finally, we'll peer a few years into the future to see where both languages are headed and determine whether we still need a Kotlin (spoiler: we probably do!).

Video: https://youtu.be/te3OU9fxC8U

E68309f117985270285ade8082f4877d?s=128

Jake Wharton

December 06, 2019
Tweet

Transcript

  1. What's new in Java 19: The end of Kotlin? @JakeWharton

  2. January 23, 1996 Java 1

  3. September 30, 2004 Java 5

  4. July 28, 2011 Java 7

  5. March 18, 2014 Java 8

  6. September 21, 2017 Java 9

  7. September 21, 2017 Java 9 March 20, 2018 Java 10

  8. March 20, 2018 Java 10 September 25, 2018 Java 11

  9. September 25, 2018 Java 11 March 19, 2019 Java 12

  10. March 19, 2019 Java 12 September 17, 2019 Java 13

  11. March 2020 Java 14 September 2020 Java 15

  12. March 2021 Java 16 September 2021 Java 17

  13. March 2022 Java 18 September 2022 Java 19

  14. 8 September 2022 Java 19

  15. 8 September 2022 Java 19 YOU ARE HERE

  16. Variable Type Inference

  17. var count = 1

  18. var count = 1 var count = 1

  19. var count = 1 val users = mutableListOf<String>() var count

    = 1
  20. var count = 1 val users = mutableListOf<String>() var count

    = 1 final var users = new ArrayList<String>()
  21. var count = 1 val users = mutableListOf<String>() var default:

    String? = null var count = 1 final var users = new ArrayList<String>()
  22. var count = 1 val users = mutableListOf<String>() var default:

    String? = null var count = 1 final var users = new ArrayList<String>() String default = null
  23. var count = 1 val users = mutableListOf<String>() var default:

    String? = null val tasks: Deque<Runnable> = ArrayDeque() var count = 1 final var users = new ArrayList<String>() String default = null
  24. var count = 1 val users = mutableListOf<String>() var default:

    String? = null val tasks: Deque<Runnable> = ArrayDeque() var count = 1 final var users = new ArrayList<String>() String default = null Deque<Runnable> tasks = new ArrayDeque<>()
  25. val run1: () -> Unit = { /* .. */

    }
  26. val run1: () -> Unit = { /* .. */

    } val run2 = { /* .. */ }
  27. val run1: () -> Unit = { /* .. */

    } val run2 = { /* .. */ } Runnable run1 = () -> { /* .. */ };
  28. val run1: () -> Unit = { /* .. */

    } val run2 = { /* .. */ } Runnable run1 = () -> { /* .. */ }; var run2 = () -> { /* .. */ };
  29. val run1: () -> Unit = { /* .. */

    } val run2 = { /* .. */ } Runnable run1 = () -> { /* .. */ }; var run2 = new Runnable() { @Override public void run() { /* .. */ } };
  30. var count = 1 val users = mutableListOf<String>() var default:

    String? = null val tasks: Deque<Runnable> = ArrayDeque() val run1: () -> Unit = { /* .. */ } val run2 = { /* .. */ } var count = 1 final var users = new ArrayList<String>() String default = null Deque<Runnable> tasks = new ArrayDeque<>() Runnable run1 = () -> { /* .. */ }; var run2 = new Runnable() { @Override public void run() { /* .. */ } };
  31. Local Functions

  32. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  33. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  34. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  35. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  36. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  37. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() } public static boolean any(Predicate<Node> predicate) { var seen = new HashSet<Node>(); boolean hasMatch(Node node) { if (!seen.add(node)) return false; // already seen if (predicate.test(node)) return true; // match! return node.getNodes().stream().anyMatch(n -> hasMatch(n)); } return hasMatch(getRoot()); }
  38. public static boolean any(Predicate<Node> predicate) { var seen = new

    HashSet<Node>(); boolean hasMatch(Node node) { if (!seen.add(node)) return false; // already seen if (predicate.test(node)) return true; // match! return node.getNodes().stream().anyMatch(n -> hasMatch(n)); } return hasMatch(getRoot()); }
  39. public static boolean any( Graph, java.util.function.Predicate<Node>); Code: 0: new #7

    // class java/util/HashSet 3: dup 4: invokespecial #9 // Method java/util/HashSet."<init>":()V 7: astore_2 8: aload_2 9: aload_1 10: aload_0 11: invokevirtual #10 // Method getRoot:()Lcom/example/Node; 14: invokestatic #16 // Method local$any$0(...)Z 17: ireturn private static boolean local$any$0( java.util.HashSet, java.util.function.Predicate, Node); Code: ...
  40. public static boolean any( Graph, java.util.function.Predicate<Node>); Code: 0: new #7

    // class java/util/HashSet 3: dup 4: invokespecial #9 // Method java/util/HashSet."<init>":()V 7: astore_2 8: aload_2 9: aload_1 10: aload_0 11: invokevirtual #10 // Method getRoot:()Lcom/example/Node; 14: invokestatic #16 // Method local$any$0(...)Z 17: ireturn private static boolean local$any$0( java.util.HashSet, java.util.function.Predicate, Node); Code: ...
  41. public static boolean any( Graph, java.util.function.Predicate<Node>); Code: 0: new #7

    // class java/util/HashSet 3: dup 4: invokespecial #9 // Method java/util/HashSet."<init>":()V 7: astore_2 8: aload_2 9: aload_1 10: aload_0 11: invokevirtual #10 // Method getRoot:()Lcom/example/Node; 14: invokestatic #16 // Method local$any$0(...)Z 17: ireturn private static boolean local$any$0( java.util.HashSet, java.util.function.Predicate, Node); Code: ...
  42. public static boolean any(Predicate<Node> predicate) { var seen = new

    HashSet<Node>(); boolean hasMatch(Node node) { if (!seen.add(node)) return false; // already seen if (predicate.test(node)) return true; // match! return node.getNodes().stream().anyMatch(n -> hasMatch(n)); } return hasMatch(getRoot()); }
  43. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  44. public static boolean any( Graph, kotlin.jvm.functions.Function1<Node, java.lang.Boolean>); Code: 0: new

    #20 // class java/util/HashSet 3: dup 4: invokespecial #24 // Method java/util/HashSet."<init>":()V 7: astore_2 8: new #26 // class GraphKt$any$1 11: dup 12: aload_2 13: aload_1 14: invokespecial #29 // Method GraphKt$any$1."<init>": (Ljava/util/HashSet; Lkotlin/jvm/functions/Function1;)V 17: astore_3 18: aload_3 19: aload_0 20: invokeinterface #35, 1 // InterfaceMethod Graph.getRoot:()LNode; 25: invokevirtual #39 // Method GraphKt$any$1.invoke:(LNode;)Z 28: ireturn
  45. public static boolean any( Graph, kotlin.jvm.functions.Function1<Node, java.lang.Boolean>); Code: 0: new

    #20 // class java/util/HashSet 3: dup 4: invokespecial #24 // Method java/util/HashSet."<init>":()V 7: astore_2 8: new #26 // class GraphKt$any$1 11: dup 12: aload_2 13: aload_1 14: invokespecial #29 // Method GraphKt$any$1."<init>": (Ljava/util/HashSet; Lkotlin/jvm/functions/Function1;)V 17: astore_3 18: aload_3 19: aload_0 20: invokeinterface #35, 1 // InterfaceMethod Graph.getRoot:()LNode; 25: invokevirtual #39 // Method GraphKt$any$1.invoke:(LNode;)Z 28: ireturn
  46. public static boolean any( Graph, kotlin.jvm.functions.Function1<Node, java.lang.Boolean>); Code: 0: new

    #20 // class java/util/HashSet 3: dup 4: invokespecial #24 // Method java/util/HashSet."<init>":()V 7: astore_2 8: new #26 // class GraphKt$any$1 11: dup 12: aload_2 13: aload_1 14: invokespecial #29 // Method GraphKt$any$1."<init>": (Ljava/util/HashSet; Lkotlin/jvm/functions/Function1;)V 17: astore_3 18: aload_3 19: aload_0 20: invokeinterface #35, 1 // InterfaceMethod Graph.getRoot:()LNode; 25: invokevirtual #39 // Method GraphKt$any$1.invoke:(LNode;)Z 28: ireturn
  47. public static boolean any( Graph, kotlin.jvm.functions.Function1<Node, java.lang.Boolean>); Code: 0: new

    #20 // class java/util/HashSet 3: dup 4: invokespecial #24 // Method java/util/HashSet."<init>":()V 7: astore_2 8: new #26 // class GraphKt$any$1 11: dup 12: aload_2 13: aload_1 14: invokespecial #29 // Method GraphKt$any$1."<init>": (Ljava/util/HashSet; Lkotlin/jvm/functions/Function1;)V 17: astore_3 18: aload_3 19: aload_0 20: invokeinterface #35, 1 // InterfaceMethod Graph.getRoot:()LNode; 25: invokevirtual #39 // Method GraphKt$any$1.invoke:(LNode;)Z 28: ireturn
  48. final class GraphKt$any$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<Node, java.lang.Boolean> { final

    java.util.HashSet $seen; final kotlin.jvm.functions.Function1 $predicate; GraphKt$any$1(java.util.HashSet, kotlin.jvm.functions.Function1); Code: ... public final boolean invoke(Node); Code: ... }
  49. final class GraphKt$any$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<Node, java.lang.Boolean> { final

    java.util.HashSet $seen; final kotlin.jvm.functions.Function1 $predicate; GraphKt$any$1(java.util.HashSet, kotlin.jvm.functions.Function1); Code: ... public final boolean invoke(Node); Code: ... }
  50. final class GraphKt$any$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<Node, java.lang.Boolean> { final

    java.util.HashSet $seen; final kotlin.jvm.functions.Function1 $predicate; GraphKt$any$1(java.util.HashSet, kotlin.jvm.functions.Function1); Code: ... public final boolean invoke(Node); Code: ... }
  51. final class GraphKt$any$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<Node, java.lang.Boolean> { final

    java.util.HashSet $seen; final kotlin.jvm.functions.Function1 $predicate; GraphKt$any$1(java.util.HashSet, kotlin.jvm.functions.Function1); Code: ... public final boolean invoke(Node); Code: ... }
  52. final class GraphKt$any$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<Node, java.lang.Boolean> { final

    java.util.HashSet $seen; final kotlin.jvm.functions.Function1 $predicate; GraphKt$any$1(java.util.HashSet, kotlin.jvm.functions.Function1); Code: ... public final boolean invoke(Node); Code: ... }
  53. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() }
  54. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() } "Optimize generation of local functions" youtrack.jetbrains.com/issue/KT-6336
  55. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() } "Consider more aggresively removing classes from Kotlin local functions" issuetracker.google.com/issues/145231155
  56. fun Graph.any(predicate: (Node) -> Boolean): Boolean { val seen =

    HashSet<Node>() fun Node.hasMatch(): Boolean { if (!seen.add(this)) return false // already seen if (predicate(this)) return true // match! return nodes.any { it.hasMatch() } } return root.hasMatch() } public static boolean any(Predicate<Node> predicate) { var seen = new HashSet<Node>(); boolean hasMatch(Node node) { if (!seen.add(node)) return false; // already seen if (predicate.test(node)) return true; // match! return node.getNodes().stream().anyMatch(n -> hasMatch(n)); } return hasMatch(getRoot()); }
  57. Multiline Strings

  58. fun main() { println(""" SELECT * FROM users WHERE name

    LIKE 'Jake %' """) }
  59. fun main() { println(""" SELECT * FROM users WHERE name

    LIKE 'Jake %' """) } ····SELECT * ····FROM users ····WHERE name LIKE 'Jake %' ··
  60. fun main() { println(""" |SELECT * |FROM users |WHERE name

    LIKE 'Jake %' |""".trimMargin()) } SELECT * FROM users WHERE name LIKE 'Jake %'
  61. fun main() { println(""" !!!SELECT * !!!FROM users !!!WHERE name

    LIKE 'Jake %' !!!""".trimMargin(marginPrefix = "!!!")) } SELECT * FROM users WHERE name LIKE 'Jake %'
  62. fun main() { println(""" SELECT * FROM users WHERE name

    LIKE 'Jake %' """.trimIndent()) } SELECT * FROM users WHERE name LIKE 'Jake %' Margin m a r g i n P r e f i x = " ! ! ! "
  63. fun main() { println(""" SELECT * FROM users WHERE name

    LIKE 'Jake %' """.trimIndent()) } public static void main(String[] args) { System.out.println(""" SELECT * FROM users WHERE name LIKE 'Jake %' """); }
  64. public static void main(String[] args) { System.out.println(""" SELECT * FROM

    users WHERE name LIKE 'Jake %' """); }
  65. public static void main(String[] args) { System.out.println(""" SELECT * FROM

    users WHERE name LIKE 'Jake %' """); } SELECT * FROM users WHERE name LIKE 'Jake %'
  66. public static void main(String[] args) { System.out.println(""" SELECT * FROM

    users WHERE name LIKE 'Jake %' """); } SELECT * FROM users WHERE name LIKE 'Jake %'
  67. public static void main(String[] args) { System.out.println(""" SELECT * \

    FROM users \ WHERE name LIKE 'Jake %' """); } SELECT * FROM users WHERE name LIKE 'Jake %'
  68. assertThat(table.toString()).isEqualTo(""" |┌─┬─┐ ╷ |│ │ │ │ |├─┤ ╵ │

    |│ │ │ |└─┼───┘ | │ |╶─┴─╴ |""".trimMargin())
  69. assertThat(table.toString()).isEqualTo(""" ··|┌─┬─┐·╷ ··|│·│·│·│ ··|├─┤·╵·│ ··|│·│···│ ··|└─┼───┘ ··|··│···· ··|╶─┴─╴·· ··|""".trimMargin())

  70. assertThat(table.toString()).isEqualTo(""" ··|┌─┬─┐·╷ ··|│·│·│·│ ··|├─┤·╵·│ ··|│·│···│ ··|└─┼───┘ ··|··│···· ··|╶─┴─╴·· ··|""".trimMargin()) assertThat(table.toString()).isEqualTo("""

    ····┌─┬─┐·╷ ····│·│·│·│ ····├─┤·╵·│ ····│·│···│ ····└─┼───┘ ······│···· ····╶─┴─╴·· ····""");
  71. assertThat(table.toString()).isEqualTo(""" ··|┌─┬─┐·╷ ··|│·│·│·│ ··|├─┤·╵·│ ··|│·│···│ ··|└─┼───┘ ··|··│···· ··|╶─┴─╴·· ··|""".trimMargin()) assertThat(table.toString()).isEqualTo("""

    ····┌─┬─┐·╷ ····│·│·│·│ ····├─┤·╵·│ ····│·│···│ ····└─┼───┘ ······│···· ····╶─┴─╴·· ····""");
  72. assertThat(table.toString()).isEqualTo(""" ··|┌─┬─┐·╷ ··|│·│·│·│ ··|├─┤·╵·│ ··|│·│···│ ··|└─┼───┘ ··|··│···· ··|╶─┴─╴·· ··|""".trimMargin()) assertThat(table.toString()).isEqualTo("""

    ····┌─┬─┐·╷ ····│·│·│·│ ····├─┤·╵·│ ····│·│···│ ····└─┼───┘ ······│···\s ····╶─┴─╴·\s ····""");
  73. println(""" Hey $name! Hola $name! Hello $name! """.trimIndent())

  74. public static final void sayHi(java.lang.String); Code: 0: new #17 //

    class java/lang/StringBuilder 3: dup 4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V 7: ldc #23 // String \n Hey 9: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 12: aload_0 13: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 16: ldc #29 // String !\n Hola 18: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 21: aload_0 22: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 25: ldc #31 // String !\n Hello 27: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 30: aload_0 31: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 34: ldc #33 // String !\n 36: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 39: invokevirtual #37 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: invokestatic #43 // Method kotlin/text/StringsKt.trimIndent:(Ljava/lang/String;)…; 45: astore_1 46: getstatic #49 // Field java/lang/System.out:Ljava/io/PrintStream; 49: aload_1 50: invokevirtual #55 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 53: return
  75. public static final void sayHi(java.lang.String); Code: 0: new #17 //

    class java/lang/StringBuilder 3: dup 4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V 7: ldc #23 // String \n Hey 9: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 12: aload_0 13: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 16: ldc #29 // String !\n Hola 18: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 21: aload_0 22: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 25: ldc #31 // String !\n Hello 27: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 30: aload_0 31: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 34: ldc #33 // String !\n 36: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 39: invokevirtual #37 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: invokestatic #43 // Method kotlin/text/StringsKt.trimIndent:(Ljava/lang/String;)…; 45: astore_1 46: getstatic #49 // Field java/lang/System.out:Ljava/io/PrintStream; 49: aload_1 50: invokevirtual #55 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 53: return
  76. public static final void sayHi(java.lang.String); Code: 0: new #17 //

    class java/lang/StringBuilder 3: dup 4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V 7: ldc #23 // String \n Hey 9: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 12: aload_0 13: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 16: ldc #29 // String !\n Hola 18: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 21: aload_0 22: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 25: ldc #31 // String !\n Hello 27: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 30: aload_0 31: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 34: ldc #33 // String !\n 36: invokevirtual #27 // Method java/lang/StringBuilder.append:(…)…; 39: invokevirtual #37 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: invokestatic #43 // Method kotlin/text/StringsKt.trimIndent:(Ljava/lang/String;)…; 45: astore_1 46: getstatic #49 // Field java/lang/System.out:Ljava/io/PrintStream; 49: aload_1 50: invokevirtual #55 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 53: return
  77. println(""" Hey $name! Hola $name! Hello $name! """.trimIndent())

  78. println(""" Hey $name! Hola $name! Hello $name! """.trimIndent()) System.out.println("" +

    "Hey " + name + "!\n" + " Hola " + name + "!\n" + " Hello " + name + "!");
  79. System.out.println("" + "Hey " + name + "!\n" + "

    Hola " + name + "!\n" + " Hello " + name + "!");
  80. public static void sayHi(java.lang.String); Code: 0: getstatic #2 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #4 // Method java/io/PrintStream.println:(…)V 14: return
  81. public static void sayHi(java.lang.String); Code: 0: getstatic #2 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #4 // Method java/io/PrintStream.println:(…)V 14: return
  82. public static void sayHi(java.lang.String); Code: 0: getstatic #2 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #4 // Method java/io/PrintStream.println:(…)V 14: return BootstrapMethods: 0: #19 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/MethodType;Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #20 Hey \u0001!\n Hola \u0001!\n Hello \u0001!
  83. public static void sayHi(java.lang.String); Code: 0: getstatic #2 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #4 // Method java/io/PrintStream.println:(…)V 14: return BootstrapMethods: 0: #19 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/MethodType;Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #20 Hey \u0001!\n Hola \u0001!\n Hello \u0001!
  84. System.out.println("" + "Hey " + name + "!\n" + "

    Hola " + name + "!\n" + " Hello " + name + "!");
  85. System.out.println(""" Hey %s! Hola %s! Hello %s! """.formatted(name, name, name));

  86. public static void sayHi(java.lang.String); Code: 0: getstatic #9 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #15, 0 // InvokeDynamic #0:format: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #19 // Method java/io/PrintStream.println:(…)V 14: return
  87. public static void sayHi(java.lang.String); Code: 0: getstatic #9 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #15, 0 // InvokeDynamic #0:format: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #19 // Method java/io/PrintStream.println:(…)V 14: return
  88. public static void sayHi(java.lang.String); Code: 0: getstatic #9 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #15, 0 // InvokeDynamic #0:format: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #19 // Method java/io/PrintStream.println:(…)V 14: return BootstrapMethods: 0: #34 REF_invokeStatic java/util/Formatter.formatterBootstrap: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/MethodType;Ljava/lang/String;II)… Method arguments: #41 Hey %s!\n Hola %s!\n Hello %s! #43 1 #44 0
  89. public static void sayHi(java.lang.String); Code: 0: getstatic #9 // Field

    java/lang/System.out:… 3: aload_0 4: aload_0 5: aload_0 6: invokedynamic #15, 0 // InvokeDynamic #0:format: (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String; 11: invokevirtual #19 // Method java/io/PrintStream.println:(…)V 14: return BootstrapMethods: 0: #34 REF_invokeStatic java/util/Formatter.formatterBootstrap: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/MethodType;Ljava/lang/String;II)… Method arguments: #41 Hey %s!\n Hola %s!\n Hello %s! #43 1 #44 0
  90. System.out.println(""" Hey %s! Hola %s! Hello %s! """.formatted(name, name, name));

  91. println(""" Hey $name! Hola $name! Hello $name! """.trimIndent()) System.out.println(""" Hey

    %s! Hola %s! Hello %s! """.formatted(name, name, name));
  92. println(""" Hey $name! Hola $name! Hello $name! """.trimIndent()) System.out.println(""" Hey

    %s! Hola %s! Hello %s! """.formatted(name, name, name)); "Indify String Concatenation (StringConcatFactory)" youtrack.jetbrains.com/issue/KT-21147
  93. Value-Based Classes

  94. data class Person(val name: String, val age: Int)

  95. data class Person(val name: String, val age: Int) record Person(String

    name, int age) { }
  96. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  97. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  98. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  99. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  100. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  101. public java.lang.String getName(); public int getAge(); public java.lang.String toString(); Code:

    0: new #44 // class java/lang/StringBuilder 3: dup 4: invokespecial #45 // Method java/lang/StringBuilder."<init>":()V 7: ldc #47 // String Person(name= 9: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: aload_0 13: getfield #11 // Field name:Ljava/lang/String; 16: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: ldc #53 // String , age= 21: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: aload_0 25: getfield #19 // Field age:I 28: invokevirtual #56 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 31: ldc #58 // String ) 33: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 36: invokevirtual #60 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 39: areturn public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  102. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); Code: 0: aload_0 1: invokedynamic #19, 0 // InvokeDynamic #0:toString:(LPerson;)Ljava/lang/String; 6: areturn public int hashCode(); public boolean equals(java.lang.Object); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); Code: 0: new #44 // class java/lang/StringBuilder 3: dup 4: invokespecial #45 // Method java/lang/StringBuilder."<init>":()V 7: ldc #47 // String Person(name= 9: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: aload_0 13: getfield #11 // Field name:Ljava/lang/String; 16: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: ldc #53 // String , age= 21: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: aload_0 25: getfield #19 // Field age:I 28: invokevirtual #56 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 31: ldc #58 // String ) 33: invokevirtual #51 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 36: invokevirtual #60 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 39: areturn public int hashCode();
  103. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); Code: 0: aload_0 1: invokedynamic #19, 0 // InvokeDynamic #0:toString:(LPerson;)Ljava/lang/String; 6: areturn public int hashCode(); public boolean equals(java.lang.Object); }
  104. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); Code: 0: aload_0 1: invokedynamic #19, 0 // InvokeDynamic #0:toString:(LPerson;)Ljava/lang/String; 6: areturn public int hashCode(); public boolean equals(java.lang.Object); } BootstrapMethods: 0: #42 REF_invokeStatic java/lang/runtime/ObjectMethods.bootstrap: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String; [Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object; Method arguments: #8 Person #49 name;age #51 REF_getField Person.name:Ljava/lang/String; #52 REF_getField Person.age:I Code: 0: aload_0 1: invokedynamic #23, 0 // InvokeDynamic #0:hashCode:(LPerson;)I 6: areturn
  105. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); Code: 0: aload_0 1: invokedynamic #19, 0 // InvokeDynamic #0:toString:(LPerson;)Ljava/lang/String; 6: areturn public int hashCode(); public boolean equals(java.lang.Object); } BootstrapMethods: 0: #42 REF_invokeStatic java/lang/runtime/ObjectMethods.bootstrap: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String; [Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object; Method arguments: #8 Person #49 name;age #51 REF_getField Person.name:Ljava/lang/String; #52 REF_getField Person.age:I Code: 0: aload_0 1: invokedynamic #23, 0 // InvokeDynamic #0:hashCode:(LPerson;)I 6: areturn
  106. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); Code: 0: aload_0 1: invokedynamic #23, 0 // InvokeDynamic #0:hashCode:(LPerson;)I 6: areturn public boolean equals(java.lang.Object); } BootstrapMethods: 0: #42 REF_invokeStatic java/lang/runtime/ObjectMethods.bootstrap: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String; [Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object; Method arguments: #8 Person #49 name;age #51 REF_getField Person.name:Ljava/lang/String; #52 REF_getField Person.age:I Code: 0: aload_0 1: invokedynamic #19, 0 // InvokeDynamic #0:toString:(LPerson;)Ljava/lang/String; 6: areturn
  107. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); Code: 0: aload_0 1: invokedynamic #27, 0 // InvokeDynamic #0:equals:(LPerson;Ljava/lang/Object;)Z 6: areturn } BootstrapMethods: 0: #42 REF_invokeStatic java/lang/runtime/ObjectMethods.bootstrap: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String; Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String; [Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object; Method arguments: #8 Person #49 name;age #51 REF_getField Person.name:Ljava/lang/String; #52 REF_getField Person.age:I Code: 0: aload_0 1: invokedynamic #23, 0 // InvokeDynamic #0:hashCode:(LPerson;)I 6: areturn Code: 0: aload_0 1: invokedynamic #27, 0 /q InvokeDynamic #0:equals:(LPerson;Ljava/lang/Object;)Z 6: areturn
  108. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… } public final class Person extends java.lang.Record { private final java.lang.String name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); } Code: 0: aload_0 1: invokedynamic #27, 0 // InvokeDynamic #0:equals:(LPerson;Ljava/lang/Object;)Z 6: areturn
  109. data class Person(val name: String, val age: Int) record Person(String

    name, int age) { }
  110. data class Person(val name: String, val age: Int) record Person(String

    name, int age) { } "Use StringConcatFactory for data class toString when targeting JVM 9+ " youtrack.jetbrains.com/issue/KT-35176
  111. Sealed Hierarchies

  112. data class Person(val name: String, val age: Int)

  113. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer()
  114. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() record Person(String name, int age) { }
  115. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Developer { } record Person(String name, int age) extends Developer { } record Business(String name) extends Developer { }
  116. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() class extends extends sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { }
  117. sealed class Developer { abstract val name: String } data

    class Person(override val name: String, val age: Int) : Developer() data class Business(override val name: String) : Developer() sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { }
  118. sealed class Developer { abstract val name: String } data

    class Person(override val name: String, val age: Int) : Developer() data class Business(override val name: String) : Developer() sealed interface Developer { String name(); } record Person(@Override String name, int age) implements Developer { } record Business(@Override String name) implements Developer { }
  119. public abstract class Developer { public abstract java.lang.String getName(); private

    Developer(); public synthetic Developer(kotlin.jvm.internal.DefaultConstructorMarker); } public interface Developer { public abstract java.lang.String name(); } PermittedSubtypes: Person Business
  120. public abstract class Developer { public abstract java.lang.String getName(); private

    Developer(); public synthetic Developer(kotlin.jvm.internal.DefaultConstructorMarker); } public interface Developer { public abstract java.lang.String name(); } PermittedSubtypes: Person Business
  121. public abstract class Developer { public abstract java.lang.String getName(); private

    Developer(); public synthetic Developer(kotlin.jvm.internal.DefaultConstructorMarker); } public interface Developer { public abstract java.lang.String name(); } PermittedSubtypes: Person Business
  122. sealed class Developer { abstract val name: String } data

    class Person(override val name: String, val age: Int) : Developer() data class Business(override val name: String) : Developer() sealed interface Developer { String name(); } record Person(@Override String name, int age) implements Developer { } record Business(@Override String name) implements Developer { }
  123. Type Matching

  124. val o: Any = 1

  125. val o: Any = 1 if (o is Int) {

    }
  126. val o: Any = 1 if (o is Int) {

    println(o + 1) }
  127. val o: Any = 1 if (o is Int) {

    println(o + 1) } Object o = 1; if (o instanceof Integer i) { System.out.println(i + 1); }
  128. Object o = 1; if (o instanceof Integer i) {

    System.out.println(i + 1); }
  129. Object o = 1; if (o instanceof Integer) { Integer

    i = (Integer) o; System.out.println(i + 1); }
  130. Object o = 1; if (o instanceof Integer) { Integer

    i = (Integer) o; System.out.println(i + 1); } static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue(); }
  131. Object o = 1; if (o instanceof Integer) { Integer

    i = (Integer) o; System.out.println(i + 1); record(o); } static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue(); }
  132. Object o = 1; if (o instanceof Integer) { System.out.println(o

    + 1); record(o); } static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue(); }
  133. Object o = 1; if (o instanceof Integer) { System.out.println(o

    + 1); record(o); } static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue(); }
  134. Object o = 1; if (o instanceof Integer) { System.out.println(o

    + 1); record(o); } static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue(); }
  135. Object o = 1; if (o instanceof Integer i) {

    System.out.println(i + 1); record(o); } static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue(); }
  136. val o: Any = 1 if (o is Int) {

    println(o + 1) } Object o = 1; if (o instanceof Integer i) { System.out.println(i + 1); } record(o); static void record(Object o) { objects.add(o); } static void record(Number n) { sum += n.intValue();
  137. Destructuring

  138. data class Person(val name: String, val age: Int)

  139. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12)
  140. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice
  141. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice val people = listOf(alice) for ((name, age) in people) { // .. }
  142. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice val people = listOf(alice) for ((name, age) in people) { // .. } val display = people.map { (name, age) -> "$name is $age years old" }
  143. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice
  144. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice
  145. ⋮ 10: aload_0 11: invokevirtual #12 // Method Person.component1:()Ljava/lang/String; 14:

    astore_1 15: aload_0 16: invokevirtual #16 // Method Person.component2:()I 19: istore_2 ⋮
  146. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy and component methods omitted… }
  147. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy methods omitted… public java.lang.String component1(); public int component2(); } a n d c o m p o n e n t
  148. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice
  149. data class Person( val name: String, val nickname: String, val

    age: Int ) val alice = Person("Alice", "Ali", 12) val (name, age) = alice
  150. public final class Person { private final java.lang.String name; private

    final int age; public Person(java.lang.String, int); public java.lang.String getName(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy methods omitted… public java.lang.String component1(); public int component2(); }
  151. public final class Person { private final java.lang.String name; +

    private final java.lang.String nickname; private final int age; - public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String getName(); + public java.lang.String getNickname(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy methods omitted… public java.lang.String component1(); - public int component2(); + public java.lang.String component2(); + public int component3(); }
  152. public final class Person { private final java.lang.String name; +

    private final java.lang.String nickname; private final int age; - public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String getName(); + public java.lang.String getNickname(); public int getAge(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); // copy methods omitted… public java.lang.String component1(); - public int component2(); + public java.lang.String component2(); + public int component3(); }
  153. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice
  154. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice record Person(String name, int age) { } var alice = new Person("Alice", 12);
  155. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice record Person(String name, int age) { } Object alice = new Person("Alice", 12);
  156. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice record Person(String name, int age) { } Object alice = new Person("Alice", 12); if (alice instanceof Person alicePerson) { // ... }
  157. data class Person(val name: String, val age: Int) val alice

    = Person("Alice", 12) val (name, age) = alice record Person(String name, int age) { } Object alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... } alicePerson
  158. data class Person(val name: String, val age: Int) val alice:

    Any = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... } record Person(String name, int age) { } Object alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... }
  159. record Person(String name, int age) { } Object alice =

    new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... }
  160. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  161. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); }
  162. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); }
  163. record Person(String name, int age) { } Object alice =

    new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... }
  164. record Person(String name, String nickname, int age) { } Object

    alice = new Person("Alice", "Ali", 12); if (alice instanceof Person(var name, var age)) { // ... }
  165. public final class Person extends java.lang.Record { private final java.lang.String

    name; private final int age; public Person(java.lang.String, int); public java.lang.String name(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); }
  166. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; - public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); - public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); }
  167. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; - public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); - public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); }
  168. record Person(String name, String nickname, int age) { }

  169. record Person(String name, String nickname, int age) { Person(String name,

    int age) { this(name, null, age); } }
  170. record Person(String name, String nickname, int age) { Person(String name,

    int age) { this(name, null, age); } // WARNING: 100% made-up syntax by me! destructor Person(String, int) { return p -> deconstruct(Person::name, Person::age); } }
  171. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; - public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); - public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); }
  172. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); }
  173. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); data class Person(val name: String, val age: Int) val alice: Any = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... } record Person(String name, int age) { } Object alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... }
  174. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); sealed class Developer data class Person(val name: String, val age: Int): Developer() data class Business(val name: String): Developer() val alice: Any = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Object alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... }
  175. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } Object alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... } sealed class Developer data class Person(val name: String, val age: Int): Developer() data class Business(val name: String): Developer() val alice: Any = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... } public final class Person extends java.lang.Record { private final java.lang.String name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString();
  176. sealed class Developer data class Person(val name: String, val age:

    Int): Developer() data class Business(val name: String): Developer() val alice: Developer = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... } Object public final class Person extends java.lang.Record { private final java.lang.String name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString();
  177. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); sealed class Developer data class Person(val name: String, val age: Int): Developer() data class Business(val name: String): Developer() val alice: Developer = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... } Object
  178. sealed class Developer data class Person(val name: String, val age:

    Int): Developer() data class Business(val name: String): Developer() val alice: Developer = Person("Alice", 12) if (alice is Person) { val (name, age) = alice // ... }
  179. sealed class Developer data class Person(val name: String, val age:

    Int): Developer() data class Business(val name: String): Developer() val alice: Developer = Person("Alice", 12) when (alice) { is Person -> { val (name, age) = alice // ... } is Business -> { // ... } } if
  180. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); if (alice instanceof Person(var name, var age)) { // ... }
  181. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... } if i n s t a n c e o f
  182. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... }
  183. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... }
  184. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... }
  185. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... }
  186. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?I)(); + public static java.lang.runtime.PatternHandle %pattern%Person%(Ljava|lang|String?Ljava|lang|String?I)(); } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... }
  187. public final class Person extends java.lang.Record { private final java.lang.String

    name; + private final java.lang.String nickname; private final int age; public Person(java.lang.String, int); + public Person(java.lang.String, java.lang.String, int); public java.lang.String name(); + public java.lang.String nickname(); public int age(); val alice: Developer = Person("Alice", 12) when (alice) { is Person -> { val (name, age) = alice // ... } is Business -> // ... } Developer alice = new Person("Alice", 12); switch (alice) { case Person(var name, var age) -> // ... case Business b -> // ... } sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { }
  188. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { }
  189. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { }
  190. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //...
  191. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App) { }
  192. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person) { }
  193. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { }
  194. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" }
  195. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else if (download is Movie) { }
  196. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else if (download is Movie && download.director.name == "Alice") { }
  197. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else if (download is Movie && download.director.name == "Alice") { "Alice's movie ${download.title}" }
  198. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else if (download is Movie && download.director.name == "Alice") { "Alice's movie ${download.title}" } else { "Not by Alice" }
  199. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() data class TvShow(val title: String, val showRunner: Person) : Download() val download: Download = //... val result = if (download is App && download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else if (download is Movie && download.director.name == "Alice") { "Alice's movie ${download.title}" } else { "Not by Alice" }
  200. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //...
  201. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = when (download) { is App -> is Movie -> }
  202. sealed class Developer data class Person(val name: String, val age:

    Int) : Developer() data class Business(val name: String) : Developer() sealed class Download data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = when (download) { is App -> if (download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else { "Not by Alice" } is Movie -> }
  203. data class Business(val name: String) : Developer() sealed class Download

    data class App(val name: String, val developer: Developer) : Download() data class Movie(val title: String, val director: Person) : Download() val download: Download = //... val result = when (download) { is App -> if (download.developer is Person && download.developer.name == "Alice") { "Alice's app ${download.name}" } else { "Not by Alice" } is Movie -> if (download.director.name == "Alice") { "Alice's movie ${download.title}" } else { "Not by Alice" } }
  204. data class Movie(val title: String, val director: Person) : Download()

    val download: Download = //... val result = when (download) { is App -> when (download.developer) { is Person -> if (download.developer.name == "Alice") { "Alice's app ${download.name}" } else { "Not by Alice" } else -> "Not by Alice" } is Movie -> if (download.director.name == "Alice") { "Alice's movie ${download.title}" } else { "Not by Alice" } }
  205. val result = when (download) { is App -> {

    val (name, developer) = download when (developer) { is Person -> if (developer.name == "Alice") { "Alice's app $name" } else { "Not by Alice" } else -> "Not by Alice" } } is Movie -> { val (title, directory) = download if (director.name == "Alice") { "Alice's movie $title" } else { "Not by Alice" } } } download download download
  206. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { }
  207. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //...
  208. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App -> case Movie -> };
  209. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App -> case Movie -> };
  210. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App -> case Movie -> };
  211. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, var developer) -> case Movie -> };
  212. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, var developer) -> case Movie -> };
  213. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> case Movie -> }; var developer
  214. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> case Movie -> }; var developer
  215. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie -> };
  216. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie(var title, Person("Alice", _)) -> };
  217. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie(var title, Person("Alice", _)) -> "Alice's movie " + title };
  218. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie(var title, Person("Alice", _)) -> "Alice's movie " + title case App(_), Movie(_) -> "Not by Alice" };
  219. val download: Download = //... val result = when (download)

    { is App -> { val (name, developer) = download when (developer) { is Person -> if (developer.name == "Alice") { "Alice's app $name" } else { "Not by Alice" } else -> "Not by Alice" } } is Movie -> { val (title, directory) = download if (director.name == "Alice") { "Alice's movie $title" } else { "Not by Alice" } } } Download download = //... var result = switch (download) { case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie(var title, Person("Alice", _)) -> "Alice's movie " + title case App(_), Movie(_) -> "Not by Alice" }; sealed interface Developer { } record Person(String name, int age) implements Developer { } record Business(String name) implements Developer { } sealed interface Download { } record App(String name, Developer developer) implements Download { } record Movie(String title, Person director) implements Download { }
  220. Coroutines

  221. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } }
  222. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } } 
 
 
 
 
 
 
 
 
 
 0 1 2 3 4 5 6 7 8 9 10
  223. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } }
  224. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } }
  225. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } }
  226. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } } public static void main(String... args) { Executor e = Executors.newWorkStealingPool(); for (int count = 10; count >= 0; count--) { final var finalCount = count; e.execute(() -> { Thread.sleep(100 * finalCount); System.out.println(finalCount); }); } }
  227. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } } public static void main(String... args) { Executor e = Executors.newWorkStealingPool(); for (int count = 10; count >= 0; count--) { final var finalCount = count; e.execute(() -> { Thread.sleep(100 * finalCount); System.out.println(finalCount); }); } }
  228. suspend fun main() = coroutineScope { for (count in 10

    downTo 0) { launch { delay(100.milliseconds * count) println(count) } } } public static void main(String... args) { Executor e = Executors.newWorkStealingPool(); for (int count = 10; count >= 0; count--) { final var finalCount = count; e.execute(() -> { Thread.sleep(100 * finalCount); System.out.println(finalCount); }); } }
  229. The end of Kotlin?

  230. var count = 1 final var users = new ArrayList<String>()

    The end of Kotlin? Java 10: Variable Type Inference
  231. public static boolean any(Predicate<Node> predicate) { var seen = new

    HashSet<Node>(); boolean hasMatch(Node node) { if (!seen.add(node)) return false; // already seen if (predicate.test(node)) return true; // match! return node.getNodes().stream().anyMatch(n -> hasMatch(n)); } return hasMatch(getRoot()); } Java 16/17: Local Methods
  232. public static void main(String[] args) { System.out.println(""" SELECT * FROM

    users WHERE name LIKE 'Jake %' """); } Java 15: Multiline Strings
  233. record Person(String name, int age) { } Java 15/16: Records

  234. sealed interface Developer { } record Person(String name, int age)

    implements Developer { } record Business(String name) implements Developer { } Java 15/16: Sealed Hierarchies
  235. Object o = 1; if (o instanceof Integer i) {

    System.out.println(i + 1); } Java 15/16: Type Matching
  236. Download download = //... var result = switch (download) {

    case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie(var title, Person("Alice", _)) -> "Alice's movie " + title case App(_), Movie(_) -> "Not by Alice" }; Java 16/17: Pattern Matching
  237. Download download = //... var result = switch (download) {

    case App(var name, Person("Alice", _)) -> "Alice's app " + name case Movie(var title, Person("Alice", _)) -> "Alice's movie " + title case App(_), Movie(_) -> "Not by Alice" }; Java 14: Expression Switch
  238. public static void main(String... args) { Executor e = Executors.newWorkStealingPool();

    for (int count = 10; count >= 0; count--) { final var finalCount = count; e.execute(() -> { Thread.sleep(100 * finalCount); System.out.println(finalCount); }); } } Java 16/17: Virtual Threads
  239. The end of Kotlin? New Java APIs and new VM

    improvements also help Kotlin
  240. The end of Kotlin? New Java APIs and new VM

    improvements also help Kotlin API, bytecode, and VM changes for new Java language features are also available for use by kotlinc
  241. The end of Kotlin? New Java APIs and new VM

    improvements also help Kotlin API, bytecode, and VM changes for new Java language features are also available for use by kotlinc No plans to tackle nullability in Java!
  242. The end of Kotlin? New Java APIs and new VM

    improvements also help Kotlin API, bytecode, and VM changes for new Java language features are also available for use by kotlinc No plans to tackle nullability in Java! Java in 3 years will also be competing with Kotlin in 3 years,
 not the Kotlin of today
  243. The end of Kotlin? New Java APIs and new VM

    improvements also help Kotlin API, bytecode, and VM changes for new Java language features are also available for use by kotlinc No plans to tackle nullability in Java! Java in 3 years will also be competing with Kotlin in 3 years,
 not the Kotlin of today Kotlin has an IDE to potentially evolve in ways that Java cannot
  244. The end of Kotlin? New Java APIs and new VM

    improvements also help Kotlin API, bytecode, and VM changes for new Java language features are also available for use by kotlinc No plans to tackle nullability in Java! Java in 3 years will also be competing with Kotlin in 3 years,
 not the Kotlin of today Kotlin has an IDE to potentially evolve in ways that Java cannot Kotlin has first-class multiplatform
  245. What's new in Java 19: The end of Kotlin? @JakeWharton

    [ Nope! ]