Kotlin无法访问Java库的类,Java可以访问该类

  • 本文关键字:Java 访问 Kotlin kotlin
  • 更新时间 :
  • 英文 :


我对Kotlin比较陌生,最近开始将一些Java项目转换为Kotlin进行实践。我知道Java代码正在运行,但我在运行Kotlin端口时遇到了问题。Kotlin似乎无法像Java那样访问Java类。

我在Java库中有一个类,它看起来像这样:

package foo.bar.utils;
import java.util.List;
import java.util.ArrayList;
public class Foo {
private List<Bar> bars;
public Foo() {
bars = new ArrayList<>();
}
static public class Bar {
private Qux quxs;
public Qux getQuxs() {
return quxs;
}
public Bar setQuxs(final Qux quxs) {
this.quxs = quxs;
return this;
}
static class Qux {
@Override
public String toString() {
return "Qux []";
}
}
static public class QuxClass extends Qux {
private String id;
public String getId() {
return id;
}
public QuxClass setId(final String id) {
this.id = id;
return this;
}
}
}
}

工作的Java代码如下所示:

package com.example;
import foo.bar.utils.Foo;
public class JavaMain {
public static void main(String... args) {
Foo.Bar bar = new Foo.Bar();
Foo.Bar.QuxClass qux = new Foo.Bar.QuxClass();
bar.setQuxs(qux);
System.out.println(bar);
}
}

不工作的Kotlin代码如下所示:

package com.example
import foo.bar.utils.Foo
fun main() {
val bar = Foo.Bar()
val qux = Foo.Bar.QuxClass()
bar.quxs = qux
println(bar)
}

我省略了(我认为(没有必要重现这个问题的代码。

Kotlin代码实际上是编译的,但在运行时,它会抛出Exception in thread "main" java.lang.IllegalAccessError: tried to access class foo.bar.utils.Foo$Bar$Qux from class com.example.MainKt。当IntelliJ悬停在bar.quxs上时,会显示一个Type Foo.Bar.Qux! is inaccessible in this context due to: public/*package*/ open class Qux defined in foo.bar.utils.Foo.Bar的提示,但我很难理解这个提示。

一个可能的解决方案是将内部类Qux的可访问性更改为public。

我尝试了OpenJDK 12和AmazonCorretto 8,得到了相同的结果。

我还试图检查Kotlin和Java代码的反编译代码,但没有发现任何值得注意的差异。

调用setQux((也没有帮助。

有没有办法更改我的Kotlin代码以使端口运行?我真的很想了解科特林为什么会这样。

当您检查kotlin片段的JVM字节码时,问题很容易发现(使用常规字节码查看器,而不是Intellij中包含的查看器(。您的线路bar.quxs = qux变为:

aload0
aload1
checkcast foo/bar/utils/Foo$Bar$Qux
invokevirtual foo/bar/utils/Foo$Bar.setQuxs(Lfoo/bar/utils/Foo$Bar$Qux;)Lfoo/bar/utils/Foo$Bar;

或者表示为java代码:

bar.setQuxs((foo.bar.utils.Foo.Bar.Qux)qux);

JavaMain类的字节码不包括这个不必要的checkcast:

aload1
aload2
invokevirtual foo/bar/utils/Foo$Bar.setQuxs(Lfoo/bar/utils/Foo$Bar$Qux;)Lfoo/bar/utils/Foo$Bar;

我不能说为什么kotlin编译器会添加这个检查码。我倾向于将其归类为一个bug,或者至少是kotlin编译器中的意外行为,而没有简单的修复方法(除了修改库的代码(。

New关键字不用于在Kotlin中创建对象你像这个一样添加导入

import foo.bar.utils.Foo.Bar
import foo.bar.utils.Foo.Bar.QuxClass

然后创建类似的对象

val bar = Bar()
val qux = QuxClass()

最新更新