Kotlin中“ = lazy”和“ by lazy”有什么区别?

时间:2019-07-24 08:16:16

标签: kotlin

我想知道科特林的'= lazy'与'by lazy'有什么区别

val host by lazy { ... }
val host = lazy { ... }

在我的Android代码中

val host by lazy {
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
}

成功

但此代码

val host = lazy {
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
}

失败了

3 个答案:

答案 0 :(得分:0)

lazy { ... }部分指定一个返回Lazy<T>的函数。

如果您只说val foo = lazy { "bar" },那么任何get或set操作都将在Lazy<String>实例上进行。

使用val foo by lazy { "bar" }时,是在告诉编译器将foo上的所有get或set操作委托给String


如果我们有这个:

class Test {
    val usingAssign = lazy {
        "bar"
    }

    val usingBy by lazy {
        "bar"
    }
}

,我们看一下相应的Java代码,它看起来像这样:

private final Lazy usingAssign;
private final Lazy usingBy$delegate;

public final Lazy getUsingAssign() {
   return this.usingAssign;
}

public final String getUsingBy() {
   Lazy var1 = this.usingBy$delegate;
   KProperty var3 = $$delegatedProperties[0];
   return (String)var1.getValue();
}

public Test() {
   this.usingAssign = LazyKt.lazy((Function0)null.INSTANCE);
   this.usingBy$delegate = LazyKt.lazy((Function0)null.INSTANCE);
}

因此,任何尝试读取usingBy的尝试都会给我们String,然后我们可以例如分配给另一个String变量。您无法使用usingAssign来执行此操作,因为其类型为Lazy<String>

答案 1 :(得分:0)

by lazy表示,该逻辑将在首次使用时执行

  

惰性属性:仅在首次访问时才计算该值

使用时

val host = lazy {
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
}

您基本上将惰性属性分配给主机变量。这样就变成了Lazy<Something>,您可以从中获取值或检查其是否已初始化。

by lazy {"test"}->给出String

= lazy { "test" }->给出Lazy<String>

答案 2 :(得分:0)

val host by lazy { ... }

这意味着主机属性是Kotlin's lazy delegate增强的属性。首次访问时,其值仅计算一次。后续通话仅返回第一次通话的缓存结果。

val host = lazy { ... }

另一方面,这意味着不包含通过委托增强的主机属性,它包含一个惰性委托。由于它包含委托对象,因此您可以访问其方法,例如isInitialized()或访问将触发其计算的委托的value

考虑以下示例:

val host = lazy {
    println("computed!")
    "Hello"
}

fun main() {
    println(host)
    println(host.value)
    println(host)
}

在这里,我们有一个懒惰的代表host。如果尝试打印其值,则会得到:“惰性值尚未初始化。” 。但是,一旦访问它的值,其行为便与by lazy {...}

相同