Котлин: изменение (неизменяемого) списка через cast, является ли это законным?

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

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-это действительно список, который должен быть неизменным. И бросая его, позвольте ему быть измененным.

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

3 ответов


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

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

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

List - Это просто интерфейс, который не имеет методов мутации, но вы можете изменить экземпляр, если вы приведете его к MutableList.

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

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

Источник: Котлин и неизменяемые коллекции?


это нормально? Ну да. Есть случаи использования, в которых это имело бы смысл.

это хорошая идея? Я думаю, что нет, особенно если вы говорите о приведении списка, который был возвращен какой-то внешней библиотекой. Бросок не удастся, если кто-то вручает вам подарки!--0--> реализации, которые действительно неизменяемы и не реализуют MutableList. Дело в том, что на данный момент (Котлин 1.0.2), все Котлина Lists также MutableLists не означает, что каждый List вы когда-нибудь увидите, что в вашем коде также есть MutableList.


Если вы используете listOf () вы получите список со всеми методами, которые мутируют список, бросая java.ленг.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)