Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Kotlin方法重载_Java_Kotlin_Overloading_Java Interop - Fatal编程技术网

Java Kotlin方法重载

Java Kotlin方法重载,java,kotlin,overloading,java-interop,Java,Kotlin,Overloading,Java Interop,以下声明在科特林是合法的 fun foo(): String = "foo_1" fun <T> foo(): T = "foo_2" as T 模棱两可的电话。两种方法都匹配 如何避免这样的问题?如何处理这些方法?如果第三方kt图书馆也有同样的问题呢 上面的例子是一个合成的例子 从java调用代码时,您可以使用来区分代码: @JvmName("fooString") fun foo(): String = "foo_1" fun <T> foo(): T = "fo

以下声明在科特林是合法的

fun foo(): String = "foo_1"
fun <T> foo(): T = "foo_2" as T
模棱两可的电话。两种方法都匹配

如何避免这样的问题?如何处理这些方法?如果第三方kt图书馆也有同样的问题呢

上面的例子是一个合成的例子

从java调用代码时,您可以使用来区分代码:

@JvmName("fooString")
fun foo(): String = "foo_1"

fun <T> foo(): T = "foo_2" as T
@JvmName(“fooString”)
fun foo():String=“foo_1”
fun foo():T=“foo_2”作为T
这将允许在Java中使用
ClassKt.fooString()
调用String方法,从而解决冲突。

为什么要从Kotlin开始。。。在Java中,有两种方法,如:

private static String test() {
    return "";
}

private static <T> T test() {
    return null;
}
private静态字符串测试(){
返回“”;
}
专用静态T检验(){
返回null;
}
将导致编译时错误。对于java开发人员来说,这是显而易见的,这些方法将具有相同类型的擦除。但这是由
javac
强加的规则,而不是由运行此代码的
JVM
强加的规则。因此
javac
不会将两个方法视为仅具有不同返回类型的重载。嗯,
kotlin
是一种不同的语言,因为它在
JVM
上运行(需要有效的字节码),所以它允许将返回类型不同的方法作为重载处理。我还没有看到字节码并理解它是如何发生的;这似乎只适用于泛型代码,所以类型擦除在kotlin的情况下略有不同

现在,从java调用这样的方法失败的原因应该很明显了。Kotlin为此提供了一个简洁的解决方案:
@JvmName(“someDistinctName”)
。我也不完全确定这在引擎盖下是如何工作的。。。然而,尽管我认为这将创建一个桥接方法

编辑


@JvmName
将在字节码级别重命名该方法

一个简单的解决方案是在Kotlin中编写一个helper方法并调用它


另一种仅使用Java的方法是为这两种方法获取
MethodHandle
,并使用它们:

MethodHandle MH_fooString = lookup().findStatic(ClassKt.class, "foo", methodType(String.class));
MethodHandle MH_fooT = lookup().findStatic(ClassKt.class, "foo", methodType(Object.class));

String foo = (String) MH_fooString.invokeExact();

但这并不简单,需要处理异常。

最后一部分很简单:当第三方库这样做时,您可以编写一个缺陷并要求他们解决问题:-)。。除此之外,可能的答案是:不要像这样让你的方法过载。是的,这是有意义的。我知道语言级别和vm字节码级别有不同的“限制”。但是,在这种情况下,100%的互操作性在哪里呢?我从一个更复杂的例子中得到了这个例子。如果我们将
suspend
修饰符添加到两个kotlin方法中,字节码将变得更加有趣。如果您感兴趣,我给出了一个示例,其中也强调了其中的一些内容(以及一些链接,您可以如何在Java中使用类似的内容)。还有其他一些东西不是100%兼容的,但反过来说,例如,尝试。@SergeyRybalkin不完全确定在这种情况下,当你说100%互操作在哪里时,我是否理解了你的意思?。你到底是什么意思?而且比通常的方法要慢invocation@Eugene我认为如果将MethodHandles存储在静态final字段中,不会有任何显著的性能差异。优化应该不是很难。这几乎是一个反射调用,它存储在哪里并不重要,与普通方法调用相比,它应该是重要的。@Eugene这与反射调用不同,因为该方法静态已知,并且可以通过JIT进行优化。经过足够的热身,在一个简单的测试中,我只能看到两者之间的差异<1%。不管怎样,我都怀疑在这种特殊情况下的表现是否重要。
private static String test() {
    return "";
}

private static <T> T test() {
    return null;
}
MethodHandle MH_fooString = lookup().findStatic(ClassKt.class, "foo", methodType(String.class));
MethodHandle MH_fooT = lookup().findStatic(ClassKt.class, "foo", methodType(Object.class));

String foo = (String) MH_fooString.invokeExact();