Slide 1

Slide 1 text

Kotlin Types: Exposed

Slide 2

Slide 2 text

Agenda …types…

Slide 3

Slide 3 text

Agenda • Basic types • Nullable types • Collection types &

Slide 4

Slide 4 text

fun foo(): Int = 1 fun bar(): Int? = 1 Types under the hood

Slide 5

Slide 5 text

Under the hood?

Slide 6

Slide 6 text

Kotlin Bytecode

Slide 7

Slide 7 text

Kotlin Bytecode

Slide 8

Slide 8 text

Kotlin Bytecode

Slide 9

Slide 9 text

public static final int foo() { return 1; } @Nullable public static final Integer bar() { return Integer.valueOf(1); } Decompiled Java code

Slide 10

Slide 10 text

fun foo(): Int = 1 public static final int foo() { return 1; } Correspondence between Kotlin and Java types Kotlin code: Decompiled Java code:

Slide 11

Slide 11 text

public static final Integer bar() { return 1; } Correspondence between Kotlin and Java types Kotlin code: Decompiled Java code: fun bar(): Int? = 1

Slide 12

Slide 12 text

Kotlin Java Int int Int? java.lang.Integer Correspondence between Kotlin and Java types

Slide 13

Slide 13 text

Basic types

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Generic arguments Kotlin Java List List

Slide 16

Slide 16 text

Arrays Kotlin Java Array Integer[]

Slide 17

Slide 17 text

Arrays of primitive types Kotlin Java Array Integer[] IntArray int[]

Slide 18

Slide 18 text

String Kotlin Java kotlin.String java.lang.String

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Any Kotlin Java Any java.lang.Object

Slide 21

Slide 21 text

User Any Any

Slide 22

Slide 22 text

Any Int Any User

Slide 23

Slide 23 text

Boxing under the hood log(2017) fun log(any: Any) { println("Value: $any") } the value is autoboxed

Slide 24

Slide 24 text

No boxing now log(2017) fun log(any: Any) { println("Value: $any") } fun log(i: Int) { println("Value: $i") }

Slide 25

Slide 25 text

Unit vs Nothing vs void ?

Slide 26

Slide 26 text

Unit instead of void No meaningful value is returned fun f(): Unit { /*...*/ } Two equivalent syntactic forms: fun f() { /*...*/ }

Slide 27

Slide 27 text

Unit Kotlin Java Unit void

Slide 28

Slide 28 text

Nothing is different to Unit/void fun fail(message: String): Nothing {
 throw IllegalStateException(message)
 } It means “this function never returns”

Slide 29

Slide 29 text

“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”

Slide 30

Slide 30 text

Any & Nothing types Int Any Unit Nothing

Slide 31

Slide 31 text

Expressions of Nothing type inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason") val answer: Int = if (timeHasPassed()) { 42 } else { TODO("Needs to be done") }

Slide 32

Slide 32 text

fun greetPerson(person: Person) { val name: String = person.name ?: throw IllegalArgumentException("Name is unspecified") println("Hello, $name!") } Expressions of Nothing type

Slide 33

Slide 33 text

fun greetPerson(person: Person) { val name = person.name ?: fail("Name is unspecified") println("Hello, $name!") } Expressions of Nothing type

Slide 34

Slide 34 text

fun greetPerson(person: Person) { val name = person.name ?: return println("Hello, $name!") } Expressions of Nothing type

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Nothing Kotlin Java Nothing void because we don’t have Nothing at JVM

Slide 41

Slide 41 text

Any & Nothing types Int Any User Nothing

Slide 42

Slide 42 text

Type hierarchy Any Nothing User Any? Nothing? Int? User? Int

Slide 43

Slide 43 text

Type hierarchy Any Nothing User Any? Nothing? Int? User? Int ?

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Type of null var user: Nothing? = null user = User("svtk") val users: List = mutableListOf(null) users.add(User("svtk"))

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

Nullable types Java &

Slide 48

Slide 48 text

Nullable Types Under the Hood @Nullable, @NotNull annotations

Slide 49

Slide 49 text

@Nullable @NotNull Type Type? Type Type Nullability annotations

Slide 50

Slide 50 text

Nullability & Java Type behaves like regular Java type ?

Slide 51

Slide 51 text

Platform type Type Type! type of “unknown” nullability notation, not syntax type that came from Java

Slide 52

Slide 52 text

A bit of history…

Slide 53

Slide 53 text

The safest approach would be… Type Type? We tried, but it didn’t work well

Slide 54

Slide 54 text

Type? then the code looks like Type And it doesn’t really work with generics !! !! !! !! !! !! !! !! !! !! !! !! If

Slide 55

Slide 55 text

Platform type Type Type! type of “unknown” nullability type that came from Java

Slide 56

Slide 56 text

Pick two • Null-safety • Convenience • Java Interop

Slide 57

Slide 57 text

Pick two • Null-safety • Convenience • Java Interop Thanks to Dr. Ross Tate of Platform types

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

Using Java from Kotlin val session = Session()
 val description = session.description
 println(description.length) NullPointerException! public class Session {
 public String getDescription() {
 return null;
 }
 }

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

Type @NotNull @Nullable Type Annotate your Java types

Slide 63

Slide 63 text

Different annotations are supported @Nullable @NotNull JetBrains @Nullable @NonNull Android @Nullable @CheckForNull JSR-305 @Nullable @CheckForNull FindBugs @NonNull Lombok ...

Slide 64

Slide 64 text

Using Java from Kotlin public class Session { @Nullable String getDescription() { return null; } } val session = Session() val description = session.description println(description.length) compiler error

Slide 65

Slide 65 text

Type @NotNull @Nullable Type Annotate your Java types - You can specify @NotNull as default, and annotate only @Nullable types - All of them???

Slide 66

Slide 66 text

Non-null by default (JSR-305) @ParametersAreNonnullByDefault @MyNonnullByDefault

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

@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

Slide 69

Slide 69 text

Make it an error compileKotlin { kotlinOptions { freeCompilerArgs += "-Xjsr305=strict" } } build.gradle

Slide 70

Slide 70 text

@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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

Specify types explicitly val session = Session() val description: String? = session.description println(description?.length) public class Session {
 public String getDescription() {
 return null;
 }
 } ✓

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

Intrinsic checks val session = Session() val description: String = session.description println(description)

Slide 75

Slide 75 text

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");

Slide 76

Slide 76 text

public fun foo(s: String) { } Intrinsic checks Intrinsics.checkParameterIsNotNull(s, "s");

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

Nullable platform types: summary Good compromise between safety and convenience

Slide 79

Slide 79 text

Collections

Slide 80

Slide 80 text

List & MutableList kotlin.List kotlin.MutableList • Two interfaces declared in kotlin package • MutableList extends List

Slide 81

Slide 81 text

Read-only immutable (1, 2, 3) • Read-only interface just lacks mutating methods • The actual list can be changed by another reference list mutableList

Slide 82

Slide 82 text

val mutableList = mutableListOf(1, 2, 3) val list: List = 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

Slide 83

Slide 83 text

Under the hood fun getNames(): List
 fun getNames(): MutableList 
 java.util.List getNames(); Both functions are compiled to:

Slide 84

Slide 84 text

Kotlin uses java.util.ArrayList under the hood kotlin.MutableList java.util.ArrayList kotlin.List

Slide 85

Slide 85 text

Platform type for Java collection collection type of “unknown” mutability List (Mutable)List notation, not syntax type that came from Java

Slide 86

Slide 86 text

Read-only interfaces improve API object Shop { private val customers = mutableListOf() fun getCustomers(): List = customers } val customers = Shop.getCustomers() customers.add() you can’t shoot yourself in the foot any longer

Slide 87

Slide 87 text

Platform types: summary Good compromise between safety and convenience

Slide 88

Slide 88 text

Variance

Slide 89

Slide 89 text

Java wildcards public interface Stream {
 Stream map( Function mapper);
 }

Slide 90

Slide 90 text

interface Function1 {
 operator fun invoke(p: P): R
 } (Animal) -> Int (Cat) -> Any Animal Cat Int Any in/out on the declaration-site

Slide 91

Slide 91 text

Just (T) -> R on the call-site inline fun Iterable.map(
 transform: (T) -> R): List Function1

Slide 92

Slide 92 text

List & MutableList MutableList MutableList String Any ✗ List List

Slide 93

Slide 93 text

Copyright © 2017 https://github.com/JetBrains/kotlin-workshop