不能为空的抽象变量能否在KOTLIN中引发Null指针异常?

问题描述 投票:0回答:1

免责声明:这是用Kotlin编码的,不是一些简单的初学者级代码。请不要标记它,因为您认为我是一个不知道Null Pointer Exception是什么的菜鸟。比这复杂得多。我之前上传了这个问题,建议您查找什么是Null Pointer Exceptions,然后将我的问题标记为与有关Null Pointer Exceptions的问题重复,然后立即关闭。如果您来自Java,那么Kotlin甚至不允许您创建不分配对象的对象(未指定它们是可空的,并且提供空安全检查每次使用它们]。我的问题不是那么简单,所以请先仔细阅读。在我甚至还没有读完整个内容之前,我的问题就已经结束了,所以至少在您认为我只是愚蠢之前就这样做。

信息:

这是一个Swing应用

我在Kotlin中编码

我正在尝试为Swing创建边界的类系统(搜索“干净代码边界”以获得更多信息)。本质上,我有两个类都从我制作的Item类继承。

abstract class Item(var text: String = "", var icon: Icon? = null, var items: ArrayList<Item> = ArrayList()) {

    abstract var component: JComponent

    init {
       applyProperties()
        applyItems()
    }

    fun applyProperties() {
        when (component) {
            is JMenu -> {
                (component as JMenu).text = text
                (component as JMenu).icon = icon
            }
            is JMenuItem -> {
                (component as JMenuItem).text = text
                (component as JMenuItem).icon = icon
            }
        }
    }
    fun applyItems() {
        for (item in items) {
            apply(item)
        }
    }
    private fun apply(item: Item) {
        component.add(item.component)
    }
    companion object {
        fun ArrayList<Item>.addItems(vararg items: Item) {
            this.addAll(items)
        }
    }
}

另外两个类除了覆盖组件变量外什么也不做,然后applyProperties()中的switch语句可以使用组件变量类型来知道要设置的变量。到目前为止,两个类都需要设置的变量相同,但是我使用了多态性,因此以后可以使用不同的函数添加更多的类。这是其中之一,只是为了向您显示几乎不可能是它们的原因。

class Menu(text: String = "", icon: Icon? = null, items: ArrayList<Item> = ArrayList()): Item(text, icon, items) {
   override var component: JComponent = JMenu()
}

这是我抛出空指针异常的结果。

var menu: JMenu = MenuBuilder().set { menu ->
    menu.text = "Save"
    menu.items.addItems(

        MenuItemBuilder().set { menuItem ->
            menuItem.text = "Save"
        }.build(),

        MenuItemBuilder().set { menuItem ->
            menuItem.text = "Save As"
        }.build()
    )
}.build()

apply()上调用的applyItems()方法在add()上调用,该方法接收一个JComponent作为输入,然后引发异常。但是,我输入的组件始终在运行add()之前设置。它是一个抽象变量,始终在创建Item类的实例时设置。另外,如果我忘记设置它,它甚至不应该让我运行。我用Kotlin编码,它具有极高的null安全性。除非我自己丢一个,否则我不应该得到一个空指针异常。它甚至不是一个可为空的变量,所以为什么add()抛出异常?

如果要检查用于执行此操作的任何其他类,以查看它们是否可能导致空指针异常,我将其全部放在下面。

class MenuBuilder {
    var text: String = ""
    var icon: Icon? = null
    var items: ArrayList<Item> = ArrayList()

    fun set(builderFunction: (MenuBuilder) -> Unit): MenuBuilder {
        builderFunction(this)
        return this
    }

    fun build() = Menu(text, icon, items)
}

class MenuItemBuilder {
    var text: String = ""
    var icon: Icon? = null
    var items: ArrayList<Item> = ArrayList()

    fun set(builderFunction: (MenuItemBuilder) -> Unit): MenuItemBuilder {
        builderFunction(this)
        return this
    }

    fun build() = MenuItem(text, icon, items)
}

这些是我用来使菜单和MenuItems的创建更加容易的构建器模式,但是使用MenuItem(// parameters)键入应该具有相同的效果(并产生相同的错误)。

swing kotlin nullpointerexception jcomponent
1个回答
0
投票

possible ways to get NullPointerException in Kotlin之一是:

  • 超类构造函数调用一个开放成员,其派生类中的实现使用未初始化状态

这就是您的示例中正在发生的事情。您最终将在init类的Item块中访问component属性,该属性尚未初始化,因为派生的Menu类构造函数尚未完成。这种情况在https://kotlinlang.org/docs/reference/classes.html#derived-class-initialization-order中进行了描述。

如果在基类构建过程中需要component值,则可以将其与其他参数一起传递给基类构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.