gpt4 book ai didi

java - 为什么这是 val,而不是 val?

转载 作者:行者123 更新时间:2023-12-02 14:38:32 32 4
gpt4 key购买 nike

这个似乎依赖于 Java 和 Kotlin 之间的交互,首先是一个 Java 类:

public class MyJavaClass {
private Runnable q;

public void setRunnable(final Runnable listener) {
q = listener;
}

public boolean testContains(final Runnable listener) {
return q == listener;
}
}

现在 Kotlin 测试:

class JavaInteractionTests {

@Test
fun `anonymous`() {
val abc = object : Runnable {
override fun run() {

}
}

val x = MyJavaClass()

x.setRunnable(abc)
assertTrue(x.testContains(abc))
}

@Test
fun `lambda`() {
val abc = Runnable { }

val x = MyJavaClass()

x.setRunnable(abc)
assertTrue(x.testContains(abc))
}

@Test
fun `function`() {
val abc: () -> Unit = {}

val x = MyJavaClass()

x.setRunnable(abc)
assertTrue(x.testContains(abc))
}

}

最后一个测试失败,因此看起来我的 val 实际上并不是 val

错误或可解释的预期行为?

请注意,如果像这样在 Kotlin 中定义 Java 类,则最后一个测试不会编译:

class MyKtClass {
private var q: Runnable? = null

fun setRunnable(listener: Runnable) {
q = listener
}

fun testContains(listener: Runnable): Boolean {
return q === listener
}
}

(我在向Java类注册回调时注意到了这一切,稍后打算将其删除,但未能删除。回调是在第三个测试样式中定义的)

最佳答案

原因是,每次调用接受 Runnable 的 Java 函数并向其传递一个 Kotlin 函数 () -> Unit 时,都会生成一个 Runnable 是隐式创建的,用于包装该函数。

当您执行两次(x.setRunnable(abc)x.testContains(abc))时,这是两个不同的 Runnable > 彼此不相等,因此失败。

这就是SAM conversion在 Kotlin 中工作。基本上,这些调用相当于

val abc: () -> Unit = {}

val x = MyJavaClass()

x.setRunnable(Runnable(abc)) // one Runnable
assertTrue(x.testContains(Runnable(abc))) // another Runnable

此外,Kotlin does not support SAM conversions for functions that are defined in Kotlin ,这就是为什么当您在 Kotlin 中重写该类时您的测试无法编译的原因。原因是 Kotlin 已经有了函数类型,应该使用它们而不是 SAM 接口(interface)。因此,SAM 转换更像是 Java 互操作的一种手段,而不是完整的语言功能。

关于java - 为什么这是 val,而不是 val?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45372528/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com