[kotlin]kotlin中的伴生對象(companion object)到底是個什么東西?

寫在前面

寫作不易,轉(zhuǎn)載注明出處:
https://blog.csdn.net/qq_34676644/article/details/119178392
或者我同步更新的簡書博客:
http://www.itdecent.cn/p/ddfed1df606c

相信初學(xué)kotlin的人,對與kotlin中的companion object會有疑惑,也有不少人將這個東西當(dāng)作java的靜態(tài)來使用,今天就來扒一扒到底什么是companion object

話不多說,直接上例子,注:以下測試基于kotlin 211-1.4.32-release-IJ7628.19版本

第一步,寫出kotlin代碼


class SingleInstance {

    companion object {
        var num1 = 10
        val num2 = 11

        @JvmStatic
        var num3 = 12

        @JvmStatic
        val num4 = 13

        fun test1() {
            println("test1")
        }

        @JvmStatic
        fun test2() {
            println("test2")
        }
    }
}

companion object中定義了2個變量:num1num3,兩個常量:num2,num4,同時定義了兩個方法:test1()test2()。其中:num3、num4test2()@JvmStatic修飾

第二步,轉(zhuǎn)成Java代碼

InterIj IDEA中的tools->Kotlin->show Kotlin Bytecode可以查看kotlin代碼的字節(jié)碼

kotlin字節(jié)碼

然后點擊字節(jié)碼右上角的Decompile可以將字節(jié)碼轉(zhuǎn)為java代碼,如圖
java代碼

第三步,查看java代碼

public final class SingleInstance {
   private static int num1 = 10;
   private static final int num2 = 11;
   private static int num3 = 12;
   private static final int num4 = 13;
   @NotNull
   public static final SingleInstance.Companion Companion = new SingleInstance.Companion((DefaultConstructorMarker)null);

   public static final int getNum3() {
      SingleInstance.Companion var10000 = Companion;
      return num3;
   }

   public static final void setNum3(int var0) {
      SingleInstance.Companion var10000 = Companion;
      num3 = var0;
   }

   public static final int getNum4() {
      SingleInstance.Companion var10000 = Companion;
      return num4;
   }

   @JvmStatic
   public static final void test2() {
      Companion.test2();
   }

   @Metadata(
      mv = {1, 4, 2},
      bv = {1, 0, 3},
      k = 1,
      d1 = {"\u0000\u001c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\b\n\u0002\b\u000e\n\u0002\u0010\u0002\n\u0002\b\u0002\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0012\u001a\u00020\u0013J\b\u0010\u0014\u001a\u00020\u0013H\u0007R\u001a\u0010\u0003\u001a\u00020\u0004X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u0005\u0010\u0006\"\u0004\b\u0007\u0010\bR\u0014\u0010\t\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\n\u0010\u0006R$\u0010\u000b\u001a\u00020\u00048\u0006@\u0006X\u0087\u000e¢\u0006\u0014\n\u0000\u0012\u0004\b\f\u0010\u0002\u001a\u0004\b\r\u0010\u0006\"\u0004\b\u000e\u0010\bR\u001c\u0010\u000f\u001a\u00020\u00048\u0006X\u0087D¢\u0006\u000e\n\u0000\u0012\u0004\b\u0010\u0010\u0002\u001a\u0004\b\u0011\u0010\u0006¨\u0006\u0015"},
      d2 = {"Ldesign_pattern/singleInstance/SingleInstance$Companion;", "", "()V", "num1", "", "getNum1", "()I", "setNum1", "(I)V", "num2", "getNum2", "num3", "getNum3$annotations", "getNum3", "setNum3", "num4", "getNum4$annotations", "getNum4", "test1", "", "test2", "leetcode2"}
   )
   public static final class Companion {
      public final int getNum1() {
         return SingleInstance.num1;
      }

      public final void setNum1(int var1) {
         SingleInstance.num1 = var1;
      }

      public final int getNum2() {
         return SingleInstance.num2;
      }

      /** @deprecated */
      // $FF: synthetic method
      @JvmStatic
      public static void getNum3$annotations() {
      }

      public final int getNum3() {
         return SingleInstance.num3;
      }

      public final void setNum3(int var1) {
         SingleInstance.num3 = var1;
      }

      /** @deprecated */
      // $FF: synthetic method
      @JvmStatic
      public static void getNum4$annotations() {
      }

      public final int getNum4() {
         return SingleInstance.num4;
      }

      public final void test1() {
         String var1 = "test1";
         boolean var2 = false;
         System.out.println(var1);
      }

      @JvmStatic
      public final void test2() {
         String var1 = "test2";
         boolean var2 = false;
         System.out.println(var1);
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}

第四步、得出結(jié)論

1.companion object的作用

使用 companion object會在原類中生成一個內(nèi)部類public static final class Companion,同時在原類中創(chuàng)建這個內(nèi)部類的對象 (這么看,伴生對象是不是就理解了)

2. 寫在companion object中的變量和方法

  • 變量全部定義在原類中,例如上面的kotlin代碼中的變量轉(zhuǎn)成java是:
   private static int num1 = 10;
   private static final int num2 = 11;
   private static int num3 = 12;
   private static final int num4 = 13;

并且會在內(nèi)部類中自動生成變量的get/set方法,val變量沒有set方法

      public final int getNum1() {
         return SingleInstance.num1;
      }

      public final void setNum1(int var1) {
         SingleInstance.num1 = var1;
      }

      public final int getNum2() {
         return SingleInstance.num2;
      }
...
  • 方法全部定義在內(nèi)部類中,修飾符是public final :
     public final void test1() {
         String var1 = "test1";
         boolean var2 = false;
         System.out.println(var1);
      }

      @JvmStatic
      public final void test2() {
         String var1 = "test2";
         boolean var2 = false;
         System.out.println(var1);
      }

3. 被@JvmStatic修飾的變量和方法

  • 變量:在原類中生成get/set靜態(tài)方法
    • 注意:此時原類內(nèi)部類都有該變量的get/set方法。
      • 區(qū)別:原類中的是靜態(tài)方法,內(nèi)部類中的是非靜態(tài)方法
      • 聯(lián)系:無
  • 方法:在原類中生成對應(yīng)的靜態(tài)方法
    • 注意:此時原類內(nèi)部類都有該方法
      • 區(qū)別:原類中的是靜態(tài)方法,內(nèi)部類中的是非靜態(tài)方法。
      • 聯(lián)系:在原類的靜態(tài)方法中調(diào)用了內(nèi)部類的非靜態(tài)方法
 @JvmStatic
   public static final void test2() {
      //Companion是內(nèi)部類的對象
      Companion.test2();
   }

以上測試基于kotlin 211-1.4.32-release-IJ7628.19版本

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容