KITCHEN DRINKER

主にAndroid開発メモとか

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は引数を指定しないと呼び出せないようになっています。

基礎的な話ですが、きちんと理解出来ていなかったので書きました。