2020-06-09 kotlin之 @JvmOverloads 的作用

kotlin之 @JvmOverloads 的作用

@JvmOverloads 介紹

@Target([AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR]) annotation class JvmOverloads

Instructs the Kotlin compiler to generate overloads for this function that substitute default parameter values.
If a method has N parameters and M of which have default values, M overloads are generated: the first one takes N-1 parameters (all but the last one that takes a default value), the second takes N-2 parameters, and so on.
官網鏈接
以上就是kotlin官方對于kotlin @JvmOverloads 作用的解釋。
中文翻譯如下:
指示Kotlin編譯器為該函數生成替代默認參數值的重載。
如果一個方法有N個參數,其中M個參數有默認值,那么就會生成M個重載。:第一個方法有N-1個參數,第二個方法有N-2個參數,依此類推(除了最后一個方法都有默認值)。

加與不加@JvmOverloads對比

來段代碼對比下吧。
定義一個printPersonInfo方法,打印人物信息,我們可以看到有兩個參數是有默認值的。

不加@JvmOverloads

首先讓我們看看不加@JvmOverloads 的情況

fun printPersonInfo(age:Int=0,name:String,sex:String="男"){
    println("姓名:$name 年齡:$age  性別:$sex")
}
fun main() {
    printPersonInfo(name = "chl")
}

其對應的反編譯Java代碼如下

public static final void overloadTest(int age, @NotNull String name, @NotNull String sex) {
    Intrinsics.checkParameterIsNotNull(name, "name");
    Intrinsics.checkParameterIsNotNull(sex, "sex");
    String var3 = "姓名:" + name + " 年齡:" + age + "  性別:" + sex;
    boolean var4 = false;
    System.out.println(var3);
 }

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

    if ((var3 & 4) != 0) {
       var2 = "男";
    }

    overloadTest(var0, var1, var2);
 }
 
 public static final void main() {
      overloadTest$default(0, "chl", (String)null, 5, (Object)null);
   }

我們可以看到其對應的Java代碼是通過生成了一個 overloadTest$default方法,這個方法成為了外部調用的方法,在這個方法里面,進行了數據默認值的處理,然后再調用 overloadTest方法。

加@JvmOverloads

接下來我們再來看下加上@JvmOverloads注解的函數。

@JvmOverloads fun printPersonInfo(age:Int=0,name:String,sex:String="男"){
    println("姓名:$name 年齡:$age  性別:$sex")
}

對應Java代碼

@JvmOverloads
   public static final void printPersonInfo(int age, @NotNull String name, @NotNull String sex) {
      Intrinsics.checkParameterIsNotNull(name, "name");
      Intrinsics.checkParameterIsNotNull(sex, "sex");
      String var3 = "姓名:" + name + " 年齡:" + age + "  性別:" + sex;
      boolean var4 = false;
      System.out.println(var3);
   }

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

      if ((var3 & 4) != 0) {
         var2 = "男";
      }

      printPersonInfo(var0, var1, var2);
   }

   @JvmOverloads
   public static final void printPersonInfo(int age, @NotNull String name) {
      printPersonInfo$default(age, name, (String)null, 4, (Object)null);
   }

   @JvmOverloads
   public static final void printPersonInfo(@NotNull String name) {
      printPersonInfo$default(0, name, (String)null, 5, (Object)null);
   }

   public static final void main() {
      printPersonInfo$default(0, "chl", (String)null, 5, (Object)null);
   }

從以上代碼可以看到,@JvmOverloads 注解的函數,對應的Java文件生成了一個所有參數都有的方法外,還生成了2個重載方法,第一個2個參數,第二個 1個參數。而所有的邏輯都在那個有所有參數的方法中,其他的方法通過調用printPersonInfo$default來訪問該方法。

為什么用@JvmOverloads

通過以上代碼我們明白了 @JvmOverloads的作用,但是我們在使用kotlin編寫代碼時候。似乎@JvmOverloads對我們的編碼毫無影響,我們為什么要加上它呢?這其實主要是為了在java中調用kotlin代碼的時候能夠使用,如果不加 @JvmOverloads , 當我們想要在Java中調用kotlin的方法時,是必須輸入所有參數的值得,kotlin中默認參數我們無法使用。而當加上 @JvmOverloads ,kotlin編譯器生成的字節碼中有對應的重載方法,我們就可以通過Java的重載方式來使用kotlin的代碼了,不必要輸入所有的參數。

@JvmOverloads 使用范圍

kotlin中 構造函數、頂級函數、類中方法,靜態方法(@Jvmstatic修飾) 均可以采用@JvmOverloads生成對應重載方法。
在主構造函數使用重載函數,效果如下
kotlin代碼

class People @JvmOverloads constructor(age:Int=0,name:String,sex:String="男"){

}

java代碼

public final class People {
   @JvmOverloads
   public People(int age, @NotNull String name, @NotNull String sex) {
      Intrinsics.checkParameterIsNotNull(name, "name");
      Intrinsics.checkParameterIsNotNull(sex, "sex");
      super();
   }
   // $FF: synthetic method
   public People(int var1, String var2, String var3, int var4, DefaultConstructorMarker var5) {
      if ((var4 & 1) != 0) {
         var1 = 0;
      }
      if ((var4 & 4) != 0) {
         var3 = "男";
      }
      this(var1, var2, var3);
   }

   @JvmOverloads
   public People(int age, @NotNull String name) {
      this(age, name, (String)null, 4, (DefaultConstructorMarker)null);
   }
   @JvmOverloads
   public People(@NotNull String name) {
      this(0, name, (String)null, 5, (DefaultConstructorMarker)null);
   }
}

小結

本文主要講述了@JvmOverloads 關鍵字的作用,其對應java代碼中效果,以及為什么使用@JvmOverloads關鍵字,如有問題,還請批評指正!

原創聲明

作者:陳浩亮

鏈接:

  1. 掘金 kotlin之 @JvmOverloads 的作用
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。