How does the following code compiles without any errors?
var linkedList: MutableList<Int> = java.util.LinkedList()
when java.util.LinkedList
class contract clearly doesn't implement the Kotlin interface MutableList
?
In your example, the compiler isn't inferring anything. You are telling the compiler that your linkedList
variable is to be treated as a MutableList<Int>
. The compiler allows this because java.util.LinkedList
is an implementation of the Java List
interface, which maps to the Kotlin List
or MutableList
interfaces.
Per the documentation provided by Tenfour04, a List<T>
in java is a mapped type which maps to the Kotlin List<T>
or MutableList<T>
- the choice is up to you.
Notice that the word type is used here, not class. What you're doing is simply telling the compiler that you want this variable to be treated as a MutableList<Int>
- that's it. This idea is reinforced by this sentence in the docs:
The mapping only matters at compile time, the runtime representation remains unchanged.
So by declaring your variable as mutable or otherwise, you are simply masking the underlying class (java.util.LinkedLink) with a Kotlin mapped type.
We already know that java.util.LinkedList
is mutable by default. So doing either of these
val immutableLinkedList: List<Int> = java.util.LinkedList<Int>()
val mutableLinkedList: MutableList<Int> = java.util.LinkedList<Int>()
Is perfectly valid. In the former case, since you've informed the compiler that immutableLinkedList
is only type List<Int>
(remember - you can only do this because this Kotlin type maps to a parent type of LinkedList
), then you will not be able to add to or remove from it, even though the actual runtime implementation technically allows that.
These mechanisms are in place to help keep type safety and be explicit about what type of structure you're working with. If you are working in Kotlin, it is good to annotate your linkedList as a kotlin type MutableList
, since it is very clear that this list is in fact mutable.
On there other hand, you could conceivably imagine some situation where the implementation of the list actually mattered, so you may choose to drop the type annotation completely and let the compiler treat it as a java.util.LinkedList
.
val myLinkedList = java.util.LinkedList<Int>()