※Notes記事では、英語のセッション動画やポッドキャストの内容を(雑に)英語でメモに書き残すことを行っています。 本記事は、あくまで動画を見ながら、参考程度に読んでいただくことを想定しています。これから動画を見る方にとって本記事の内容が少しでもお役に立てば幸いです。(内容において不備、誤字脱字等ありましたらご連絡いただければと思います。)
本記事はKotlin Types: Exposed by Svetlana Isakova (KotlinConf 2017)の記事です。

Agenda
- Basic Types
- Nullable types
- Collection types
How those types interact with Java and what happens when we mix types of Kotlin and Java
fun foo(): Int = 1 fun bar(): Int? = 1
public static final int foo() { return 1; } public static final Integer bar() { return Integer.of(1); }
If you want to know what is going on under the food, you can "show kotlin bytecode" (and also decompile the byte code) in Android Studio
Correspondence between Kotlin and Java types
Kotlin does not have Primitive types in the language, yet Kotlin still has Primitive types in the byte code level by making use of wrapper types and nullable types
Generic arguments
Arrays of primiteve types
If you want to use primitive types of array, then use IntArray in Kotlin:
- IntArray in Kotlin => int[] in Java
String
kotlin.String in Kotlin => java.lang.String in Java
kotlin.String hides some confusing methods:
e.g. replaceAll method
In Java:
"one.two.".replaceAll(".", "*") => *******
In Kotlin:
"one.two.".replace(".", "*") => one*two "one.two.".replace(".".toRegex(), "*") => one*two
Any
Anyin Kotlin =>java.lang.Objectin JavaAnytype is the super type for ALL types, includingIntor anything
Boxing under the hood
log(2017) // the value is autoboxed fun log(any: Any) { println("Value: $any") } fun log(i: Int) { println("Value: $i") }
Unit (Kotlin) vs Nothing (Kotlin) vs void (Java)?
The concept comes from functional programming; from the Type system
- Unit: "a type that allows only one value and thus can hold no information" => The function completes
- Nothing: "a type that has no values" => The function never completes
Unit instead of void
Whenever you use void in Java, you use Unit in Kotlin
Unit
- No meaningful value is returned
- No explicit returned type implies you return
Unitby default - Two equivalent syntactic forms:
fun f() { /*…*/ } fun f(): Unit { /*…*/ }
Under the hood, Unit is still void in the byte code
Nothing is different to Unit/void
Unit and Nothing are two very different types even though in the byte code level both mean void type
Nothingmeans "this function never returns"
Any & Nothing types
Anyis a super type for all the other typesNothingis a subtype for all the other types
e.g. fail function below returns Unit
val answer = if (timeHasPassed()) { 42 } else { fail("Not ready") } fun fail(message: String) { throw IllegalStateException(message) }
- If 42 is returned then the returned type of the expression function is
Int - If fail function is called then the returned type of the expression function is
Unit
=> Kotlin compiler thinks that the expression function returns Any type because the super type of both Int and Unit is Any
Returning Any means the variable answer will be initialized even if it fails, which is not what we expect; we expect it not to be initialized when it fails. => We can use Nothing in this case
Nothing is a subtype for all the other types, so that means the returned type of the expression function is now Int, which is what we expect
Type of null
var user = null // => var user: Nothing? = null user = User("svtk") // Error: Type mismatch val users = mutableListOf(null) // => var users: List<Nothing?> = mutableListOf(null) users.add(User("svtk")) // Error: Type mismatch
Nullable types & Java
Nullable Types Under the Hood => Just annotations
If your returned type is annotated with @Nullable in Java, then in Kotlin, the type will become nullable
How to still prevent NPEs?
- Annotate your Java types
- @Nullable type
- @NotNull type
Non-null by default (JSR-305):
@javax.annotation.Nonnull @TypeQualifierDefault(ElementType.PARAMETER, …) annotation class MyNonnullByDefault
package-info.java:
@MyNonnullByDefault package mypackage;
Then, Kotlin will give you warning when assigning null to values:
@MyNonnullByDefault public class Session { public void setDescription(String description) { this.description = description; } }
Calling Java code from Kotlin:
val session = Session() session.setDescription(null) // => Warning: Expected type doesn't accept nulls in Java …
If you prefer errors in compile time rather than warnings:
build.gradle
compileKotlin {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
}
}
Then, Kotlin will give you errors when assigning null to values:
@MyNonnullByDefault public class Session { public void setDescription(String description) { this.description = description; } }
Calling Java code from Kotlin:
val session = Session() session.setDescription(null) // => Error: Null can not be a value of a non-null type …
build.gradle
- Specify types explicitly
public class Session { public void setDescription(String description) { this.description = description; } }
val session = Session() val description: String? = session.description ✅
Or, the code below gives you IllegalStateException in runtime which notifies you very early what is wrong with your code:
val session = Session() val description: String = session.description // IllegalStateException: session.description must not be null
How it works? - Intrinsic checks
The code below will be generated by compiler:
Intrinsics.checkExpressionValueisNotNull()
Collections
Read-only interfaces improve API
- How read-only collections and mutable collections work in Kotlin
List & MutableList
- Two interfaces declared in
kotlinpackage MutableListextendsList
Read-only DOES NOT mean immutable - Read-only interface just lacks mutating methods
The actual list can be changed by another reference:
val mutableList = mutableListOf(1, 2, 3) val list: List<Int> = mutableList println(list) // [1, 2, 3] mutableList.add(4) println(list) // [1, 2, 3, 4]
In Kotlin, there is a plan to provide the immutable data structure in the standard library, but it is not ready yet
String!= notation, not syntax; platform type, which is a type that comes from Java
Platform types: summary
Good compromise between safety and convenience
Summary
- primitives under the hood, and boxing is possible
- Use
Nothingwhenever possible - Preventing NPE for Java interop: annotations, explicit types
- Read-only does not mean immutable
以上です!