何时使用lateinit,init块和companion对象。 Kotlin

我正在从开发人员的网站的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 } } 

考虑到你在构造函数中初始化你的变量,你不需要在这里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. 您不需要mmServerSocketmSocketType上的lateinit关键字,因为您正在构造函数中初始化这两个变量。 如果在创建之后变量已经被初始化,你将需要它。
  2. 有一种情况可能会引发异常。 如果抛出IOException则变量tmp可以为空。 在这种情况下,当您将tmp分配给KotlinNullPointerException将引发KotlinNullPointerException 。 你有几种可能的解决方法:你可以在catch块中处理一个默认情况,你可以使mmServerSocket空,等等。