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
Kotlin无法访问Java可以访问的Java库类_Kotlin - Fatal编程技术网

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

Kotlin无法访问Java可以访问的Java库类,kotlin,Kotlin,我对Kotlin比较陌生,最近开始将一些Java项目转换为Kotlin进行实践。我知道Java代码正在运行,但我在运行Kotlin端口时遇到了问题。Kotlin似乎不能像Java那样访问Java类 我在Java库中有一个类,看起来像这样: package foo.bar.utils; 导入java.util.List; 导入java.util.ArrayList; 公开课Foo{ 私人酒吧名单; 公共食物({ bars=新的ArrayList(); } 静态公共类栏{ 私人Qux-Qux; 公共

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

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

package foo.bar.utils;
导入java.util.List;
导入java.util.ArrayList;
公开课Foo{
私人酒吧名单;
公共食物({
bars=新的ArrayList();
}
静态公共类栏{
私人Qux-Qux;
公共Qux getQuxs(){
返回qux;
}
公共栏设置Qux(最终Qux){
this.quxs=quxs;
归还这个;
}
静态类Qux{
@凌驾
公共字符串toString(){
返回“Qux[]”;
}
}
静态公共类QuxClass扩展了Qux{
私有字符串id;
公共字符串getId(){
返回id;
}
公共QuxClass集合id(最终字符串id){
this.id=id;
归还这个;
}
}
}
}
工作的Java代码如下所示:

package.com.example;
导入foo.bar.utils.foo;
公共类JavaMain{
公共静态void main(字符串…参数){
Foo.Bar=新的Foo.Bar();
Foo.Bar.QuxClass qux=新的Foo.Bar.QuxClass();
bar.setQuxs(qux);
系统输出打印项次(巴);
}
}
非工作Kotlin代码如下所示:

package.com.example
导入foo.bar.utils.foo
主要内容(){
val bar=Foo.bar()
val qux=Foo.Bar.QuxClass()
bar.quxs=qux
println(bar)
}
我省略了(我相信)不需要重现这个问题的代码

Kotlin代码实际上是编译的,但在运行时,它在线程“main”java.lang.IllegalAccessError中抛出
异常:试图从类com.example.MainKt访问类foo.bar.utils.foo$bar$Qux
。 当将鼠标悬停在
bar.Qux
上时,IntelliJ会显示一个提示,提示
键入Foo.bar.Qux!由于在foo.bar.utils.foo.bar
中定义了:public/*package*/open class Qux,因此在此上下文中无法访问,但我在理解该提示时遇到困难

一个可能的修复方法是将内部类Qux的可访问性更改为public

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

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

调用setQuxs()也没有帮助

有没有办法修改我的Kotlin代码以使端口运行?
我真的很想理解为什么Kotlin会这样做。

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

import foo.bar.utils.Foo.Bar
import foo.bar.utils.Foo.Bar.QuxClass
然后创建类似

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

当您检查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类的字节码不包括以下不必要的校验:

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

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

当问题不包括在kotlin代码中时,为什么要提到
new
?(只在需要的Java代码中)为什么限定名不能和
import
ed名一样有效呢?但您在Kotlin函数中使用的是Java类。所以,即使类是java,它在Kotlin代码中使用的方式也是Kotlin方式,java和Kotlin/JVM类都被编译成java字节码;一旦编译,类就是一个类,它们之间几乎没有实际的区别。(互操作性是Kotlin的卖点之一:Java类可以使用Kotlin类,反之亦然,而不知道它们是从哪种语言编译的。)是的,在转换类文件之前有Kotlin语言规则。所以根据这些规则,这是回答你问题的一种方式。我看不出你的Kotlin代码有任何明显的错误;这正是我翻译Java的方式。如果这里没有人给出解释,我会看看它是否在bug报告网站上提到过(如果可能的话,可能会考虑提出一个问题)。