As Kotlin documentation says listOf<T>
has three implementations: for no arguments, one argument and varargs. Each function should return immutable List<T>
.
val emptyList = listOf<String>()
val oneArgList = listOf("asd")
val varargsList = listOf("asd", "asd")
if (emptyList is MutableList) println("emptyList is mutable")
if (oneArgList is MutableList) println("oneArgList is mutable")
if (varargsList is MutableList) println("varargList is mutable")
Execution of code above results in
oneArgList is mutable
varargList is mutable
Why it works that way? Is this desired behaviour?
Why it works that way?
If you check out the source code, you will find it actually creates a Java ArrayList
. This leverages the JDK instead of having to implement an ArrayList
in Kotlin. Note that your cast to MutableList
is a bad coding practice even if it is successful since the listOf()
function already specifies it is a List
and not a MutableList
.
emptyList()
(or listOf()
) on the other hand uses an EmptyList
singleton implemented in Kotlin that is truly immutable.
Is this desired behaviour?
Actually no. However it does the trick presenting an immutable interface instead. It doesn't really matter how exactly the backing data structure is implemented as long as it conforms to the interface contract. You as a programmer should also stick to the contract when using it.
You say "each one should return immutable lists", but if you look at the documentation for the three functions, the first one says it returns an immutable List, and the next two say they return a read-only List. A read-only List is not necessarily immutable.
The List interface does not guarantee immutability. It only describes itself as providing solely read-only methods.
In actual practice, haphazardly doing is
checks is a big time code smell. There are some narrow use cases that kind of make sense. Like Google's recommended way to create a DialogFragment and communicate back to the Activity, but stuff like this is (IMO) a hack to get around regrettable decisions from the original design of Activities and Fragments. In the case of this example, you would control the definition of your interface, and all implementations of it, so its a little harder for things to go wrong.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With