为什么Kotlin反编译器会生成null.INSTANCE

时间:2018-11-20 01:23:36

标签: kotlin jvm-bytecode

我试图通过检查Java方面的外观来了解Kotlin的一些功能。

因此,作为实验,我尝试了以下方法:

val printKotlin = fun () {
    print("Hello Kotlin")
}

因此上述代码段的输出为:

public final class FunAsVariableKt {
    private static final Function0 printKotlin;

    public static final Function0 getPrintKotlin() {
        return printKotlin;
    }

    static {
        printKotlin = (Function0)null.INSTANCE;
    }
}

我如何理解上述反编译代码的静态块?为什么会生成此无效代码?

2 个答案:

答案 0 :(得分:6)

使用Kotlin字节码检查器查看以JVM字节码形式生成的内容,而不是尝试将字节码反编译为Java,这可能不适用于其他语言编译器生成的代码,因为它可能未遵循预期的模式。字节码反编译器并不总是生成工作代码。

  

JVM字节码!= Java语言特定

     

Kotlin生成的JVM字节码!= Java生成的JVM字节码

您看到的NULL实例是反编译器的错误解释,您可以看到字节码中对str.gsub(/({{2,3}\s*)([^{}]*)(\s*}{2,3})/) { |_| $~[1]+Base64.urlsafe_encode64($~[2].strip, padding: false)+$~[3] } 的所有引用都正确地设置了值。

这是实际输出:

INSTANCE

答案 1 :(得分:0)

您可以为此使用JD-GUI。

http://java-decompiler.github.io/

与内置的IntelliJ反编译插件相比,这对我来说效果更好。您只需要将* .class文件提供给它即可。

科林代码

//TryingOutLamdas.kt

class TryingOutLambdas {

    public fun performSomething()
    {
        takingAOnclickListener { x -> print("Hello $x").toString() }
    }
    
    fun takingAOnclickListener(onClickListener: (Int) -> (String))
    {
        onClickListener.invoke(6)
    }

} 

使用JD-GUI为此进行了转换的字节码。

public final class TryingOutLambdas {


    public final void performSomething() {
        
       takingAOnclickListener(TryingOutLambdas$performSomething$1
        .INSTANCE);
    }

    public final void takingAOnclickListener(@NotNull Function1 onClickListener) {
        Intrinsics.checkParameterIsNotNull(onClickListener, "onClickListener");
        onClickListener.invoke(Integer.valueOf(6));
    }

    static final class TryingOutLambdas$performSomething$1 extends Lambda implements Function1<Integer, String> {
        public static final TryingOutLambdas$performSomething$1 INSTANCE = new TryingOutLambdas$performSomething$1();
        
        @NotNull
        public final String invoke(int x) {
          String str = "Hello " + x;
          boolean bool = false;
          System.out.print(str);
          return Unit.INSTANCE.toString();
        }
        
        TryingOutLambdas$performSomething$1() {
          super(1);
        }
    } 

} 

如果lambda表达式从其声明的函数访问任何变量,则将创建一个实现该接口的新对象,而不是创建上面创建的Singleton实例。