是否可以从Java代码访问扩展函数?
我在Kotlin文件中定义了扩展函数。
package com.test.extensions
import com.test.model.MyModel
/**
*
*/
public fun MyModel.bar(): Int {
return this.name.length()
}
其中MyModel是一个(生成的)java类。
现在,我想在我的正常java代码中访问它:
MyModel model = new MyModel();
model.bar();
然而,这并不奏效。IDE无法识别bar()方法,编译失败。
有效的方法是使用kotlin中的静态函数:
public fun bar(): Int {
return 2*2
}
通过使用import com.test.extensions.ExtensionsPackage,这样我的IDE似乎配置正确。
我从kotlin文档中搜索了整个Java-interop文件,也搜索了很多,但我没有找到它。
我做错了什么?这可能吗?
当你像这样扩展一个类时:
fun String.concatenatedLength(str: String): Int {
return (this.length + str.length)
}
fun f() {
var len = "one string".concatenatedLength("another string")
println(len)
}
它将编译为:
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class ExampleKt {
public static final int concatenatedLength(@NotNull String $receiver, @NotNull String str) {
Intrinsics.checkParameterIsNotNull((Object) $receiver, (String) "$receiver");
Intrinsics.checkParameterIsNotNull((Object) str, (String) "str");
return $receiver.length() + str.length();
}
public static final void f() {
int len = ExampleKt.concatenatedLength("one string", "another string");
System.out.println(len);
}
}
这里还有更多的例子。
您总是可以看到从您的Kotlin代码生成的实际Java代码,通过转到Tools > Kotlin > Show Kotlin Bytecode,然后单击反编译。这可以极大地帮助你。在您的情况下,如果使用MyModelExtensions.kt, Java代码将如下所示
public final class MyModelExtensionsKt {
public static final int bar(@NotNull MyModel $receiver) {
Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
return $receiver.getName().length();
}
}
你可以通过在包含bar的文件上使用@JvmName来改进:
@file:JvmName("MyModels")
package io.sspinc.datahub.transformation
public fun MyModel.bar(): Int {
return this.name.length
}
结果是这样的代码:
public final class MyModels {
public static final int bar(@NotNull MyModel $receiver) {
Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
return $receiver.getName().length();
}
}
使用MyModels符合Effective Java对实用程序类的建议。你也可以像这样重命名你的方法:
public fun MyModel.extractBar(): Int {
return this.name.length
}
那么从Java的角度来看,它看起来是惯用的:
MyModels.extractBar(model);
当你像这样扩展一个类时:
fun String.concatenatedLength(str: String): Int {
return (this.length + str.length)
}
fun f() {
var len = "one string".concatenatedLength("another string")
println(len)
}
它将编译为:
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class ExampleKt {
public static final int concatenatedLength(@NotNull String $receiver, @NotNull String str) {
Intrinsics.checkParameterIsNotNull((Object) $receiver, (String) "$receiver");
Intrinsics.checkParameterIsNotNull((Object) str, (String) "str");
return $receiver.length() + str.length();
}
public static final void f() {
int len = ExampleKt.concatenatedLength("one string", "another string");
System.out.println(len);
}
}
这里还有更多的例子。
使用更新的KotlinEx,您可以直接在java中调用扩展
ExtensionFileName.foo(field1...)
基本上,它所做的是,让接收者作为第一个参数,其他参数保持在相同的位置
所以For。
你有extension(在extension .kt文件中)
Context.showToast(message:String){
...
}
在Java中,称之为as
ExtensionKt.showToast(context, message);