Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin as a Modernized Java @ Oracle Code One 2018

Kotlin as a Modernized Java @ Oracle Code One 2018

Kotlin was designed with Java developers in mind. Java is evolving, but the language evolution is mostly limited to adding new features. It is nearly impossible to remove features that have proved to be troublesome from a language as popular as Java. This session looks at those features that have been either removed or radically adjusted in Kotlin and how this leads to better, modern, easier-to-read code in Kotlin while still retaining the ability to leverage all the Java libraries in the Java ecosystem.

Roman Elizarov

October 25, 2018
Tweet

More Decks by Roman Elizarov

Other Decks in Programming

Transcript

  1. Kotlin as a Modernized Java
    Programming in XXI Century
    Presented at JavaOne, 2018
    email [email protected]
    Roman Elizarov
    @relizarov

    View Slide

  2. 1995 2003 2004 2011

    View Slide

  3. What if Java was designed in 201x?

    View Slide

  4. Error handling

    View Slide

  5. Error handling
    int res = fread(buf, n, file);

    View Slide

  6. Error handling
    int res = fread(buf, n, file);
    if (res < n) { // error or EOF
    if (ferror(file) != 0) {
    // handle error
    }
    return;
    }

    View Slide

  7. Error handling
    int res = fread(buf, n, file);
    if (res < n) { … }
    res = fread(buf, m, file);
    if (res < n) { // error or EOF
    if (ferror(file) != 0) {
    // handle error
    }
    return;
    }

    View Slide

  8. Exceptions
    try {
    FileInputStream file = new FileInputStream(fileName);
    // …
    int res = file.read(buf, 0, n); // throws exception
    // …
    } catch (IOException e) {
    // handle error
    }

    View Slide

  9. Exceptions
    try {
    FileInputStream file = new FileInputStream(fileName);
    // …
    int res = file.read(buf, 0, n);
    // …
    res = file.read(buf, 0, m); // throws exception
    // …
    } catch (IOException e) {
    // handle error
    }

    View Slide

  10. Exceptions
    try {
    Data result = work(fileName);
    } catch (IOException e) {
    // handle error
    }

    View Slide

  11. Checked Exceptions
    Data work(String fileName) throws IOException {
    FileInputStream file = new FileInputStream(fileName);
    // …
    int res = file.read(buf, 0, n);
    // …
    res = file.read(buf, 0, m);
    // …
    }

    View Slide

  12. View Slide

  13. 1995
    1.0
    2004
    5
    Generics

    View Slide

  14. 1995
    1.0
    2004
    5
    Generics
    Lambdas (FP)
    2014
    8

    View Slide

  15. Imperative
    List results = new ArrayList<>();
    for (String fileName : fileNames) {
    Result work = work(fileName);
    results.add(work);
    }

    View Slide

  16. Func%onal & Declara%ve
    List results = fileNames.stream()
    .map(fileName -> work(fileName))
    .collect(Collectors.toList());

    View Slide

  17. Functional + Checked Exceptions = !
    List results = fileNames.stream()
    .map(fileName -> work(fileName))
    .collect(Collectors.toList());

    View Slide

  18. XXI Century Languages
    2000 2003
    2005
    2004
    2009 2010 2011 2011
    2012 2014

    View Slide

  19. If Java was designed in 201x
    It would not have checked exceptions

    View Slide

  20. Func%onal

    View Slide

  21. Functional in Java
    List results = fileNames.stream()
    .map(fileName -> work(fileName))
    .collect(Collectors.toList());

    View Slide

  22. Functional in Java as an afterthought
    List results = fileNames.stream()
    .map(fileName -> work(fileName))
    .collect(Collectors.toList());

    View Slide

  23. Kotlin is designed to be functional
    val results = fileNames
    .map { fileName -> work(fileName) }

    View Slide

  24. val results = fileNames
    .map { work(it) }

    View Slide

  25. val results = fileNames
    .map { work(it) }
    .filter { it.isGood() }

    View Slide

  26. val results = fileNames
    .map { work(it) }
    .filter { it.isGood() }
    .doMyProcessing()

    View Slide

  27. val results = fileNames
    .map { work(it) }
    .filter { it.isGood() }
    .doMyProcessing()

    View Slide

  28. val results = MyUtils.doMyProcessing(fileNames
    .map { work(it) }
    .filter { it.isGood() })

    View Slide

  29. val results = fileNames
    .map { work(it) }
    .filter { it.isGood() }
    .doMyProcessing()

    View Slide

  30. Kotlin extension functions
    val results = fileNames
    .map { work(it) }
    .filter { it.isGood() }
    .doMyProcessing()
    fun List.doMyProcessing() = …

    View Slide

  31. Kotlin top-level functions
    val results = fileNames
    .map { work(it) }
    .filter { it.isGood() }
    .doMyProcessing()
    fun List.doMyProcessing() = …

    View Slide

  32. If Java was designed in 201x
    It would have been functional
    by design

    View Slide

  33. More generic casualties…

    View Slide

  34. More generic casualties…
    List strings = …

    View Slide

  35. More generic casualties…
    List strings = …
    List dates = …

    View Slide

  36. More generic casualties…
    List strings = …
    List date = …
    List ints = …

    View Slide

  37. More generic casualties…
    List strings = …
    List date = …
    List ints = …

    View Slide

  38. Primitives

    View Slide

  39. C for Consistency
    myDate.toString()

    View Slide

  40. C for Consistency
    myDate.toString()
    String.valueOf(myInt)

    View Slide

  41. Equality
    myInt == otherInt

    View Slide

  42. Equality
    myInt == otherInt
    myString == otherString
    Oops!

    View Slide

  43. Equality
    myInt == otherInt
    myString.equals(otherString)

    View Slide

  44. If Java was designed in 201x
    It would not have exposed primitives

    View Slide

  45. Kotlin hides primi/ves
    myDate.toString()
    myInt.toString()

    View Slide

  46. Kotlin hides primitives
    myDate.toString()
    myInt.toString()
    List
    List

    View Slide

  47. Kotlin hides primitives
    myDate.toString()
    myInt.toString()
    List
    List
    dates.map { it.toString() }
    ints.map { it.toString() }

    View Slide

  48. Kotlin hides primitives
    myDate.toString()
    myInt.toString()
    List
    List
    dates.map { it.toString() }
    ints.map { it.toString() }
    myDate == otherDate
    myInt == otherInt

    View Slide

  49. Local variable type inference
    1995
    1.0
    2004
    5
    2018
    10
    2014
    8

    View Slide

  50. Before type inference
    int count = …
    double average = …
    List strings = …
    Map> items = …

    View Slide

  51. With type inference
    var count = …
    var average = …
    var strings = …
    var items = …

    View Slide

  52. With type inference
    var count = …
    var average = …
    var strings = …
    Map> items = …

    View Slide

  53. Types on right!
    var count = …
    var average = …
    var strings = …
    var items: Map> = …

    View Slide

  54. Where is the type in XXI Century?
    Left Right

    View Slide

  55. Where is the type in XXI Century?
    Left Right

    View Slide

  56. If Java was designed in 201x
    It would have been designed for type
    inference with types on the right

    View Slide

  57. Type safety

    View Slide

  58. How type-safe is that?
    int process(List input) { … }

    View Slide

  59. How type-safe is that?
    int process(List input) { … }

    View Slide

  60. How type-safe is that?
    int process(List input) { … }
    process(null);
    Oops!

    View Slide

  61. Null in Kotlin
    fun process(input: List): Int { … }
    process(null)

    View Slide

  62. Null in Kotlin is forbidden by default
    fun process(input: List): Int { … }
    process(null)

    View Slide

  63. Opt-in to use nulls
    fun process(input: List?): Int { … }
    process(null)

    View Slide

  64. fun process(input: List?): Int {

    return input.size
    }
    process(null)

    View Slide

  65. fun process(input: List?): Int {

    return input.size
    }
    process(null)

    View Slide

  66. fun process(input: List?): Int {

    return input?.size
    }
    process(null)

    View Slide

  67. fun process(input: List?): Int {

    return input?.size
    }
    process(null)

    View Slide

  68. fun process(input: List?): Int? {

    return input?.size
    }
    process(null)

    View Slide

  69. If Java was designed in 201x
    It would have had null-safety

    View Slide

  70. How type-safe is that?
    int process(List input) { … }

    View Slide

  71. How type-safe is that?
    int process(List input) {
    input.removeIf(data -> !data.isGood());
    return input.size();
    }

    View Slide

  72. How type-safe is that?
    int process(List input) {
    input.removeIf(data -> !data.isGood());
    return input.size();
    }
    Oops!

    View Slide

  73. Collections in Kotlin
    fun process(input: List): Int {
    input.removeIf { data -> !data.isGood() }
    return input.size
    }

    View Slide

  74. Collections in Kotlin are read-only
    fun process(input: List): Int {
    input.removeIf { data -> !data.isGood() }
    return input.size
    }

    View Slide

  75. Opt-in to mutability
    fun process(input: MutableList): Int {
    input.removeIf { data -> !data.isGood() }
    return input.size
    }

    View Slide

  76. How type-safe is that?
    int process(List input) {

    int size = input.size();

    return size;
    }

    View Slide

  77. How type-safe is that?
    int process(List input) {

    final int size = input.size();

    return size;
    }

    View Slide

  78. Kotlin: Make val not var
    fun process(input: List): Int {

    val size = input.size

    return size
    }

    View Slide

  79. Choice of Defaults

    View Slide

  80. Defaults
    Null/Not-null

    View Slide

  81. Defaults
    Java
    Null/Not-null Nullable

    View Slide

  82. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable

    View Slide

  83. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable

    View Slide

  84. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable

    View Slide

  85. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable

    View Slide

  86. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable
    Open/Final

    View Slide

  87. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable
    Open/Final Open

    View Slide

  88. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable
    Open/Final Open Final

    View Slide

  89. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable
    Open/Final Open Final
    Private/Public

    View Slide

  90. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable
    Open/Final Open Final
    Private/Public Pkg private

    View Slide

  91. Defaults
    Java Real life
    Null/Not-null Nullable Non-nullable
    Mutable/Immutable Mutable Immutable
    Open/Final Open Final
    Private/Public Pkg private Public

    View Slide

  92. If Java was designed in 201x
    It would have very different defaults

    View Slide

  93. Syntax

    View Slide

  94. Semicolon
    foo(); bar();

    View Slide

  95. Semicolon
    foo();
    bar();

    View Slide

  96. Semicolon
    foo();
    bar();

    View Slide

  97. Semicolon
    foo()
    bar()

    View Slide

  98. Where is the semicolon in XXI Century?
    Mandatory None/Optional

    View Slide

  99. Where is the semicolon in XXI Century?
    Mandatory None/Optional

    View Slide

  100. If Java was designed in 201x
    It would have optional semicolon

    View Slide

  101. What if Java was designed in 201x?
    ØNo checked exceptions
    ØDesigned for type inference
    ØFunctional by design
    ØNo exposed primitives
    ØNull safety
    ØWell-founded defaults
    ØOptional semicolon

    View Slide

  102. Syntactic sugar

    View Slide

  103. Properties in Java
    public class Person {
    private String firstName;
    private String lastName;
    public String getFirstName() {
    return firstName;
    }
    public void setFirstName(String firstName) {
    this.firstName = firstName;
    }

    View Slide

  104. Properties in Kotlin
    class Person {
    var firstName: String? = null
    var lastName: String? = null
    }

    View Slide

  105. Primary constructor in Java
    public class Person {
    private String firstName;
    private String lastName;
    public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    }

    View Slide

  106. Primary constructor in Kotlin
    class Person(
    var firstName: String?,
    var lastName: String?
    )

    View Slide

  107. Primary constructor + null-safety = ❤
    class Person(
    var firstName: String,
    var lastName: String
    )

    View Slide

  108. Equals/hashCode/etc in Java
    public class Person {
    private String firstName;
    private String lastName;
    @Override
    public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Person)) return false;
    Person person = (Person) o;
    return Objects.equals(firstName, person.firstName) &&
    Objects.equals(lastName, person.lastName);
    }

    View Slide

  109. Data class in Kotlin
    data class Person(
    var firstName: String,
    var lastName: String
    )

    View Slide

  110. String concatenation in Java
    public class Person {
    @Override
    public String toString() {
    return firstName + " " + lastName;
    }

    View Slide

  111. String format in Java
    public class Person {
    @Override
    public String toString() {
    return String.format("%s %s", firstName, lastName);
    }

    View Slide

  112. String interpolation in Kotlin
    class Person(…) {
    override fun toString(): String {
    return "$firstName $lastName";
    }

    View Slide

  113. String interpolation in Kotlin
    class Person(…) {
    override fun toString(): String =
    "$firstName $lastName"

    View Slide

  114. Singleton in Java
    public class Singleton {
    public static final INSTANCE = new Singleton();
    private Singleton() {}

    }

    View Slide

  115. Singleton in Kotlin
    object Singleton {

    }

    View Slide

  116. Why Kotlin?

    View Slide

  117. Kotlin was designed as a modernized Java

    View Slide

  118. Kotlin
    ØInteroperability with JVM ecosystem
    ØEasy to learn for Java developers by design
    ØExtensible, DSL-friendly
    ØPragmatic
    ØFun to work with

    View Slide

  119. Resources
    Økotlinlang.org
    Øtry.kotlinlang.org
    Ødiscuss.kotlinlang.org
    Øslack.kotlinlang.org

    View Slide

  120. Thank you
    Any questions?
    Slides are available at https://speakerdeck.com/elizarov
    email [email protected]
    Roman Elizarov
    @relizarov

    View Slide