何时使用 lateinit、init 块和伴随对象。科特林

when to use lateinit, init block, and companion object. Kotlin

我正在开发者网站上的 android 蓝牙聊天项目,我正在尝试使用 Kotlin 而不是 java。我是 Kotlin 的新手,我只是对 "right" 将我的 init 块和 lateinit 关键字与我的伴随对象一起使用的方式感到困惑。在我发布的代码中,我没有伴随对象,但我想知道是否应该。到目前为止,我主要只是使用伴随对象来模仿 java 的静态 class 成员,或者有时包含 class 常量。至于我的 init 块,我基本上用于构造函数。这与通过 class 声明中定义的实际构造函数传入的成员赋值不同。至于 lateinit,我用它来声明我不想立即初始化但也不想使其可为空的成员。请让我知道这是否是正确的用法,或者如果不是,我需要更改。这是我的代码:

    inner class AcceptThread(val secure:Boolean) : Thread(){
    lateinit var mmServerSocket:BluetoothServerSocket
    lateinit var mSocketType:String

    init {
        var tmp:BluetoothServerSocket? = null
        mSocketType = if (secure) "Secure" else "Insecure"

        try {
            if (secure){
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_SECURE)
            } else{
                tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, UUID_INSECURE)
            }
        }catch (ioe:IOException){
            Log.e(TAG, "Socket Type: $mSocketType listen() failed", ioe)
        }
        mmServerSocket = tmp!!
        mState = STATE_LISTEN
    }
}

Please let me know if this is correct usage or thing's for me to change if it is not.

关于您的代码,我要指出两点。

  1. 您不需要 mmServerSocketmSocketType 上的 lateinit 关键字,因为您正在构造函数中初始化这两个变量。你会需要它,如果变量在创建后被初始化的话。
  2. 有一种情况会抛出异常。如果抛出 IOException,则变量 tmp 可以为 null。在这种情况下,当您将 tmp 分配给 mmServerSocket 时,将抛出 KotlinNullPointerException。 您有多种修复它的可能性:您可以在 catch 块中处理默认情况,您可以使 mmServerSocket 可为空等。

这里不需要 lateinit 考虑到您正在构造函数中初始化变量。例如,如果您要在像 onCreate() 这样的生命周期方法中初始化变量,那么您可以使用 lateinit var.

此外,我认为您可以重构 init 块以消除 tmp 变量:

inner class AcceptThread(val secure:Boolean) : Thread() {
val mmServerSocket: BluetoothServerSocket
val mSocketType: String = if (secure) "Secure" else "Insecure"

init {
    try {
        mmServerSocket = if (secure) {
            mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_SECURE)
        } else {
            mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, UUID_INSECURE)
        }
    } catch (ioe: IOException) {
        Log.e(TAG, "Socket Type: $mSocketType listen() failed", ioe)
    }
    mState = STATE_LISTEN
}