# Why can kotlin.collections.List be passed to method that accepts java.util.List?

**URL:** <https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955>\
**Category:** Language Design\
**Created:** [January 13, 2024, 7:02pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955 "2024-01-13T19:02:39Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![marcoeckstein](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@marcoeckstein](https://discuss.kotlinlang.org/u/marcoeckstein)\
**Post date:** [January 13, 2024, 7:02pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/1 "2024-01-13T19:02:39Z")

</div>

A `kotlin.collections.List` is statically read-only (i.e. defines no modifying methods) but may be mutable at runtime. On the JVM:

```kotlin
val readonlyList: kotlin.collections.List<String> =
    listOf("a", "b", "c") // At runtime: java.util.Arrays$ArrayList (which is a java.util.List)

```

As long as you stay in Kotlin land, `readonlyList` is practically immutable, and when you can be confident that a non-malicious function `f(list: kotlin.collections.List<T>)` will not mutate it when calling `f(readonlyList)`. (A malicious function could of course cast and modify it, but then it could also access private variables via reflection).

A `kotlin.collections.List` cannot be assigned to `java.util.List` or `java.util.ArrayList`, which makes sense given that these are generally mutable:

```kotlin
fun main() {
    val a: java.util.List<String> = mutableList // Compile error: Type mismatch.
    val b: java.util.ArrayList<String> = mutableList // Compile error: Type mismatch.
    modify(readonlyList) // Compile error: Type mismatch.
}

fun <T> modify(list: java.util.List<T>) {
    list.clear()
}

```

What baffles me is the decision to allow `kotlin.collections.List` to be passed to Java methods that accept `java.util.List`, i.e. methods that accept platform types:

```kotlin
val readonlyList: kotlin.collections.List<String> = listOf("a", "b", "c")
java.util.Collections.shuffle(readonlyList) // accepts java.util.List
println(readonlyList) // E.g., can print [a, c, b]

```

This is quite dangerous. I guess the motivation for this is better interoperability. Most Java methods that accept `java.util.List` and that you want to use will probably not modify the parameter. E.g.:

```kotlin
val readonlyList: kotlin.collections.List<String> = listOf("a", "b", "c")
java.util.Collections.unmodifiableList(readonlyList) // accepts java.util.List
println(readonlyList) // Prints [a, b, c]

```

If `kotlin.collections.List` was not accepted, but only the correct `kotlin.collections.MutableList`, one would need to write `java.util.Collections.unmodifiableList(readonlyList.toMutableList())`.

I am not sure that benefit of saving us from writing `f(readonlyList as MutableList<String>)` or `f(readonlyList.toMutableList())` is worth the potential of hard-to-find bugs that can arise when a list is modified and passed around, but you and the compiler reason about the code thinking it is read-only.

One could use truly immutable lists, which still do not provide type safety at compile time, but at least at runtime, thus making any bugs easy to find:

```kotlin
val immutableList: kotlinx.collections.immutable.ImmutableList<String> =
    kotlinx.collections.immutable.persistentListOf("a", "b", "c")
java.util.Collections.shuffle(immutableList)
println(immutableList) // throws java.lang.UnsupportedOperationException: Operation is not supported for read-only collection

```

Not only is runtime-only type safety unsatisfying, but `kotlin.collections.List` is already established, so this causes interoperability issues with Kotlin itself. E.g.:

```kotlin
fun processList(list: kotlin.collections.List<String>): kotlin.collections.List<String> =
    list.filter { it == "foo" }

fun main() {
    val immutableList: kotlinx.collections.immutable.ImmutableList<String> =
        kotlinx.collections.immutable.persistentListOf("a", "b", "c")
    java.util.Collections.shuffle(
        processList(immutableList).toImmutableList() // must call .toImmutableList() for runtime type safety
    )
}

```

So, as it is, one must be very careful when passing `kotlin.collections.List` to Java methods. One must either trust that the names do not betray (always clearly indicate modification) or always remember to append `toImmutableList()` to these arguments, potentially with a performance hit.

I wonder if it would be good if there would be a “strict mode” where in general only `kotlin.collections.MutableList` is accepted for Java methods. To improve interoperability, there could also be a hybrid approach:

- Passing a `kotlin.collections.List` could still be allowed for a set of widely-used Java methods that promise to not modify the list.
- Or in the current mode - where passing `kotlin.collections.List` is generally allowed - forbidding it for a set of Java methods that have a strong indicator of modifying it: If the method accepts only a list and its Javadoc documents a `java.lang.UnsupportedOperationException`. (Still an unsafe approach in general of course - just a mitigation.)

What do you think? Would such a compiler option makes sense? Is it considered best practice nowadays to use `kotlinx.collections.immutable.ImmutableList` wherever possible (and still have no compile time safety)? Are there static checkers already that can provide the desired safety?

For simplicity, I have spoken only about lists, but the same issues apply to other collection types as well.

---

<div class="post-metadata">

**Author:** ![brunojcm](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/brunojcm/32/5116_2.png) [@brunojcm](https://discuss.kotlinlang.org/u/brunojcm)\
**Post date:** [January 20, 2024, 8:12am UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/2 "2024-01-20T08:12:35Z")

</div>

> [@marcoeckstein](#):
>
> What baffles me is the decision to allow `kotlin.collections.List` to be passed to Java methods that accept `java.util.List`

That is not entirely true, you cannot pass a `kotlin.collections.List` into a Kotlin method taking `java.util.List`, just to a pure java class taking a `java.util.List`.

Consider the code below:

```auto
val kotlinList: kotlin.collections.List<String> = listOf("a", "b", "c")

val javaList: java.util.List<String> = kotlinList // Type mismatch.

fun takesJavaList(l: java.util.List<String>) {
    TODO()
}

takesJavaList(kotlinList) // Type mismatch.

java.util.Collections.shuffle(kotlinList) // warning: Call of Java mutator 'shuffle' on immutable Kotlin collection 'kotlinList'

```

There i no better option, really, the pain of not letting any kotlin lists be used in Java would certainly overweight the extra safety by making `kotlin.collections.List` and `java.util.List` totally incompatible.

---

<div class="post-metadata">

**Author:** ![clovisai](https://avatars.discourse-cdn.com/v4/letter/c/a9adbd/32.png) [@clovisai](https://discuss.kotlinlang.org/u/clovisai)\
**Post date:** [February 11, 2024, 7:02pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/3 "2024-02-11T19:02:35Z")

</div>

Here’s another idea: have a compiler flag to insert `Collections.unmodifiableList` anytime a Kotlin read-only `List` is passed to a Java function that accepts a `java.util.List`.

This way, you get the safety you mentioned, with behavior consistent with the Java standard library, without needing to write more code.

---

<div class="post-metadata">

**Author:** ![marcoeckstein](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@marcoeckstein](https://discuss.kotlinlang.org/u/marcoeckstein)\
**Post date:** [February 29, 2024, 10:08pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/4 "2024-02-29T22:08:29Z")

</div>

> [@brunojcm](#):
>
> That is not entirely true, you cannot pass a `kotlin.collections.List` into a Kotlin method taking `java.util.List`, just to a pure java class taking a `java.util.List`.

Yes, that’s why I was referring to Java methods specifically.

> [@brunojcm](#):
>
> `java.util.Collections.shuffle(kotlinList) // warning: Call of Java mutator 'shuffle' on immutable Kotlin collection 'kotlinList'`

Interesting. For some strange reason I had not seen that warning before. That is essentially the second hybrid approach that I had suggested - forbidding/discouraging passing a ` kotlin.collections.List` to a Java method that is know to mutate. Do you know how the static analysis knows this?

---

<div class="post-metadata">

**Author:** ![marcoeckstein](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@marcoeckstein](https://discuss.kotlinlang.org/u/marcoeckstein)\
**Post date:** [February 29, 2024, 10:10pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/5 "2024-02-29T22:10:01Z")

</div>

> [@clovisai](#):
>
> have a compiler flag to insert `Collections.unmodifiableList` anytime a Kotlin read-only `List` is passed to a Java function that accepts a `java.util.List`.

That would be nice.

---

<div class="post-metadata">

**Author:** ![marcoeckstein](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@marcoeckstein](https://discuss.kotlinlang.org/u/marcoeckstein)\
**Post date:** [February 29, 2024, 10:18pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/6 "2024-02-29T22:18:11Z")

</div>

Reading my post again, I see that I have made a mistake (probably a copy/paste mistake), but I cannot edit it anymore:

> [@marcoeckstein](#):
>
> ```auto
> fun main() {
> val a: java.util.List<String> = mutableList // Compile error: Type mismatch.
> val b: java.util.ArrayList<String> = mutableList // Compile error: Type mismatch.
> modify(readonlyList) // Compile error: Type mismatch.
> }
> 
> fun <T> modify(list: java.util.List<T>) {
> list.clear()
> }
> 
> ```

Instead of `mutableList`, it should have been `readonlyList`, even though indeed the same compile errors would pop up when using a `kotlin.collections.MutableList`.

---

<div class="post-metadata">

**Author:** ![clovisai](https://avatars.discourse-cdn.com/v4/letter/c/a9adbd/32.png) [@clovisai](https://discuss.kotlinlang.org/u/clovisai)\
**Post date:** [March 1, 2024, 9:39am UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/7 "2024-03-01T09:39:44Z")

</div>

I created [an issue](https://youtrack.jetbrains.com/issue/KT-66257/Compiler-option-for-protected-passing-of-collections-to-Java) for it.

---

<div class="post-metadata">

**Author:** ![brunojcm](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/brunojcm/32/5116_2.png) [@brunojcm](https://discuss.kotlinlang.org/u/brunojcm)\
**Post date:** [March 6, 2024, 2:37pm UTC](https://discuss.kotlinlang.org/t/why-can-kotlin-collections-list-be-passed-to-method-that-accepts-java-util-list/27955/8 "2024-03-06T14:37:49Z")

</div>

> [@marcoeckstein](#):
>
> Interesting. For some strange reason I had not seen that warning before. That is essentially the second hybrid approach that I had suggested - forbidding/discouraging passing a ` kotlin.collections.List` to a Java method that is know to mutate. Do you know how the static analysis knows this?

I’m no expert in the Kotlin compiler, but I’d say it’s probably an IDE warning or a list of hardcoded methods somewhere.
