Search code examples
javakotlinlinked-listmapped-typesmutablelist

How is java.util.LinkedList() an instance of MutableList?


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?


Solution

  • 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>()