【问题标题】:Why Kotlin function with default parameters creates a method with unused parameter为什么带有默认参数的 Kotlin 函数会创建带有未使用参数的方法
【发布时间】:2017-09-03 15:06:29
【问题描述】:

在 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 参数仍未使用,只是坐在那里。 在其他测试中,我注意到扩展方法的行为相同。当默认参数是最后一个时也是如此(即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 会为具有默认参数的函数生成未使用的参数?它是一个错误吗?

【问题讨论】:

  • 当您的默认参数是最后一个时,您会得到什么?如fun foo(bar: Int, baz: Int = 0) {}
  • @Les 刚刚检查过。是一样的(即生成了奇怪的 Object var)
  • 有没有试过调用,看看java代码中传入的对象是什么?
  • @DPM 我刚刚做了一个基本测试(foo(baz = 2)),传递的参数是null。我也编辑了问题
  • 如果您只是出于好奇而问这个问题,最好在 Kotlin 论坛或 Slack 中提问。如果你想从 Java 调用一个带有默认参数的 Kotlin 函数,你应该用 @JvmOverloads 注解来注解它,这样编译器就会生成干净的重载方法,没有魔法参数。

标签: kotlin


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-03
    • 2012-08-01
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2011-07-18
    相关资源
    最近更新 更多