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
@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