为什么Kotlin函数使用默认参数会创建一个带有未使用参数的方法

Mib*_*bac 17 kotlin

在Kotlin中查看此示例代码:

fun foo(bar: Int = 0, baz: Int) {
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

在将其反编译为Java代码(工具 - > Kotlin - >显示Kotlin字节码 - >反编译)之后,我得到了以下代码

public static final void foo(int bar, int baz) {
}

// $FF: synthetic method
// $FF: bridge method
public static void foo$default(int var0, int var1, int var2, Object var3) {
  if ((var2 & 1) != 0) {
     var0 = 0;
  }

  foo(var0, var1);
}
Run Code Online (Sandbox Code Playgroud)

我注意到生成的Java方法有一个未使用的Object var3参数.

我有点认为它可能与类中的函数有关,但在反编译此代码时

class Foo {
    fun foo(bar: Int = 0, baz: Int) {
        /* ... */
    }
}
Run Code Online (Sandbox Code Playgroud)

我有这个代码

public final class Foo {
   public final void foo(int bar, int baz) {
   }

   // $FF: synthetic method
   // $FF: bridge method
   public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
      if ((var3 & 1) != 0) {
         var1 = 0;
      }

      var0.foo(var1, var2);
   }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Object参数仍未使用,只是坐在那里.在进行其他测试后,我注意到扩展方法的行为相同.默认参数为last(即fun foo(bar: Int, baz: Int = 0) {})时也是如此

我还做了一个基本测试来检查使用下面的代码调用该函数时设置的值是什么

fun main(args: Array<String>) {
    foo(baz = 2)
}
Run Code Online (Sandbox Code Playgroud)

class Something {
    init {
        foo(baz = 2)
    }
}
Run Code Online (Sandbox Code Playgroud)

反编译后,我得到以下代码

public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      foo$default(0, 2, 1, (Object)null);
}
Run Code Online (Sandbox Code Playgroud)

public final class Something {
   public Something() {
      FooKt.foo$default(0, 2, 1, (Object)null);
   }
}
Run Code Online (Sandbox Code Playgroud)

这甚至没有任何意义.

我的问题是:为什么Kotlin为具有默认参数的函数生成一个未使用的参数?这是一个错误吗?

fal*_*fal 7

根据,目前它是未使用,但被保留用于添加具有默认值后超级调用.

你可以在这里看到它:

open class Foo {
    open fun foo(bar: Int = 0, baz: Int) {
        /* ... */
    }
}

class Blah: Foo() {
    override fun foo(bar: Int, baz: Int) {
    }
}
Run Code Online (Sandbox Code Playgroud)

这将生成一个字节码到Java Foo:

public class Foo {
   public void foo(int bar, int baz) {
   }

   // $FF: synthetic method
   // $FF: bridge method
   public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
      if(var4 != null) {
         throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: foo");
      } else {
         if((var3 & 1) != 0) {
            var1 = 0;
         }

         var0.foo(var1, var2);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)