首页 文章

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

提问于
浏览
17

在Kotlin中查看此示例代码:

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

在将其反编译为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);
}

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

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

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

我有这个代码

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);
   }
}

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

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

fun main(args: Array<String>) {
    foo(baz = 2)
}

class Something {
    init {
        foo(baz = 2)
    }
}

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

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

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

这甚至没有任何意义 .

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

1 回答

  • 7

    根据this,目前它尚未使用,但保留用于稍后添加具有默认值的超级呼叫 .

    你可以在这里看到它:

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

    这将生成一个字节码到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);
          }
       }
    }
    

相关问题