將 kotlin 編譯成 java
先來個題外話,我們?nèi)绾慰?kotlin 對應的 java 代碼,kotlin 最終還是要編譯成 java class 在 JVM 上運行的,有時我們的確是想看看用 kotlin 寫完的代碼編譯完了是什么樣子,這樣有助于我們理解 kotlin 語法
其實很簡單,AS tools 工具里面有提供
-
tools -> Show kotlin Bytecode
-
點擊 Decompile
ok ,這樣就行了
kotlin 實現(xiàn)靜態(tài)的方式
在 kotin 語言中其實沒有 java static 的這個概念,基本都是用一個靜態(tài)對象來模擬 class 的靜態(tài)屬性和方法,目前有4種實現(xiàn)方式:
- companion object - 伴隨對象,聲明單例的方式
- @JvmField + @JvmStatic 注解 - 使用注解標簽聲明 static 的部分
- object 單例 - 靜態(tài)單例其實和 companion object 類似
- const - 包內(nèi)唯一性,脫離類的束縛,kotlin 的特性,在 java 中會編譯生成一個 kotlin.kt 的文件專門對齊提供支持
companion object
companion object 伴隨對象這是我們在 kotlin 中最常用的方式了吧,在 companion object 里面我們即可以聲明屬性,也可以聲明方法,kotlin 中的調(diào)用方式感覺和 java 的 static 一樣,舉個例子看下面:
class BookKotlin {
var name: String = "AA"
fun speak() {}
companion object instance {
var nameStatic: String = "BB"
fun speakStatic() {}
}
}


看上面圖,我們在 kotlin 中使用時感覺的確是和 java 中的 static 一樣,靜態(tài)參數(shù)方法和成員參數(shù)方法能有效區(qū)別開來,下面我們來看看 java 中使用



kotlin 的使用 ok ,但是一到 java 上就全變了,為啥,因為 kotlin 最終也是會編譯成 java 文件去 JVM 運行的,kotlin 并沒有提供自己特有的 VM ,所以kotlin 代碼還是要轉(zhuǎn)換成 java 代碼的,要不 kotlin 怎么宣傳 kotlin 和 java 可以實現(xiàn)無縫調(diào)用
kotlin 中所有的成員變量,不管是不是 static 的都有 get/set 方法,另外 kotlin 并沒有把我們聲明的靜態(tài)參數(shù)和方法聲明成 static 的,而是通過 instance 這個靜態(tài)對象中轉(zhuǎn)使用的,這就讓我們迷惑了,kotlin 變成成 java 之后到底上啥樣的,會不會和我們的初衷不同,影響我們使用
instance 這個靜態(tài)對象的名字是采用 companion object 后面跟的名字,可以不寫,不寫的話默認就是 INSTANCE(版本不同會有變化)
下面我們把 kotlin 轉(zhuǎn)換成 java 代碼來一探究竟
public final class BookKotlin {
private static String nameStatic = "BB";
public static final BookKotlin.instance instance = new BookKotlin.instance((DefaultConstructorMarker)null);
private String name = "AA";
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public final void speak() {
}
public static final class instance {
@NotNull
public final String getNameStatic() {
return BookKotlin.nameStatic;
}
public final void setNameStatic(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
BookKotlin.nameStatic = var1;
}
public final void speakStatic() {
}
private instance() {
}
// $FF: synthetic method
public instance(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
看到 java 代碼后,大家都徹底清楚了吧, companion object 伴隨對象真不是白叫的,真的是個對象,在 class 內(nèi)部添加一個 static final class 的靜態(tài)內(nèi)部類實現(xiàn)對象來模擬 static 特性
@JvmField + @JvmStatic 注解
上面我們見識了 companion object 伴隨對象,那么 kotlin 是不是真的無法實現(xiàn) static 了,也不是,kotlin 還是提供了相關辦法,這就是 @JvmField + @JvmStatic 注解,其意思是聲明成員和方法使用 JVM 提供的特性
- @JvmField - 修飾靜態(tài)變量
- @JvmStatic - 修飾靜態(tài)方法
- @JvmField 和 @JvmStatic 只能寫在 object 修飾的類或者 companion object 里,寫法雖然有些別扭,但是效果是真的是按 static 來實現(xiàn)的
我們把上面的代碼修改下:
class BookKotlin {
companion object {
@JvmField
var nameStatic: String = "BB"
@JvmStatic
fun speakStatic() {
}
}
var name: String = "AA"
fun speak() {}
}




public final class BookKotlin {
@JvmField
public static String nameStatic = "BB";
@JvmStatic
public static final void speakStatic() {
Companion.speakStatic();
}
public static final BookKotlin.Companion Companion = new BookKotlin.Companion((DefaultConstructorMarker)null);
private String name = "AA";
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public final void speak() {
}
public static final class Companion {
@JvmStatic
public final void speakStatic() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
object 單例
kotlin 自身提供了一種單例實現(xiàn)方式:object ,直接用來修飾 class ,用 object 修飾的類不能 new 對象,只能使用 object 提供的單例
object BookKotlin {
var name: String = "AA"
fun speak() {}
}




public final class BookKotlin {
private static String name;
public static final BookKotlin INSTANCE;
public final String getName() {
return name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
name = var1;
}
public final void speak() {
}
static {
BookKotlin var0 = new BookKotlin();
INSTANCE = var0;
name = "AA";
}
}
雖然 name 是 static 的了,但還是 private 私有的,還是得通過靜態(tài)單例來中轉(zhuǎn)調(diào)用,真的是單例
const
const 寫在 class 外面,效果 = @JvmField,但是不能修飾方法,也不能和 @JvmField 混用,一般就是用來聲明常用值的,用處不多,而且只能用 val ,var 不行,想要修飾方法的話,不寫 const 就行
const val name: String = "AA"
fun adk(){}
class BookKotlin {
fun speak() {}
}
kotlin 中使用如下:
kotlin 沒有包的概念,所以直接用,注意這么寫其實已經(jīng)相當于脫離了類的范圍,一個包的范圍內(nèi)不能重名的



這個 BookKotlinKt 文件就是為了專門支持這個 kotlin 特性而生成的輔助類,java 中我們是通過這個類來調(diào)用 const 聲明的內(nèi)容的,為啥要有這個類呢,因為 java 是有包這個概念的,所有的文件必須要有統(tǒng)一的地址規(guī)范,所以 kotlin 層面只能是提供 XXXKt 文件來單獨支持了,其實這已經(jīng)脫離了 java 范圍
public final class BookKotlin {
public final void speak() {
}
}
public final class BookKotlinKt {
@NotNull
public static final String name = "AA";
public static final void adk() {
}
}
在 java 代碼中是以 kotlin 輔助類存在的,這樣用的人真的是非常少,限制太大

