2016-04-05 5 views
1

IchKotlin: java.lang.UnsupportedOperationException in MutableList hinzufügen Element

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] 
     } 
    } 

} 

einen Stapel Algorithmus für die Studie Zweck in Kotlin Umsetzung Und ich versuche, diesen Code auszuführen, mit:

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()) 

    } 

Wenn ich den Code ausführen erhalte ich diesen Fehler:

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) 

Diese mit der Folge Linie verwandt ist, die Umset ist ted in push (Element: T) Methode:

this.items.add(position, element) 

Das Seltsame ist, dass ich eine orderedArray einen sehr ähnlichen Code Implementierung verwendet und es funktioniert perfekt.

Haben Sie eine Ahnung, was ich falsch mache?

Antwort

5

listOf<Int> ist nicht wirklich veränderbar. Nach the doc:

fun <T> listOf(vararg elements: T): List<T> (source) Returns a new read-only list of given elements. The returned list is serializable (JVM).

sollten Sie mutableListOf<> stattdessen verwenden.

Der Grund, warum as MutableList erlaubt hier ist, weil listOf(10) kehrt Collections.singletonList(10), die eine java.util.List zurückgibt (die Kotlin übernimmt implementiert die kotlin.collections.MutableList Schnittstelle). Daher weiß der Compiler nicht, dass er nicht wirklich änderbar ist, bis die Mutationsmethode zur Laufzeit aufgerufen wird und die Ausnahme auslöst.

+1

Also die Lösung ist, in der Hauptmethode, initialvalue mit mutableListOf anstelle von listOf, richtig? – Sebastian

+0

Ja. Ich habe die Antwort aktualisiert. – szym

+1

Die Erklärung, warum die Besetzung legal ist, lautet wie folgt: 'List' ist eine Schnittstelle und' MutableList' ist eine Schnittstelle, die 'List' erweitert. Daher ist das Umwandeln von 'List' nach' MutableList' zulässig, kann aber zur Laufzeit abstürzen. –