Kotlin SAM运行时错误:NoSuchMethodError:无静态方法

Kotlin SAM运行时错误:NoSuchMethodError:无静态方法,kotlin,Kotlin,今天,我在开发kotlin/android时遇到了一个非常奇怪的运行时错误,涉及SAM转换和子分类 下面是纯java+kotlin的一个简单示例。以下是两个java类: public class A { public interface I { public void f(); } public I i; } public class B extends A {} 这是kotlin的主要功能: fun main(args: Array<Stri

今天,我在开发kotlin/android时遇到了一个非常奇怪的运行时错误,涉及SAM转换和子分类

下面是纯java+kotlin的一个简单示例。以下是两个java类:

public class A {
    public interface I {
        public void f();
    }

    public I i;
}

public class B extends A {}
这是kotlin的主要功能:

fun main(args: Array<String>) {
    A().i = B.I {}
}
现在,这已经很糟糕了——如果这样的代码不起作用(我想永远不会),编译器应该会出错。但至少有人会说,通过子类
B
而不是定义位置
A
(即
A.I
)引用接口
I
是个坏主意

但不太清楚的是,如果此代码位于
B
的子类中,我可以直接使用
I
引用
I

class C: B {
    constructor() {
        this.i = I {}
    }
}
所以我的问题是:

  • 为什么会发生这种行为
  • 如果发生这种情况,为什么编译器还没有引发错误
  • PS:在安卓系统中,错误消息与此类似,更令人困惑:

    Caused by: java.lang.NoSuchMethodError: No static method OnFocusChangeListener(Lkotlin/jvm/functions/Function2;)Landroid/view/View$OnFocusChangeListener; in class Landroid/widget/LinearLayout; or its super classes (declaration of 'android.widget.LinearLayout' appears in /system/framework/framework.jar:classes2.dex)
    

    将主方法定义为静态方法,如-

    companion object {
        @JvmStatic fun main(args: Array<String>) {
            A().i = B.I {}
        }
    }
    
    伴生对象{
    @JvmStatic fun main(args:Array){
    A().i=B.i{}
    }
    }
    
    前端似乎将
    B.I{}
    识别为一个函数调用,lambda参数在括号外。我打赌这是假设失败的结果。验证器(或他们命名的任何东西)确实发现
    B.I
    表示通过JLS后面的某个名称注册表(允许通过子类型引用超类型静态成员)的有效SAM接口。编译器后端的名称系统不遵循JLS(因为kotlin没有static),但是没有找到
    B.java
    中声明的
    B.I
    ,因此它希望它是一个函数调用。不过这只是一个随机猜测。我猜测的结论是:编译器前端和后端对于是否允许通过子类型引用超类型静态成员有不同的策略。你应该在上提交一个问题。
    companion object {
        @JvmStatic fun main(args: Array<String>) {
            A().i = B.I {}
        }
    }