6

As we know the List in Kotlin is immutable i.e. you can't do add and remove as below.

class TempClass {
    var myList: List<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        myList!!.add(10)
        myList!!.remove(10)
    }
}

But if we cast it to ArrayList as below, the add and remove works.

class TempClass {
    var myList: List<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        (myList!! as ArrayList).add(10)
        (myList!! as ArrayList).remove(10)
    }
}

I just thought this is odd, as myList is really a List, which is suppose to be immutable. And casting it, allow it to be altered.

Is what done above (casting to Array and modify the content) legitimate, or the language need to improve to disallow that?

Elye
  • 53,639
  • 54
  • 212
  • 474
  • 2
    Possible duplicate of [Kotlin and Immutable Collections?](http://stackoverflow.com/questions/33727657/kotlin-and-immutable-collections) – Jayson Minard Jun 22 '16 at 00:59
  • The link offered does explain that List is not immutable, but readable. But then "Readable" is really not as 'useful' given that, it could still be cast to be changed. Ideally, 'readable' shouldn't be cast-able to something 'writeable' – Elye Jun 22 '16 at 01:20
  • It is enough to cast to `MutableList`, a super type of `ArrayList` – voddan Jun 22 '16 at 02:22
  • It looks like you're trying to initialize the list after assigning. In that case you can do `ArrayList().apply { add(10) }` or even better just use the built-in factory functions like `listOf(10)`. – Kirill Rakhman Jun 22 '16 at 11:30
  • A blocker to prevent casting of List to mutable (and other collection types) wax added today to Klutter library blocking all related actions such as an `Iterator` recieved from a list, a `subList` from a list, a `entrySet` from a map and more. See: http://stackoverflow.com/a/38002121/3679676 ... you cannot cast around it, nor any other collection it returns, they are truly protected. – Jayson Minard Jun 23 '16 at 21:30

3 Answers3

7

There are a few different types of immutability:

One is mentioned from a separate SO answer here.

Readonly - you are NOT supposed to change it (Kotlin's List) but something may (cast to Mutable, or change from Java).

List is just an interface that does not have mutating methods, but you can change the instance if you cast it to MutableList.

Someone then goes on to comment that Kotlin chose to be readonly in order to use Java collections directly, so there is no overhead or conversion in using Java collections.

Kotlin List is readonly, not immutable. Other callers (Java for example) may change the list. Kotlin callers might cast the list and change it. There is no immutable protection.

Original Source: Kotlin and Immutable Collections?

Community
  • 1
  • 1
gotnull
  • 26,454
  • 22
  • 137
  • 203
  • Thanks gotnull. That explained well. Immutable != Readable... The "Readable" is not as safe as "Immutable"/ – Elye Jun 22 '16 at 01:21
  • 1
    some instances of `List` in kotlin's library are immutable, e.i. the cast will fail. You have to make sure that your list is indeed a subclass of `ArrayList` – voddan Jun 22 '16 at 02:20
2

Is it legitimate? Well, yes. There are uses cases in which that would make sense.

Is it a good idea? I think not, especially if you're talking about casting a list that was returned by some external library. The cast will fail if someone actually hands you some List implementations that really is immutable and does not implement MutableList. The fact that at the moment (Kotlin 1.0.2), all of Kotlin's Lists are also MutableLists doesn't mean that every List you'll ever see in your code is also an MutableList.

Malt
  • 28,965
  • 9
  • 65
  • 105
1

Right now if you use listOf() you'll get a List with all methods, which mutate the list, throwing java.lang.UnsupportedOperationException:

val list = listOf(1, 2)

val mlist = list as MutableList

mlist.add(3)

This throws:

Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.AbstractList.add(AbstractList.java:148)
D3xter
  • 6,165
  • 1
  • 15
  • 13