【问题标题】:Kotlin: Even if the class has a nullable generic parameter type E, assignement failsKotlin:即使类具有可为空的泛型参数类型 E,赋值也会失败
【发布时间】:2020-04-01 14:23:13
【问题描述】:

我正在为可空和不可空类型苦苦挣扎。有两个错误。 我定义了一个实现“队列”概念的类,如下所示,试图使其通用参数类型可以为空,这里有第一个错误:

class QueueLightweight<T: Any?> { //: Queue<T?> removed because of Java clashes, but it's another question
        protected var size = 0
        protected var first: NodeQLW<T>? = null
        protected var last: NodeQLW<T>? = null

        protected class NodeQLW<E>(var item: E) {
            var next: NodeQLW<E>? = null
        }

        ....

        fun iterator(): Iterator<T> {
            return IteratorQLW(this)
        }

        ....

        fun add(e: T?): Boolean {
            val n: NodeQLW<T>
            n = NodeQLW(e) // <--- first error: 
            // "type inference failed: required: QueueLightweight.NodeQLW<T> , found: QueueLightweight.NodeQLW<T?> "
            if (size == 0) {
                last = n
                first = last
                size = 1
            } else {
                last!!.next = n
                last = n
                size++
            }
            return true
        }
    }

然后我定义了一个 Iterator 子类,如下所示,在突出显示的行(通过箭头),有错误。

protected class IteratorQLW<E: Any?>(var q: QueueLightweight<E>) :
Iterator<E> {
var n: NodeQLW<E>?
init {
    n = q.first
}

override fun hasNext(): Boolean {
    return n != null
}

override fun next(): E {
    var e: E
    e = null // <--- error here: null cannot be a value of a non-null type E
    if (n != null) {
        e = n!!.item
        n = n!!.next
    }
    return e
}

}

我不明白如何修复这些错误。

【问题讨论】:

    标签: generics kotlin types parameters non-nullable


    【解决方案1】:

    该类型默认允许为空,因此您的类类型定义只能是&lt;T&gt;,而不是&lt;T: Any?&gt;。使用类时,可以将泛型类型指定为不可为空(例如使用QueueLightweight&lt;String&gt; 而不是QueueLightweight&lt;String?&gt;),因此在使用泛型类型时必须将其视为不可为空课堂内。

    这是您的第一个问题的根源。您的 NodeQLE 期望其构造函数有一个可能不可为空的参数,但您强制它为 null。您的 add 方法应该采用 T 参数,而不是强制使用 T?

    然后在您的迭代器中,您将一个变量声明为(可能)不可为空的E,但为其分配一个空值。您需要使变量可以为空。由于即使 E 不可为空,它也可以返回 null,因此如果没有下一个值,则必须抛出异常。但这可以通过改变分支来简化,所以方法应该是这样的:

    override fun next(): E {
        n?.let {
            n = it.next
            return it.item
        }
        throw NoSuchElementException()
    }
    

    【讨论】:

      【解决方案2】:

      不可为空的类型是对应的可空类型的子类型。例如。任何String 都是String?,因此StringString? 的子类型。所以任何类型,包括不可为空的类型,都是Any?E: Any? 的子类型,绑定不会强制E 可以为空(并且可以删除)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-25
        • 2018-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-02
        相关资源
        最近更新 更多