我正在开发者网站上的Android蓝牙聊天项目,我正在尝试使用Kotlin而不是java。我是Kotlin的新手,我只是对使用我的init块和lateinit关键字以及我的伴侣对象的“正确”方式感到困惑。在我发布的代码中我没有伴侣对象,但我想知道我是否应该。到目前为止,我主要只是使用一个伴侣对象来模仿java的静态类成员,或者有时包含类常量。至于我的init块,我基本上用于构造函数。这是通过类声明中定义的实际构造函数传递成员的赋值。至于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
}
}
答案 0 :(得分:3)
考虑到你在构造函数中初始化变量,这里不需要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
}
答案 1 :(得分:2)
如果这是正确的用法或事情,请告诉我 如果不是则改变。
关于您的代码,我会指出两件事。
lateinit
和mmServerSocket
上都不需要mSocketType
关键字,因为您正在构造函数中初始化这两个变量。如果变量在创建后已初始化,那么您将需要它。tmp
,变量IOException
可以为null。在这种情况下,当您将tmp
分配给mmServerSocket
时,将会抛出KotlinNullPointerException
。
您有几种方法可以解决它:您可以在catch
块中处理默认情况,可以使mmServerSocket
可以为空等等。