当前位置: 首页 > 知识库问答 >
问题:

Kotlin不能访问Java库的类,而Java可以访问该类

巫马令
2023-03-14
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;
            }
        }
    }
}
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代码实际上是编译的,但在运行时,它在线程“main”java.lang.IllegalAccesserRor中抛出异常:试图从类com.example.mainkt访问类foo.bar.utils.foo$bar$qux。当悬停在bar.quxs上时,IntelliJ显示一个提示,提示键入foo.bar.qux!由于在foo.bar.utils.foo.bar中定义了:public/*package*/open class Qux,所以在此上下文中无法访问,但是我很难理解这个提示。

调用setQuxs()也没有帮助。

有没有办法改变我的Kotlin代码来让端口运行?我很想明白为什么Kotlin会这样做。

共有1个答案

胡越
2023-03-14

当您查看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;
 类似资料:
  • 问题内容: 与我的其他问题略相关:以下内容之间有什么区别: 同样,最后2个之间的差异是我最感兴趣的。 问题答案: 任何包中的类都可以访问公共类。 具有默认访问权限()的类仅对同一包中的其他类可见。 private和protected修饰符只能应用于内部类。 私有类仅对其封闭类以及同一封闭类中的其他内部类可见。 受保护的类对于同一包中的其他类以及扩展该封闭类的类都是可见的。

  • 问题内容: 是否可以从Java代码访问扩展功能? 我在Kotlin文件中定义了扩展功能。 (生成的)java类在哪里。现在,我想用普通的Java代码访问它: 但是,这不起作用。 IDE无法识别该方法,并且编译失败。 起作用的是与kotlin的静态函数一起使用: 通过使用我的IDE似乎已正确配置。 我从kotlin文档中搜索了整个Java互操作文件,并且在谷歌上搜索了很多,但是找不到。 我究竟做错了

  • 我正在尝试从Java切换到Kotlin。但我有很多遗留代码和第三方库。我看到,Java类中经常存在没有getter和setter的公共字段,这些字段必须从其他类访问。如果没有Kotlin代码中的getter,我如何访问Java类的公共字段?

  • 使用Kotlin 1.0.0版本(在IntelliJ 15中编译)。 当它试图编译引用基于Lombok的Pojo的代码(在IntelliJ或Gradle中)时,它给出错误“无法访问‘foo’:它在‘MyPojo’中是‘private’。这是真的,它们都是私有的,我的对象有@Value @Builder用于lombok注释。 我已经尝试专门调用getFoo(),但是它显示“getFoo的未解析引用”

  • 我已经在网上搜索了这个问题,并找到了许多线程,给出了一个接近我一直遭受的问题的解决方案。 我收到一个访问限制错误,如下所述:访问限制:由于对所需库/opt/java/jdk1.8.0_31/jre/lib/rt.jar的限制,无法访问类型JFrame 在我的代码中,JFrame和JPanel下面有红线 我在这些线程中执行了所需的操作,但问题是尚未解决的访问限制:由于对所需库JDK1.6.0\jre

  • 我知道如何访问私有变量,但我正在尝试测试以下类: ProcessStatusResult: 在我的测试中,我需要在ProcessStatusBody中获取ProcessStatus来验证它,但我不知道如何做到这一点。 有没有一种方法可以使用反射(或其他方法)来访问它,而不必仅仅为了测试而在ProcessStatusResult中添加getter?