Kotlin : object、companion object、 @JvmField、 @JvmStatic、頂層函數(shù)、單例

object關(guān)鍵字主要有三種使用場景

  • 對象聲明(object declaration)
  • 伴生對象(companion object)
  • 對象表達(dá)式(object expression)

對象聲明(object declaration)

  1. 將類的聲明和定義該類的單例對象結(jié)合在一起(即通過object就實現(xiàn)了單例模式)
  2. 對象聲明中不能包含構(gòu)造器(包括主構(gòu)造器和次級構(gòu)造器)
Kotlin實現(xiàn)及調(diào)用
object KotlinTest {
    public var a = 0;
}

fun main() {
   var b = KotlinTest.a;
}
轉(zhuǎn)成Java及調(diào)用
public final class KotlinTest {
   @NotNull
   public static final KotlinTest INSTANCE;

   private KotlinTest() {
   }

   static {
      KotlinTest var0 = new KotlinTest();
      INSTANCE = var0;
   }
}
//java 調(diào)用
 public JavaTest() {
        int a = KotlinTest.INSTANCE.getA();

    }

Kotlin 中的 object 本質(zhì)上就是 Java 中簡單的單例模式,同時它的構(gòu)造方法是 private 的,因此 object 類不能自定義構(gòu)造方法!

伴生對象(companion object)

在 Kotlin 中是沒有 static 關(guān)鍵字的!想要實現(xiàn)通過 類名.xxx() 的方式調(diào)用工具方法,可以使用上述的 object 類,但 object 本身就是一個對象,我們無法在外部調(diào)用其構(gòu)造方法,既然想擁有 object 類(通過類名調(diào)用方法)與 class 類(外部可以調(diào)用構(gòu)造方法)的兩種特性,這時伴生對象 companion object 就完全可以滿足這個需求:

Kotlin實現(xiàn)及調(diào)用
class KotlinTest {
    companion object {
        var a = 0;
        fun test() {}
    }
    
    fun main() {
        val b: Int = KotlinTest.a;
    }
}
轉(zhuǎn)成Java及調(diào)用
public final class KotlinTest {
   private static int a;
   @NotNull
   public static final KotlinTest.Companion Companion = new KotlinTest.Companion((DefaultConstructorMarker)null); 
   public static final class Companion {
      public final int getA() {
         return KotlinTest.a;
      }

      public final void setA(int var1) {
         KotlinTest.a = var1;
      }
      public final void test() {
      }
      private Companion() {
      }

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

//java 調(diào)用
public class JavaTest {
    public JavaTest() {
        int a = KotlinTest.Companion.getA();
    }
}

Kotlin 中的 companion object 其實對應(yīng)到 Java 中也就只是 一個靜態(tài)內(nèi)部類實例而已。當(dāng)類中成員和伴生對象中成員重名的時候,類名調(diào)用的是伴生對象中的,實例調(diào)用的是類中的。

對象表達(dá)式(object expression)

對象表達(dá)式常用來作為匿名內(nèi)部類的實現(xiàn)

// 通過對象表達(dá)式實現(xiàn)點擊事件回調(diào)
btn.setOnClickListener(object : View.OnClickListener {
    override fun onClick(v: View) {
        TODO("Not yet implemented")
    }
})

@JvmField、 @JvmStatic

在對象聲明和伴生對象中,java代碼調(diào)用總會跟上INSTANCE或者Companion,Kotlin 中 的伴生對象本質(zhì)上就是靜態(tài)實例,如果想像kotlin代碼那樣直接調(diào)用,需要使用kotlin自帶的注解:@JvmStatic或者@JvmField

對于對象聲明
object KotlinTest {
    @JvmField
    var a = 0;
}

轉(zhuǎn)換的java代碼

public final class KotlinTest {
   @JvmField
   public static int a;
   @NotNull
   public static final KotlinTest INSTANCE;

   private KotlinTest() {
   }

   static {
      KotlinTest var0 = new KotlinTest();
      INSTANCE = var0;
   }
}

java代碼中在KotlinTest類中增加了靜態(tài)成員屬性

對于伴生對象
class KotlinTest {
    companion object {
        @JvmField
        public var a = 0;
        @JvmStatic
        fun test() {
            
        }
    }
}

轉(zhuǎn)換的java代碼

public final class KotlinTest {
   @JvmField
   public static int a;
   @NotNull
   public static final KotlinTest.Companion Companion = new KotlinTest.Companion((DefaultConstructorMarker)null);

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

   public static final class Companion {
      @JvmStatic
      public final void test() {
      }

      private Companion() {
      }

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

增加了對應(yīng)的 static 屬性和方法

頂層函數(shù)

fun print() {
    
}
class KotlinTest {
    
}

轉(zhuǎn)換成Java

public final class KotlinTest {
}

// KotlinTestKt.java
public final class KotlinTestKt {
   public static final void print() {
   }
}

在JVM中它會生成一個類,類的名字就是你的文件名加上Kt。這個文件中的所有頂層函數(shù)編譯為這個類的靜態(tài)函數(shù)。因此當(dāng)從Java中調(diào)用這個函數(shù)的時候和調(diào)用任何其他靜態(tài)函數(shù)一樣。

要修改包含kotlin頂層函數(shù)的生成的類的名稱,需要為這個文件添加@JvmName注解,將其放到文件開頭,位于包名前面

@file:JvmName("PrintUtils")
package com.utils
fun print() {

}
class KotlinTest {

}

轉(zhuǎn)換成Java

public final class KotlinTest {
}
// PrintUtils.java
package com.utils;

import kotlin.Metadata;
import kotlin.jvm.JvmName;
@JvmName(
   name = "PrintUtils"
)
public final class PrintUtils {
   public static final void print() {
   }
}

單例

class KotlinTest {
    private constructor() {

    }
    companion object {
        val instance:KotlinTest by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
           KotlinTest()
       }
    }
}
?著作權(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)容