Kotlin:MutableList中的java.lang.UnsupportedOperationException添加元素

Seb*_*ian 3 java algorithm stack kotlin

我正在Kotlin中实现用于研究目的的堆栈算法

class Stack<T:Comparable<T>>(list:MutableList<T>) {

    var items: MutableList<T> = list


    fun isEmpty():Boolean = this.items.isEmpty()

    fun count():Int = this.items.count()

    fun push(element:T) {
        val position = this.count()
        this.items.add(position, element)
    }

    override  fun toString() = this.items.toString()

    fun pop():T? {
        if (this.isEmpty()) {
            return null
        } else {
            val item =  this.items.count() - 1
            return this.items.removeAt(item)
        }
    }

    fun peek():T? {
        if (isEmpty()) {
            return null
        } else {
            return this.items[this.items.count() - 1]
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用此代码执行:

fun main(args: Array<String>) {

        var initialValue = listOf<Int>(10) as MutableList<Int>
        var stack = Stack<Int>(initialValue)
          stack.push(22)
        println(stack.count())
        println(stack.isEmpty())
        println(stack.pop())
        println(stack.count())
        println(stack.isEmpty())

    }
Run Code Online (Sandbox Code Playgroud)

当我运行代码时,我收到此错误:

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at Stack.push(Stack.kt:17)
at StackKt.main(Stack.kt:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Run Code Online (Sandbox Code Playgroud)

这与在push(element:T)方法中实现的以下行相关 :

 this.items.add(position, element)
Run Code Online (Sandbox Code Playgroud)

最奇怪的是我使用了一个非常相似的代码来实现orderedArray并且它完美地运行.

你知道我做错了什么吗?

szy*_*zym 9

listOf<Int>并不是真正可变的.根据文件:

fun <T> listOf(vararg elements: T): List<T> (source) 返回给定元素的新只读列表.返回的列表是可序列化的(JVM).

你应该使用mutableListOf<>.

as MutableList这里允许的原因是因为listOf(10)返回Collections.singletonList(10)一个java.util.List(Kotlin假定实现kotlin.collections.MutableList接口的返回).因此,在运行时调用mutating方法并抛出异常之前,编译器不知道它不是真正可变的.

  • 为什么强制转换是合法的解释如下:`List` 是一个接口,`MutableList` 是一个扩展 `List` 的接口。因此,从 `List` 转换为 `MutableList` 是合法的,但它可能并且会在运行时崩溃。 (2认同)
  • Kotlin 的`List` 和`MutableList` 都在编译时映射到`java.util.List`,在运行时根本不存在。 (2认同)

Hum*_*Bee 5

您可以通过调用 toMutableList() api 而不是使用智能转换 (as) 来解决此问题。

尝试: var initialValue = listOf< Int >(10).toMutableList()

下面是一个工作示例:

fun main(){
    val x : List<String> = listOf("foo", "bar", "baz")
    //val y: MutableList<String> = x as MutableList<String> throws UnsupportedOperationException
    val y: MutableList<String> = x.toMutableList()
    y.add("sha")
    println(y) // [foo, bar, baz, sha]
}
Run Code Online (Sandbox Code Playgroud)