I tried looking for it but failed, so let me ask: ...
# language-evolution
s
I tried looking for it but failed, so let me ask: Are there any plans for providing language-level support for Java 21's SequencedCollection interface in terms of distinguishing read-only and Mutable interfaces, as it currently is for (MutableList : List), (MutableCollection : Collection), etc? Currently, when working with Kotlin and JVM language level 21 having
list: List<T>
you can call
list.removeFirst()
, or
list.removeLast()
just as if you were calling
MutableList<T>.removeFirst()
, or
MutableList<T>.removeLast()
extensions. Similarly,
addFirst/Last
methods are also visible To me this sounds problematic for 2 main reasons: • one might confuse the type being worked on - you wouldn't normally see mutating methods in autocomplete for objects exposed via read-only interfaces, so I can imagine someone mutating a collection by accident (especially by confusing with a well-known removeFirst/Last extension with the same name as the new interface's methods) • just as in Java's world, the result of the operation depends on the underlying implementation, meaning you have to watch out for
UnsupportedOperationException
again
l
kotlin.MutableCollection
compiles to
java.util.Collection
.
kotlin.Collection
and
kotlinx.collections.immutable
are their own, standalone classes, that do not have equivalents in the JDK. When using Kotlin, make sure not to accidentally import
java.util
classes, as Kotlin's are automatically imported.
s
Firstly, that's not what I'm asking about, secondly, that is not necesarilly correct. When using Kotlin JVM, all
kotlin.collections.Collection
types are also types of
java.util.Collection
, otherwise you wouldn't be able to use Java's Collections API on it, which of course you can.
Copy code
fun main() {
    val collection = PureKotlinCollection<Int>()
    println(collection is java.util.Collection<*>) // always returns true
}

class PureKotlinCollection<E> : kotlin.collections.Collection<E> {
    override val size: Int get() = TODO("Not yet implemented")
    override fun isEmpty(): Boolean = TODO("Not yet implemented")
    override fun iterator(): Iterator<E> = TODO("Not yet implemented")
    override fun containsAll(elements: Collection<E>): Boolean = TODO("Not yet implemented")
    override fun contains(element: E): Boolean = TODO("Not yet implemented")
}
From what I understand, distinguishing between Collection and MutableCollection allows compiler to prioritize Kotlin's interfaces over Java ones, and that's why having
kotlin.collections.List
you cannot call
add
method, because it is moved to seperate
kotlin.collections.MutableList
interface. Now, as I mentioned, the problem is, that every
kotlin.collections.List
is also
java.util.List
, therefore it is also
SequencedCollection
in JDK 21. Kotlin does not yet have dedicated interfaces as
kotlin.collections.SequencedCollection
and
kotlin.collections.MutableSequencedCollection
to allow the compiler prioritizing them and as a result affect original methods visibility. Because of that, you can call all the
SequencedCollection
methods on any
kotlin.collections.List
as presented on the snippet below
Copy code
fun main() {
    val listReadOnlyUnderneath: kotlin.collections.List<Int> = listOf(1, 2, 3)
    val listMutableUnderneath: kotlin.collections.List<Int> = List(3) { it + 1 }
    println(runCatching { listReadOnlyUnderneath.removeLast() }) // Failure(java.lang.UnsupportedOperationException)
    println(runCatching { listMutableUnderneath.removeLast() }) // Success(3)
    println(listReadOnlyUnderneath) // [1, 2, 3]
    println(listMutableUnderneath) // [1, 2], list mutated
}
l
You're wrong -
kotlin.collections.List
isn't always a
java.util.List
. It can be a
kotlinx.collections.immutable.ImmutableList
Or any other implementation.
kotlin.collections.MutableList
is equivalent to
java.util.List.
(and is actually the same class)
Copy code
java.util.List is kotlin.collections.List // true
java.util.List is kotlin.collections.MutableList // true
kotlin.collections.List is java.util.List // depends
kotlin.collections.MutableList is java.util.List // true
s
Please at least look at the provided samples before commenting. It is not about implementation, but about direct relation between kotlin interfaces and Java interfaces for Kotlin JVM. I've already provided sample with custom class implementing
kotlin.collections.collection
, where
is java.util.Collection<*>
check returned
true,
but here's example of
kotlinx.collections.immutable.ImmutableList
to double prove myself. Please run it yourself if you don't believe me.
Copy code
val immutableList = kotlinx.collections.immutable.persistentListOf(1, 2, 3)
println(immutableList is java.util.List<*>) // true
d
Thank you for noticing it! Looks like a bug, indeed. Created KT-64640 for tracking.
❤️ 2
👍 2