javaからkotlinのdefault引数付き関数呼び出しについて
javaからkotlin classのcompanion object
内の関数を呼び出すとき書き方が二つあると思います。
(例)HogeActivity.ktのcreateIntentをjavaから呼び出すとき
class HogeActivity { companion object { fun createIntent(context: Context) = Intent(context, HogeActivity::class.java) } // 以下略
①
java側にCompanion
をつけて呼び出す
HogeActivity.Companion.createIntent(getContext(), false);
②
kotlin側に@JvmOverloads
をつける
class HogeActivity { @JvmOverloads companion object { fun createIntent(context: Context) = Intent(context, HogeActivity::class.java) }
現在javaプロジェクトをkotlinに以降中なのですが一応100%kotlin目指しているので、 全部Kotlinに置き換わった時のことを考えて①の方を使った書き方で統一をしていました。
が、companion object内の関数がdefault引数を利用している場合 パターン②の書き方でないと呼び出せないことがわかりました。
というか超基礎的な話ですがcompanion object内かに関わらず、default引数を利用している場合はjava側に@JvmOverloads付けないとダメ🙅
@JvmOverloads fun test01(arg01: String = "AAA") { } fun test02(arg02: String = "BBB") { }
試しに上記関数をDecompileしてみます。
// test01をDecompile @JvmOverloads public final void test01(@NotNull String arg01) { Intrinsics.checkParameterIsNotNull(arg01, "arg01"); } @JvmOverloads public static void test01$default(UserProfileFragment var0, String var1, int var2, Object var3) { if((var2 & 1) != 0) { var1 = "AAA"; } var0.test01(var1); } @JvmOverloads public final void test01() { test01$default(this, (String)null, 1, (Object)null); }
@JvmOverloadsをつけてるtest01は引数なしのものが自動生成されているのがわかります。
// test02をDecompile public final void test02(@NotNull String arg02) { Intrinsics.checkParameterIsNotNull(arg02, "arg02"); } public static void test02$default(UserProfileFragment var0, String var1, int var2, Object var3) { if((var2 & 1) != 0) { var1 = "BBB"; } var0.test02(var1); }
一方test02は引数を指定しないと呼び出せないようになっています。
基礎的な話ですが、きちんと理解出来ていなかったので書きました。