Kotlin: Модифицировать (неизменный) Список через бросок, это законно?

Поскольку мы знаем, что Список в Котлине неизменен, т. Е. Вы не можете добавлять и удалять, как показано ниже.

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

Но если мы передадим его в ArrayList, как показано ниже, то добавление и удаление будут работать.

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

Я просто подумал, что это странно, так как myList – это действительно список, который, как предполагается, является неизменным. И бросив его, позвольте ему изменить его.

Является ли то, что сделано выше (кастинг в Массив и изменение контента) законным, или язык должен улучшать, чтобы запретить это?

Существует несколько разных типов неизменности:

Один из них упоминается из отдельного ответа SO здесь .

Readonly – вы НЕ должны его менять (список Котлина), но что-то может (переключение на Mutable или изменение с Java).

List – это просто интерфейс, который не имеет мутирующих методов, но вы можете изменить экземпляр, если вы MutableList его в MutableList .

Затем кто-то продолжает комментировать, что Котлин выбрал только для чтения, чтобы напрямую использовать коллекции Java, поэтому нет никаких накладных расходов или конверсии в использовании коллекций Java.

Список Котлин – только для чтения, а не неизменный. Другие вызывающие абоненты (например, Java) могут изменить список. Абоненты Kotlin могут перечислить список и изменить его. Нет постоянной защиты.

Оригинальный источник: Kotlin и неизменяемые коллекции?

Это законно? Ну да. Существуют случаи, когда это имеет смысл.

Это хорошая идея? Я думаю, что нет, особенно если вы говорите о литье списка, который был возвращен какой-то внешней библиотекой. Листинг не удастся, если кто-то действительно передаст вам некоторые реализации List которые действительно являются неизменяемыми и не реализуют MutableList . Тот факт, что на данный момент (Kotlin 1.0.2) все Lists Kotlin также являются MutableList , не означает, что каждый List вы когда-либо увидите в своем коде, также является MutableList .

Прямо сейчас, если вы используете listOf (), вы получите список со всеми методами, которые мутируют список, бросая java.lang.UnsupportedOperationException:

 val list = listOf(1, 2) val mlist = list as MutableList mlist.add(3) 

Это бросает:

 Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148)