Search code examples
kotlinreflectioncollectionsjvmmutable

Mutable and immutable collection classes are the same kotlin


When using reflection to investigate collection classes, mutable and immutable classes for the same type are referentially equal.

Why is this the case?

    @Test
    fun demonstrate_mutableAndImmutableClassesAreTheSame() {
        println("(MutableIterable::class === Iterable::class) = ${(MutableIterable::class === Iterable::class)}")
        println("(MutableCollection::class === Collection::class) = ${(MutableCollection::class === Collection::class)}")
        println("(MutableList::class === List::class) = ${(MutableList::class === List::class)}")
        println("(MutableSet::class === Set::class) = ${(MutableSet::class === Set::class)}")
        println("(MutableMap::class === Map::class) = ${(MutableMap::class === Map::class)}")
        println("(MutableMap.MutableEntry::class === Map.Entry::class) = ${(MutableMap.MutableEntry::class === Map.Entry::class)}")
    }

prints

(Iterable::class === MutableIterable::class) = true
(Collection::class === MutableCollection::class) = true
(List::class === MutableList::class) = true
(Set::class === MutableSet::class) = true


Solution

  • Collection and MutableCollection are mapped to the same java.util.Collection class (mapped-types), so from POV of JVM (after compilation at runtime) that they are the same.

    If you decompile the code you've written, you'll get this (I've decompiled it using Kotlin Bytecode generated by Intellij):

    Kotlin:

    fun demonstrate_mutableAndImmutableClassesAreTheSame() {
        println("(MutableCollection::class === Collection::class) = ${(MutableCollection::class === Collection::class)}")
    }
    

    Java:

    import kotlin.jvm.internal.Reflection;
    
    // class declaration
    public static final void demonstrate_mutableAndImmutableClassesAreTheSame() {
        String var0 = "(MutableCollection::class === Collection::class) = " + (Reflection.getOrCreateKotlinClass(Collection.class) == Reflection.getOrCreateKotlinClass(Collection.class));
        boolean var1 = false;
        System.out.println(var0);
    }
    

    References: