Kotlin Primitive Types and Reference Types
Primitive Types and Reference Types
Java distinguishes between primitive types and reference types, but in Kotlin they are used without such a visible distinction, as with Int, Long, and Boolean.
Then does Kotlin not have separate primitive and reference types? Considering that null exists, we can make two guesses.
- Since a type can contain
null, it will always be declared as a reference type. - If a type allows
null, it will be a reference type; if it does not allownull, it will be a primitive type.
The correct answer here is the latter. If a type allows null, it is declared as a reference type, and if it does not allow null, it is declared as a primitive type.
In other words, on the JVM, Kotlin types are converted into primitive or reference types depending on how the data type was declared in Kotlin.
Let’s look at an example.
Kotlin
fun main() {
val n1 = 10
val n2: Int = 20
val n3: Int? = 30
println("n1=$n1, n2=$n2, n3=$n3")
}
The code above declares variables in the following three cases.
Intis not explicitly declared.- Declared as
Int, which does not allow null. - Declared as
Int?, which allows null.
If we convert this to bytecode and inspect part of it, it looks like the following.
Bytecode
L0
LINENUMBER 4 L0
BIPUSH 10
ISTORE 0
L1
LINENUMBER 5 L1
BIPUSH 20
ISTORE 1
L2
LINENUMBER 6 L2
BIPUSH 30
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
ASTORE 2
In L0 and L1, 10 and 20 are assigned respectively. In L2, 30 is assigned and Integer.valueOf(int i) is called, returning a reference type.
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
Now let’s decompile it into Java and look at the code more easily.
Java
public final class DataTypePrimitiveReferenceTutorialKt {
public static final void main() {
int n1 = 10;
int n2 = 20;
Integer n3 = 30;
String var3 = "n1=" + n1 + ", n2=" + n2 + ", n3=" + n3;
boolean var4 = false;
System.out.println(var3);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
You can see that the types were transformed in Java as shown in the following table.
| Data type declaration | Kotlin type | Java type |
|---|---|---|
var n1 = 10 |
Int |
int |
var n2: Int = 20 |
Int |
int |
var n3: Int? = 30 |
Int |
Integer |
Notes on Kotlin Types
In Kotlin, it is probably more accurate to say that the distinction between primitive and reference types is hidden rather than absent. In general, using types without distinguishing them is usually not a major problem, but there can be issues when calling Java libraries that use reflection from Kotlin.
The code below is extracted from an actual Java library, spring-retry. It compares the types of a parameter and an argument.
if (!parameterTypes[i].isAssignableFrom(argument.getClass())) {
return false;
}
If the parameter is int and the argument is Integer, false is returned, which can cause behavior the user did not intend.