Kotlin listOf の実態はなに

Kotlin における listOf は、以下のように https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/list-of.html

fun <T> listOf(vararg elements: T): List<T>

List (interface) が返ってきます。

利用する分には全く問題がないめちゃくちゃ便利なビルダーですが、ふとしたことをきっかけに Kotlin における listOf() が具体的な型として何を返してるのかなどの仕組みが気になってしまったので軽く調べてみました。
(当初は普通に java.util.ArrayList が返ってくると思ってた。)

環境としては、以下で調べてみたりしてます - Kotlin 1.5.30 (そんなに他のバージョンも違わないはず) - IntelliJ IDEA

listOf -> CollectionsKt.listOf

まずは、おなじみ Kotlin の Plugin で Bytecode に変換したのち Decompile して Java のコードとして見てみます。
( Tools > Kotlin > Show Kotlin Bytecode でみることができます)

val list = listOf<String>("a", "b")
↓
List list = CollectionsKt.listOf(new String[]{"a", "b"});

CollectionsKt#listOf
https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/collections/Collections.kt#L77
にありました

public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()

どうやら vararg に対して asList() を呼び出しているようです。

vararg に対しての asList() -> ArraysKt.asList

こちらも Kotlin の Plugin で Bytecode に変換して Java Decompile してみます。

val list = elements.asList()
↓
List list = ArraysKt.asList(elements);

ArraysKt#asList は IntelliJ から遷移すると以下の実装となっていた。

public actual fun <T> Array<out T>.asList(): List<T> {
    return ArraysUtilJVM.asList(this)
}

(補足)

//
// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt
// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib
//

とあるのでおそらくソースコード自体にはなく? Jetbrains/kotlin では見つからなかった。

ArraysKt.asList -> java.util.Arrays$ArrayList の生成

ArraysUtilJVM.asList(this) の部分は、 https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/jvm/src/kotlin/collections/ArraysUtilJVM.java
にありました

class ArraysUtilJVM {
    static <T> List<T> asList(T[] array) {
        return Arrays.asList(array);
    }
}

Java の return Arrays.asList(array); を呼び出してたのでそれをたどっていくと今自分が開いてる IntelliJ で見ると以下の実装に遷移する

@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

return new ArrayList<>(a); にもあるように ArrayList を返却している。 しかしこの ArrayList は、型の宣言としては java.util.Arrays$ArrayList となるので https://docs.oracle.com/javase/jp/8/docs/api/java/util/ArrayList.html
で宣言されているような java.util.ArrayList ではなく Arrays のインナークラスとして宣言されたものが利用されているので、 以下のような判定などはできず、 List インターフェースとして利用するという形になります (それはそう)

val list = listOf("a", "b", "c")
list is java.util.ArrayList // これは false となる

まとめ