Kotlin Types: Exposed

C6997ce411091d4a51ea3caa2109c0b0?s=47 Svetlana Isakova
November 03, 2017
290

Kotlin Types: Exposed

C6997ce411091d4a51ea3caa2109c0b0?s=128

Svetlana Isakova

November 03, 2017
Tweet

Transcript

  1. Kotlin Types: Exposed Svetlana Isakova @sveta_isakova

  2. Agenda …types…

  3. None
  4. Agenda • Basic types • Nullable types • Collection types

    &
  5. fun foo(): Int = 1 fun bar(): Int? = 1

    Types under the hood
  6. Under the hood?

  7. Kotlin Bytecode

  8. Kotlin Bytecode

  9. Kotlin Bytecode

  10. public static final int foo() { return 1; } @Nullable

    public static final Integer bar() { return Integer.valueOf(1); } Decompiled Java code
  11. fun foo(): Int = 1 public static final int foo()

    { return 1; } Correspondence between Kotlin and Java types Kotlin code: Decompiled Java code:
  12. public static final Integer foo() { return 1; } Correspondence

    between Kotlin and Java types Kotlin code: Decompiled Java code: fun bar(): Int? = 1
  13. Kotlin Java Int int Int? java.lang.Integer Correspondence between Kotlin and

    Java types
  14. Basic types

  15. Primitive & wrapper types Kotlin Java Int int Double double

    Boolean boolean Kotlin Java Int? java.lang.Integer Double? java.lang.Double Boolean? java.lang.Boolean
  16. Generic arguments Kotlin Java List<Int> List<Integer>

  17. Arrays Kotlin Java Array<Int> Integer[]

  18. Arrays of primitive types Kotlin Java Array<Int> Integer[] IntArray int[]

  19. String Kotlin Java kotlin.String java.lang.String

  20. "one.two.".replace(".".toRegex(), "*") kotlin.String hides some confusing methods "one.two.".replaceAll(".", "*") ********

    "one.two.".replace(".", "*") one*two*
  21. Any Kotlin Java Any java.lang.Object

  22. User Any Any

  23. Any Int Any User

  24. Boxing under the hood log(2017) fun log(any: Any) { println("Value:

    $any") } the value is autoboxed
  25. No boxing now log(2017) fun log(any: Any) { println("Value: $any")

    } fun log(i: Int) { println("Value: $i") }
  26. Unit vs Nothing vs void ?

  27. Unit instead of void No meaningful value is returned fun

    f(): Unit { /*...*/ } Two equivalent syntactic forms: fun f() { /*...*/ }
  28. Unit Kotlin Java Unit void

  29. Nothing is different to Unit/void fun fail(message: String): Nothing {


    throw IllegalStateException(message)
 } It means “this function never returns”
  30. “a type that allows only one value and thus can

    hold no information” Unit Nothing “a type that has no values” “the function completes successfully” “the function never completes”
  31. Any & Nothing types Int Any Unit Nothing

  32. val answer = if (timeHasPassed()) { 42 } else {

    fail("Not ready") } fun fail(message: String) {
 throw IllegalStateException(message)
 } Let’s say, fail function returns Unit Int Unit Any : Unit
  33. val answer: Any = if (timeHasPassed()) { 42 } else

    { fail("Not ready") } fun fail(message: String) {
 throw IllegalStateException(message)
 } Int Any Unit Let’s say, fail function returns Unit
  34. val answer = if (timeHasPassed()) { 42 } else {

    fail("Not ready") } fun fail(message: String): Nothing {
 throw IllegalStateException(message)
 } Now, fail returns Nothing
  35. val answer = if (timeHasPassed()) { 42 } else {

    fail("Not ready") } fun fail(message: String): Nothing {
 throw IllegalStateException(message)
 } Int Nothing Now, fail returns Nothing
  36. val answer: Int = if (timeHasPassed()) { 42 } else

    { fail("Not ready") } fun fail(message: String): Nothing {
 throw IllegalStateException(message)
 } Nothing Int Now, fail returns Nothing
  37. Nothing Kotlin Java Nothing void because we don’t have Nothing

    at JVM
  38. Any & Nothing types Int Any User Nothing

  39. Type hierarchy Any Nothing User Any? Nothing? Int? User? Int

  40. Type hierarchy Any Nothing User Any? Nothing? Int? User? Int

    ?
  41. Type of null var user = null user = User("svtk")

    val users = mutableListOf(null) users.add(User("svtk")) Error: Type mismatch: inferred type is User but Nothing? was expected Error: Type mismatch: inferred type is User but Nothing? was expected
  42. Type of null var user: Nothing? = null user =

    User("svtk") val users: List<Nothing?> = mutableListOf(null) users.add(User("svtk"))
  43. Specify types explicitly var user: User? = null user =

    User("svtk") val users: List<User?> = mutableListOf(null) users.add(User("svtk")) ✓ ✓
  44. Nullable types Java &

  45. Nullable Types Under the Hood @Nullable, @NotNull annotations

  46. @Nullable @NotNull Type Type? Type Type Nullability annotations

  47. Nullability & Java Type behaves like regular Java type ?

  48. Platform type Type Type! type of “unknown” nullability notation, not

    syntax type that came from Java
  49. A bit of history…

  50. The safest approach would be… Type Type? We tried, but

    it didn’t work well
  51. Type? then the code looks like Type And it doesn’t

    really work with generics !! !! !! !! !! !! !! !! !! !! !! !! If
  52. Platform type Type Type! type of “unknown” nullability type that

    came from Java
  53. Pick two • Null-safety • Convenience • Java Interop

  54. Pick two • Null-safety • Convenience • Java Interop Thanks

    to Dr. Ross Tate of Platform types
  55. Platform type in error message public class Session {
 public

    String getDescription()
 } val session = Session()
 val description: Boolean = session.description Compiler error: Type mismatch: inferred type is String! but Boolean was expected
  56. Using Java from Kotlin val session = Session()
 val description

    = session.description
 println(description.length) NullPointerException! public class Session {
 public String getDescription() {
 return null;
 }
 }
  57. How to still prevent NPEs? • Annotate your Java types

    • Specify types explicitly
  58. How to still prevent NPEs? • Annotate your Java types

    • Specify types explicitly
  59. Type @NotNull @Nullable Type Annotate your Java types

  60. Different annotations are supported @Nullable @NotNull JetBrains @Nullable @NonNull Android

    @Nullable @CheckForNull JSR-305 @Nullable @CheckForNull FindBugs @NonNull Lombok ...
  61. Using Java from Kotlin public class Session { @Nullable String

    getDescription() { return null; } } val session = Session() val description = session.description println(description.length) compiler error
  62. Type @NotNull @Nullable Type Annotate your Java types - You

    can specify @NotNull as default, and annotate only @Nullable types - All of them???
  63. Non-null by default (JSR-305) @ParametersAreNonnullByDefault @MyNonnullByDefault

  64. @MyNonnullApi @javax.annotation.Nonnull @TypeQualifierDefault(ElementType.PARAMETER, ...) annotation class MyNonnullByDefault @MyNonnullByDefault package mypackage;

    package-info.java
  65. @MyNonnullByDefault public class Session { public void setDescription(String description) {

    this.description = description; } } @NonNull by default val session = Session() session.setDescription(null) Warning: Expected type doesn’t accept nulls in Java, but the value may be null in Kotlin
  66. Make it an error compileKotlin { kotlinOptions { freeCompilerArgs +=

    "-Xjsr305=strict" } } build.gradle
  67. @MyNonnullByDefault public class Session { public void setDescription(String description) {

    this.description = description; } } @NonNull by default val session = Session() session.setDescription(null) Error: Null can not be a value of a non-null type String
  68. How to still prevent NPEs? • Annotate your Java types

    • Specify types explicitly
  69. Specify types explicitly val session = Session() val description: String?

    = session.description println(description?.length) public class Session {
 public String getDescription() {
 return null;
 }
 } ✓
  70. IllegalStateException: session.description must not be null val session = Session()

    val description: String = session.description public class Session {
 public String getDescription() {
 return null;
 }
 } Specify types explicitly
  71. Intrinsic checks val session = Session() val description: String =

    session.description println(description)
  72. val session = Session() val description: String = session.description println(description)

    Intrinsic checks is generated by the compiler throws an exception if session.description is null Intrinsics.checkExpressionValueIsNotNull( description, "session.description");
  73. public fun foo(s: String) { } Intrinsic checks Intrinsics.checkParameterIsNotNull(s, "s");

  74. How to still prevent NPEs? • Annotate your Java types

    • Specify types explicitly
  75. Nullable platform types: summary Good compromise between safety and convenience

  76. Collections

  77. List & MutableList kotlin.List kotlin.MutableList • Two interfaces declared in

    kotlin package • MutableList extends List
  78. Read-only immutable (1, 2, 3) • Read-only interface just lacks

    mutating methods • The actual list can be changed by another reference list mutableList
  79. val mutableList = mutableListOf(1, 2, 3) val list: List<Int> =

    mutableList println(list) // [1, 2, 3] (1, 2, 3) list mutableList (1, 2, 3, 4) mutableList.add(4) println(list) // [1, 2, 3, 4] Read-only immutable
  80. Under the hood fun getNames(): List<String>
 fun getNames(): MutableList<String> 


    java.util.List<String> getNames(); Both functions are compiled to:
  81. Kotlin uses java.util.ArrayList under the hood kotlin.MutableList java.util.ArrayList kotlin.List

  82. Platform type for Java collection collection type of “unknown” mutability

    List<String> (Mutable)List<String!> notation, not syntax type that came from Java
  83. Read-only interfaces improve API object Shop { private val customers

    = mutableListOf<Customer>() fun getCustomers(): List<Customer> = customers } val customers = Shop.getCustomers() customers.add() you can’t shoot yourself in the foot any longer
  84. Platform types: summary Good compromise between safety and convenience

  85. Summary fun myFail(): Nothing = throw MyException() Preventing NPE: •

    annotations • explicit types @Nullable @MyNonnullByDefault Read-only immutable Nothing primitives under the hood boxing: Int Any
  86. Have a nice Kotlin! #kotlinconf17