何时使用 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.
关于您的代码,我要指出两点。
- 您不需要
mmServerSocket
和 mSocketType
上的 lateinit
关键字,因为您正在构造函数中初始化这两个变量。你会需要它,如果变量在创建后被初始化的话。
- 有一种情况会抛出异常。如果抛出
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
}
我正在开发者网站上的 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.
关于您的代码,我要指出两点。
- 您不需要
mmServerSocket
和mSocketType
上的lateinit
关键字,因为您正在构造函数中初始化这两个变量。你会需要它,如果变量在创建后被初始化的话。 - 有一种情况会抛出异常。如果抛出
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
}