記錄一下初學(xué)kotlin時(shí)的一些疑惑冤吨。
當(dāng)我們需要添加屬于類的常量或者方法時(shí)蒿柳,通常我們需要在java中使用static關(guān)鍵字,而kotlin中去掉了static并且沒有提供對應(yīng)得關(guān)鍵字漩蟆,那我們該如何在kotlin中實(shí)現(xiàn)呢垒探?
- companion伴生對象
- object class
- 擴(kuò)展函數(shù)
- 頂層方法和屬性等
實(shí)現(xiàn)的方式多種多樣,各自的使用場景是什么呢怠李?其實(shí)只要將相關(guān)的代碼和“翻譯”成對應(yīng)得java代碼或者看一下在java中如何調(diào)用對應(yīng)得kotlin屬性或者方法圾叼,就可以很清楚的看出來其使用場景了。
1. companion伴生對象
//kotlin實(shí)現(xiàn)代碼
class CompanionTest {
companion object {
const val TAG = "this is a static message"
fun testFunction() {}
}
}
//對應(yīng)的java代碼
public final class CompanionTest {
@NotNull
public static final String TAG = "this is a static message";
public static final Test.Companion Companion = new Test.Companion((DefaultConstructorMarker)null);
public static final class Companion {
public final void testFunction() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
可以看到在Java中companion其實(shí)是一個(gè)名為Companion的靜態(tài)內(nèi)部類捺癞,并且在外部類中生成一個(gè)該內(nèi)部類的實(shí)例夷蚊。在java中調(diào)用則用如下方式:
String test = Test.TAG;
CompanionTest.Companion.testFunction();
2. object關(guān)鍵字
//kotlin中的object實(shí)現(xiàn)
object ObjectTest {
const val TAG = "this is a static message"
fun testFunction() {}
}
//對應(yīng)的java代碼
public final class ObjectTest {
@NotNull
public static final String TAG = "this is a static message";
public static final ObjectTest INSTANCE;
public final void testFunction() {
}
static {
ObjectTest var0 = new ObjectTest();
INSTANCE = var0;
}
}
可以看到object的實(shí)現(xiàn)和java中的餓漢式單例是一致的,在類加載的時(shí)候即生成一個(gè)該類的實(shí)例翘簇。companion則是在類加載的時(shí)候?qū)崿F(xiàn)一個(gè)靜態(tài)內(nèi)部類的實(shí)例撬码,嚴(yán)格來說這兩種實(shí)現(xiàn)方法并不是java中的靜態(tài)方法。
String objectStr = ObjectTest.TAG;
ObjectTest.INSTANCE.testFunction();
3. 擴(kuò)展函數(shù)
//kotlin中的擴(kuò)展函數(shù)
fun String?.testFunction() {}
//對應(yīng)的java代碼
public final class ExtendTestKt {
public static final void testFunction(@Nullable String $receiver) {
}
}
擴(kuò)展方法和我們java中常用的static方法是比較相似的版保,只是會(huì)將調(diào)用的對象作為方法的參數(shù)呜笑。另外如果kotlin file會(huì)生成對應(yīng)得kotlinFileNameKT的class夫否,如果不想使用默認(rèn)的名字可以在kotlin中使用 @file:JvmName("StringUtil") 注解指定生成的類名。
//使用上面的注解后在java中調(diào)用該擴(kuò)展方法
StringUtil.testFunction("");
4.頂層函數(shù)和頂層屬性
//kotlin頂層函數(shù)和屬性
const val CONSTANT_STRING = "test string"
val VAL_STRING = "test string"
fun testFunction() {}
//對應(yīng)的java代碼
public final class TopTestKt {
@NotNull
public static final String CONSTANT_STRING = "test string";
@NotNull
private static final String VAL_STRING = "test string";
@NotNull
public static final String getVAL_STRING() {
return VAL_STRING;
}
public static final void testFunction() {
}
}
頂層函數(shù)的使用和java中類方法的定義是一模一樣的叫胁。
TopTestKt.getVAL_STRING();
String topStr = TopTestKt.CONSTANT_STRING;
TopTestKt.testFunction();
這里插入一個(gè)const的分析凰慈,可以看到加了const關(guān)鍵字會(huì)被編譯成public static final的常量,而不加的話則是private static final并且生成一個(gè)get方法供外部使用驼鹅。
另外const val必須是編譯時(shí)常量微谓,而val則沒有這個(gè)要求,如下圖
總結(jié)
對于常量的聲明输钩,幾種方法最后的效果都是一致的豺型。加上const更加符合java通常的寫法,并且可以減少不必要的方法买乃。
對于方法姻氨,如果想達(dá)到j(luò)ava中static function的效果,使用擴(kuò)展函數(shù)或者頂層函數(shù)更好剪验。使用companion會(huì)額外的生成內(nèi)部類對象肴焊,只有在確定需要使用單例時(shí)才使用object去實(shí)現(xiàn)。