JavaFX8 随录 二 Kotlin 小坑

2017.04.15 16:12 Sat| 226 visits | Text

使用JavaFX开发软件,写着写着Java就不耐烦了,想痛痛(zhuang)快快(bi)的用上Kotlin,远离裹脚布似的代码。开开心心的配置完Kotlin环境,在intellij idea里面把已经写好的Java代码用Ctrl+Shift+Alt+K快捷键转换成Kotlin代码。看着自动转换后Kotlin代码,想着能码Kotlin就觉着爽,爽,爽啊。

运行个看看吧,,,dung~报错了

项目Application入口类:

public class Main extends Application {
   ... ... ...
    public static void main(String[] args) {
        launch(args);
    }
}

自动转成Kotlin代码之后:

class Main : Application() {
   ... ... ...
    companion object {
        @JvmStatic fun main(args: Array<String>) {
            Application.launch(*args)
        }
    }

调用Application.launch()函数时,JavaFX框架报错。

"Error:  object is not a subclass of javafx.application.Application"

JavaFX在launch中会检测调用该方法的类是否是Application类的子类。在Java中的static方法,转换到Kotlin中成了companion object中的方法,导致编译不过。这个小坑好办,改成这样搞定:

class Main : Application() {
   ... ... ...
    companion object {
        @JvmStatic fun main(args: Array<String>) {
           launch(Main::class.java)
        }
    }

这是第一个坑,还有一个自动转换的坑是下面这个。

public class ServerController implements Initializable {

    @FXML
    private HBox legendTarget;
    @FXML
    private VBox parentBox;
    ... ... ...
}

给转成了下面这样

class ServerController : Initializable {

    @FXML
    private val legendTarget: HBox? = null
    @FXML
    private val parentBox: VBox? = null
    ... ... ...
}

然后使用FXML注解的变量永远为空,取不到值了。
这个不应该啊。。没理由啊。。

Google之,有这么写的

@FXML val legendTarget: HBox = new HBox()

试了下,完全扯淡不好使。

然后我用lateinit特性试了下

@FXML private lateinit var legendTarget: HBox

就这么好了。

想不明白原因,一开始的写法就是给变量赋值成null而已,会导致JavaFX无法给他们再次赋值?是JavaFX的问题还是Kotlin的问题?

试了下,在Java代码中,不管是明确用null还是用new对象初始化被FXML注解标注的变量,均不影响程序的正常运行。

推测是Kotlin反射的问题,有没有大神给提示一下?

这个问题说明我是个Kotlin noob!!!我刚意识到出问题是因为自动转换生成的变量是val,而不是var。蛋疼。跟lateinit没关系