当前位置: 首页 > 面试题库 >

变量“可运行”必须初始化

何嘉运
2023-03-14
问题内容

为什么Kotlin对此抱怨:

class MyActivity : Activity {
  private var handler:Handler = Handler()

  private var runnable: Runnable = Runnable {
    /* Do something very important */
    handler.postDelayed(this@MyActivity.runnable, 5000)
  }
}

编译器抱怨Variable 'runnable' must be initialized在Line中由处理程序再次发布。这在纯Java中确实有效:

private Handler handler = new Handler();

private Runnable runnable = new Runnable() {
    @Override
    public void run() {
        handler.postDelayed(runnable, 5000);
    }
};

问题答案:

Kotlin认为一个属性在其初始化程序结束之前尚未初始化,因此即使在lambda中也无法在其自己的初始化程序中使用该属性。这种语义类似于其初始化程序内部局部变量使用的限制。

有几种解决方法:

  • 使用对象表达式可以引用this已声明的对象:
    private var runnable: Runnable = object : Runnable {
    override fun run() {
        /* Do something very important */
        handler.postDelayed(this, 5000)
    }
    

    }

这仅适用于接口作为lambda的替代品,并且不是很好。

  • 与一起使用lateinit var或委派属性Delegates.notNull()
    private lateinit var runnable: Runnable
    

    init {
    runnable = Runnable {
    / Do something very important /
    handler.postDelayed(runnable, 5000)
    }
    }


相同的初始化程序将与此声明一起使用:

    private var runnable: Runnable by Delegates.notNull()
  • 自行实现并使用初始化程序的自引用:

    class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
    val self: T by lazy {
        inner ?: throw IllegalStateException("Do not use `self` until initialized.")
    }
    
    private val inner = initializer()
    

    }

    fun selfReference(initializer: SelfReference .() -> T): T {
    return SelfReference(initializer).self
    }

然后你可以写一些像

    private var runnable: Runnable = selfReference { 
    Runnable {
        /* Do something very important */
        handler.postDelayed(self, 5000)
    } 
}


 类似资料:
  • 问题内容: 例如,如果我有一个变量,并且在主线程中声明了一个runnable,并且想将x传递给该runnable的方法,则必须对其进行声明。为什么? 问题答案: 因为如果能够更改它们,可能会导致很多问题,请考虑以下事项: 这是一个粗略的示例,但您可以看到可能发生许多无法解释的错误。这就是变量必须为最终变量的原因。这是解决上述问题的简单方法: 如果您需要更完整的说明,则有点像同步。Java希望防止您

  • 问题内容: 我有一个方法创建一个,另一个方法更改字符串 我的编译器说它“可能尚未初始化”。 有人可以解释吗? 问题答案: 变量可能尚未初始化 在内部定义方法时,必须在其中初始化程序的每个变量中必须先使用一个值的地方。 同样重要的是,您的代码将永远无法正常运行,因为Java中的字符串是不可变的,因此您无法编辑字符串,因此应更改方法。 我将您的代码更改为类似的内容,但是我认为您的编辑方法应该做另一件事

  • 问题内容: 为什么必须始终在Java中初始化局部变量(包括基元)?为什么相同的实例变量不适用? 问题答案: 基本上,要求在读取变量之前为其分配值是一件好事。这意味着您不会意外阅读您不想要的内容。是的,变量可以具有默认值-但如果编译器可以证明您正在尝试读取尚未分配的内容,那么编译器是否可以捕获错误不是更好吗?如果要为局部变量提供默认值,则始终可以显式分配。 现在,对于局部变量来说,这很好-但是对于实

  • 所以我已经在结果中声明了相关字符串的值,但是它仍然说我的变量“result”可能还没有初始化。 我正在尝试实现与此类似的输出。任何人都可以帮我吗?谢谢!

  • 我正在研究Euler Problem 9项目,其中说明: 毕达哥拉斯三元组是由三个自然数组成的集合 例如,3^2 4^2=9 16=25=52。 确实存在一个毕达哥拉斯三重态,其bc=1000。查找产品abc。 以下是我到目前为止所做的: 当我运行代码时,会出现以下错误: 注意:我的每个变量(a、b和c)都有不同的行号。 我想当我声明a、b和c为整数时,如果不赋值,默认值是0。 即使不是这样,在我

  • 问题内容: 如何使用类型初始化变量? 因为我有错误 问题答案: 常量声明不能包含函数调用(某些例外,请参见下文),它们必须在编译时进行评估,而函数调用是在运行时进行的。 引用规格:常量: 常数值由符文,整数,浮点数,虚数或字符串文字表示,标识符表示常数,常数表达式,结果为常数的转换或某些内置结果的值函数,例如应用于任何值,或应用于某些表达式,以及应用于常量,以及应用于数字常量的复数。 并引用Spe