kotlin 中的“=lazy”之间的“by lazy”有什么区别?

Zun*_*gTa 6 kotlin

我想知道 kotlin 中的“=lazy”之间的“by lazy”有什么区别

val host by lazy { ... }
Run Code Online (Sandbox Code Playgroud)
val host = lazy { ... }
Run Code Online (Sandbox Code Playgroud)

在我的安卓代码中

val host by lazy {
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
}
Run Code Online (Sandbox Code Playgroud)

成功了

但是这个代码

val host = lazy {
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
}
Run Code Online (Sandbox Code Playgroud)

失败了

Jan*_*son 11

val host by lazy { ... }
Run Code Online (Sandbox Code Playgroud)

这意味着 host 属性是由Kotlin 的惰性委托增强的属性。它的值只会在第一次访问时计算一次。以下调用仅返回第一次调用的缓存结果。

val host = lazy { ... }
Run Code Online (Sandbox Code Playgroud)

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

考虑以下示例:

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

fun main() {
    println(host)
    println(host.value)
    println(host)
}
Run Code Online (Sandbox Code Playgroud)

这里我们有一个懒惰的委托host。如果您尝试打印其值,您将得到:“惰性值尚未初始化。” 。但是一旦你访问它的值,它的行为就与by lazy {...}


Mic*_*ael 8

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

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

当您使用 时val foo by lazy { "bar" },您是在告诉编译器将任何 get 或 set 操作委托fooString.


如果我们有这个:

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

    val usingBy by lazy {
        "bar"
    }
}
Run Code Online (Sandbox Code Playgroud)

我们看一下相应的 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);
}
Run Code Online (Sandbox Code Playgroud)

因此,任何读取尝试usingBy都会给我们一个String,然后我们可以将其分配给另一个String变量。你不能用 来做到这一点usingAssign,因为它的类型是Lazy<String>