關(guān)于Kotlin語法糖的階段性總結(jié)與思考

1. 引言

在Android應(yīng)用的開發(fā)語言上,是從Java再發(fā)展到Kotlin的十拣,所以Kotlin語言的開發(fā)習(xí)慣中不可避免會(huì)帶有Java的痕跡,所以很多關(guān)于Kotlin的語法糖的使用夭问,容易被忽略。而對(duì)于語法糖捧杉,有的人覺得很香,也有人覺得不值一提味抖,各有各想法灰粮。

此文,僅以表述個(gè)人對(duì)于Kotlin語法糖的一些優(yōu)勢(shì)總結(jié):

  • 使代碼更簡(jiǎn)潔專注
  • 使代碼更貼近閱讀習(xí)慣
  • 使代碼更具維護(hù)性
  • 使代碼更加安全

2. 使代碼更簡(jiǎn)潔專注

以啟動(dòng)線程執(zhí)行業(yè)務(wù)為例熔脂,

Java代碼:

new Thread() {
    @Override
    public void run() {
        System.out.println("hello");
    }
}.start();

Kotlin代碼可以照搬Java方式:

object : Thread() {
    override fun run() {
        println("hello")
    }
}.start()

Kotlin里啟動(dòng)線程還有另一種語法糖:

thread {
    println("hello")
}

特別注意:注意是thread而不是Thread,如果是后者其實(shí)調(diào)用了 Thread(Runnable target)的構(gòu)造方法霞揉。

不難看出晰骑,Kotlin里的這個(gè)語法糖非常簡(jiǎn)潔,可以使得開發(fā)者在無論在寫代碼還是代碼閱讀上秽荞,都只需要專注于線程中的執(zhí)行邏輯,而Java代碼則顯得繁瑣蚂会。

中間的Kotlin代碼以Java方式實(shí)現(xiàn),功能上沒有任何問題耗式,因?yàn)镴ava的代碼實(shí)現(xiàn)方式趁猴,在Kotlin中始終可以使用儡司。只不過這時(shí)候代碼結(jié)構(gòu)也與Java完全一致,相當(dāng)于吃了Kotlin語法卻沒吃到糖捕犬,不過既然吃語法酵镜,為何不吃糖?

或許有人疑惑垢粮,這種方式看似簡(jiǎn)潔了靠粪,但是如果只想創(chuàng)建線程,又不想立即啟動(dòng)占键,好像就不能這么寫了?

其實(shí)也可以:

val xThread = thread(start = false) {
    println("hello")
}

這樣便不會(huì)立即啟動(dòng)線程君仆,又拿到了線程對(duì)象的引用啸澡,自然可以根據(jù)需要在適當(dāng)?shù)臅r(shí)候再調(diào)用start()啟動(dòng)線程了氮帐。

其實(shí)嗅虏,Kotlin里的寫法之所以如此簡(jiǎn)潔而且又不局限皮服,是因?yàn)檫@里的thread是個(gè)函數(shù)参咙,聲明如下:

public fun thread(
    start: Boolean = true,
    isDaemon: Boolean = false,
    contextClassLoader: ClassLoader? = null,
    name: String? = null,
    priority: Int = -1,
    block: () -> Unit
): Thread

之所以Kotlin啟動(dòng)線程簡(jiǎn)潔且不局限蕴侧,其實(shí)是結(jié)合多種語法糖的綜合結(jié)果:函數(shù)缺省參數(shù)、函數(shù)類型净宵、拖尾的lambda表達(dá)式裹纳。

最后剃氧,放一起更直觀地對(duì)比Kotlin代碼中以Java方式實(shí)現(xiàn)以及語法糖方式實(shí)現(xiàn)的啟動(dòng)線程的區(qū)別:

object : Thread() {
    override fun run() {
        println("hello")
    }
}.start()

thread {
    println("hello")
}

不妨想想阻星,上下兩種方式,在代碼閱讀維護(hù)的時(shí)候滥酥,何種方式的代碼更好?

下面的語法糖果不重要么恨狈?確實(shí)不重要呛讲,因?yàn)榫退悴怀赃@個(gè)糖,Java方式的Kotlin代碼也可以實(shí)現(xiàn)贝搁,但是吃下這顆糖,可以使代碼更簡(jiǎn)潔專注啊弦讽,何樂而不為膀哲?

畢竟,是語法糖某宪,不甜的話,能叫糖么兴喂?

這里僅討論語法糖本身內(nèi)容,Kotlin中的函數(shù)類型設(shè)計(jì)不僅限于語法糖衣迷,更多內(nèi)容可參照:
函數(shù)類型壶谒,一個(gè)更好的選擇

3. 使代碼更貼近閱讀習(xí)慣

本節(jié)將以Java的靜態(tài)函數(shù)和Kotlin的拓展函數(shù)類作為對(duì)比。

以前Java代碼中让禀,經(jīng)常會(huì)這樣判斷一個(gè)字符串是否為null或空字符串:

if (TextUtils.isEmpty(str)) {
    System.out.println("str is null or empty");
}

在Kotlin中,可以這樣:

if (str.isNullOrEmpty()) {
    println("str is null or empty")
}

Java里的靜態(tài)函數(shù)和Kotlin里的拓展函數(shù)更直觀的對(duì)比:

TextUtils.isEmpty(str)  // Java靜態(tài)函數(shù)
str.isNullOrEmpty()     // Kotlin拓展函數(shù)

按照從左往右的閱讀習(xí)慣堆缘,拓展函數(shù)更符合閱讀習(xí)慣。

如上面例子的目標(biāo)其實(shí)是:判斷字符串是否為null或空字符串录平。

所以str.isNullOrEmpty() 更符合閱讀思維缀皱,從左到右閱讀出來的信息即為上述意義斗这,而Java中的TextUtils.isEmpty(str)一行從左到右閱讀起來則是文字工具中判斷是否為空方法函數(shù)調(diào)用,函數(shù)參數(shù)再傳入被判斷的字符串啤斗。

以前Java里是沒得選表箭,因?yàn)镴ava中沒有拓展函數(shù),所以要用靜態(tài)方法來實(shí)現(xiàn)钮莲;但Kotlin有拓展函數(shù)這個(gè)語法糖了免钻,所以可以用更符合閱讀習(xí)慣的方式進(jìn)行封裝和調(diào)用了。

簡(jiǎn)單作個(gè)類比崔拥,現(xiàn)金支付類比于Java靜態(tài)函數(shù)极舔、手機(jī)支付類比于Kotlin拓展函數(shù),有得選的情況下链瓦,相信大多數(shù)人會(huì)選擇手機(jī)支付(Kotlin拓展函數(shù))更為方便拆魏,但沒得選的情況下(商家不支持手機(jī)支付,類似于沒有Kotlin語言支持時(shí))慈俯,那么現(xiàn)金支付已足夠支持完成交易渤刃。

手機(jī)支付也好,現(xiàn)金支付也罷贴膘,本質(zhì)上都是貨幣交易的載體卖子;類似的Kotlin拓展函數(shù)也好,Java靜態(tài)函數(shù)也罷揪胃,本質(zhì)上都是JVM命令的編譯與執(zhí)行。

手機(jī)支付的存在并不是為了否定現(xiàn)金支付阳似,同理Kotlin拓展函數(shù)的存在也不是為了否定Java靜態(tài)函數(shù)的意義撮奏,只是Kotlin的拓展函數(shù)提供了更貼近閱讀習(xí)慣的使用方式泽疆。

4. 使代碼更具維護(hù)性

本節(jié)以Kotlin中的屬性訪問器(getter/setter)設(shè)計(jì)為例殉疼。

Java里關(guān)于屬性有下述經(jīng)典寫法:

public class JavaDemoBean {
    private String data;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}

假定需要對(duì)data數(shù)據(jù)統(tǒng)一增加后綴"@test",所以getData()里稍微改下:

public String getData() {
    return data + "@test";
}

但是眠砾,這里有個(gè)問題褒颈,因?yàn)轭悆?nèi)部是可以直接訪問私有的data數(shù)據(jù)的,所以類內(nèi)部直接訪問屬性data的地方都需要統(tǒng)一使用getData()才能達(dá)到效果淤井,而且后續(xù)新增代碼時(shí)扔直接訪問私有變量而造成額外的代碼評(píng)審和維護(hù)成本。

相對(duì)的漩绵,Kotlin中的getter/setter訪問器方法可解決上述情形的痛點(diǎn):

class KotlinDemoBean {
    var data = ""
        get() = "${field}@test"
}

這樣止吐,無論是類內(nèi)訪問還是類以外的地方調(diào)用,訪問屬性的時(shí)候都自動(dòng)加上了后綴不同,這樣就滿足了當(dāng)前需求:每次訪問數(shù)據(jù)值時(shí)都會(huì)給真實(shí)的數(shù)據(jù)值加上了相應(yīng)后綴服鹅。

更簡(jiǎn)潔,且更好維護(hù)澜倦。

注:內(nèi)存里儲(chǔ)存的對(duì)象仍將是不帶后綴的字符串藻治,只是每次讀取屬性時(shí)拼接了后綴桩卵,這時(shí)候?qū)傩缘哪缓笞侄卧趯傩栽L問器以外的地方將無法讀取。

這里稍微延展下钩乍,Java方式里寥粹,可以同時(shí)通過私有變量直接訪問到字段原本值和加上后綴的內(nèi)容,但是Kotlin的上述寫法則無法做到讀取字段原本值阔拳。其實(shí)Kotlin里要做到同時(shí)訪問兩者也可以,不過相對(duì)麻煩點(diǎn)货裹,這里用幕后屬性方式作為示例:

class KotlinDemoBean {
    private var _data: String = ""
    var data: String
        get() = "${_data}@test"
        set(value) {
            _data = value
        }
}

這樣的話,如果想訪問不帶后綴的屬性墓阀,則使用_data,想使用自動(dòng)加后綴的屬性,則使用data溢十。

如果不需要訪問原來值张弛,則是前面非常簡(jiǎn)潔的代碼,相對(duì)地刻剥,需求更多時(shí)再產(chǎn)生更多的代碼是合理的。

更多細(xì)節(jié):Kotlin在默認(rèn)情況下類外部調(diào)用屬性總是通過訪問器間接讀寫的,想要如Java那樣直接暴露Kotlin類的屬性字段而不需要訪問器函數(shù)封裝撵术,注解@JvmField 又是一種選擇嫩与。

總而言之埃篓,Kotlin的屬性訪問器語法糖設(shè)計(jì)同窘,只是在原來Java的基礎(chǔ)上裤纹,使得代碼維護(hù)性變得更好了呕童。

5. 使代碼更加安全

Kotlin與Java的差異中,空安全總是最為突出的一個(gè)點(diǎn)茫蛹,提供的語法糖也是最為繁雜的婴洼。

在Java中粉捻,關(guān)于判空杏头,一般會(huì)這樣寫:

public class JavaExample {

    private Dialog dialog;

    public void showDialog() {
        if (dialog != null) {
            dialog.setTitle("abc");
            dialog.show();
        }
    }
}

Kotlin中如果照搬Java寫法寓娩,則會(huì)出現(xiàn)下面這種代碼:

class KotlinExample {
    private var dialog: Dialog? = null

    fun showDialog() {
        if (dialog != null) {
            dialog!!.setTitle("abc")
            dialog!!.show()
        }
    }
}

注意,最后調(diào)用dialog的對(duì)象方法的時(shí)候缰犁,如果沒有操作符!!上述代碼將提示編譯錯(cuò)誤。

是不是很奇怪?為什么在調(diào)用方法前已經(jīng)進(jìn)行了判空蕴茴,為什么這里還是要加!!才能通過編譯?

其實(shí),不加!!時(shí)Android Studio已經(jīng)提示具體原因了:

1.png

簡(jiǎn)單來說糠雨,就是Kotlin檢測(cè)到在調(diào)用對(duì)象方法時(shí)dialog屬性可能已經(jīng)被改變才睹。

更具體的說,由于dialog是可空且是可變的解恰,所以可能在判空條件成立后,調(diào)用對(duì)象方法之前已經(jīng)被另一線程置空,所以即使進(jìn)行了判空后再調(diào)用對(duì)象方法羞酗,仍可能產(chǎn)生空指針。

所以卫枝,這時(shí)候在Kotlin里照搬Java的代碼風(fēng)格就顯得不合適了马篮。

Kotlin里正確的條件判空姿勢(shì)浑测,應(yīng)該是下面這種用法:

fun showDialog() {
    val curDialog = dialog
    if (curDialog != null) {
        curDialog.setTitle("abc")
        curDialog.show()
    }
}

本質(zhì)上是利用局部變量進(jìn)行判空夭委。

為什么對(duì)局部變量進(jìn)行判空有效而對(duì)成員變量進(jìn)行判空則仍編譯錯(cuò)誤厕氨?

這時(shí)候要提及JVM堆棧內(nèi)存的概念了进每,JVM中,堆內(nèi)存是所有線程共享的命斧,棧內(nèi)存僅為某線程運(yùn)行時(shí)所私有田晚,而所有對(duì)象都創(chuàng)建在堆內(nèi)存上,Java中的變量只是對(duì)象的一個(gè)引用(指針值)国葬,而類中的成員變量在堆內(nèi)存中分配贤徒,而局部變量則在棧變量分配,所以成員變量判空后再執(zhí)行對(duì)象方法時(shí)可能已經(jīng)被另一線程所置空汇四,而局部變量則沒有這種可能接奈。

這時(shí)候估計(jì)會(huì)有疑惑:代碼這里有沒有涉及多線程調(diào)用,為什么非要考慮到多線程的影響呢船殉?

Java里對(duì)于空安全是交于代碼運(yùn)行時(shí)的鲫趁,Kotlin對(duì)于空安全是交于編譯時(shí)的(除非使用!!)斯嚎,一個(gè)是出現(xiàn)問題再改利虫,一個(gè)是強(qiáng)迫在寫代碼的時(shí)候就去處理問題。既然Kotlin設(shè)計(jì)了空安全堡僻,那么還是得考慮多線程情況下的空安全糠惫。
注:Kotlin的空安全只是保證了多線程時(shí)不會(huì)觸發(fā)空指針異常,但是沒有保證數(shù)據(jù)在多線程條件下的一致性和同步性钉疫。

對(duì)于這種局部變量的判空方式硼讽,肯定是較為麻煩的,起名糾結(jié)癥患者甚至對(duì)此嗤之以鼻牲阁,所以又有下面這種語法糖寫法:

fun showDialog() {
    dialog?.setTitle("abc")
    dialog?.show()
}

看起來簡(jiǎn)潔又安全固阁,但卻不夠優(yōu)雅。

首先城菊,Kotlin中每個(gè)?操作符判空的背后备燃,都是一次對(duì)于局部變量的賦值與判空。

也就是凌唬,這里有兩次判空的命令執(zhí)行并齐。

更好的方式,是利用標(biāo)準(zhǔn)函數(shù)來優(yōu)化重復(fù)的判空操作:

比如用let

fun showDialog() {
    dialog?.let {
        it.setTitle("abc")
        it.show()
    }
}

這里個(gè)人更傾向于用run客税,因?yàn)閞un的單詞語義與上下文表意更貼切:

fun showDialog() {
    dialog?.run {
        setTitle("abc")
        show()
    }
}

兩者在此時(shí)本質(zhì)上都是在編譯時(shí)產(chǎn)生了一個(gè)局部變量進(jìn)行判空并調(diào)用况褪,原理上等同于上面的手寫局部變量條件判空的方式,只不過這時(shí)候更耻,局部變量名交予了編譯器產(chǎn)生测垛。

Kotlin的空安全語法糖,無論哪一種較之于Java復(fù)雜一些秧均,但是對(duì)于空指針確實(shí)更安全了食侮!

6. 關(guān)于對(duì)語法糖的思考

有人調(diào)侃脊奋,Kotlin一個(gè)最明顯的特點(diǎn)便是語法糖永遠(yuǎn)比Java多。

退一步說疙描,即使不用Kotlin的各種語法糖诚隙,按照J(rèn)ava的方式也基本可以實(shí)現(xiàn)功能,所以為什么要去過多糾結(jié)Kotlin設(shè)計(jì)的語法糖呢起胰?

這里借用魯迅先生的《孔乙己》中回字的四種寫法來作類比久又,一般慣以回字四種寫法嘲諷無用的知識(shí)和炫耀,然而把這件事剝開看效五,如果讀書人只會(huì)炫耀回字的四種寫法地消,那自然是無用知識(shí)。但是畏妖,如果能理解不同寫法的使用場(chǎng)景脉执、字體含義,在合適的前后文(字體戒劫、書函半夷、學(xué)科等)中正確地使用不同的回字,以達(dá)到更貼切迅细、更豐富的表達(dá)巫橄,這時(shí)候回字的不同寫法的知識(shí)一定程度上便是有意義的內(nèi)容。

只著眼于回字的四種寫法表面茵典,自然是無用知識(shí)湘换,魯迅先生借此諷刺的是封建制度對(duì)于讀書人的限制以及摧殘。

更多地统阿,只著眼于知識(shí)本身而忽略對(duì)于知識(shí)本身的理解彩倚,這種學(xué)習(xí)是否正確呢?

回到開發(fā)語言上扶平,只著眼于語法糖本身而去否定語法糖帆离,忽略對(duì)語法糖設(shè)計(jì)的理解,是否正確蜻直?

從Java轉(zhuǎn)戰(zhàn)Kotlin過程盯质,過于著眼于Kotlin的語法糖本身而忽略了語法糖設(shè)計(jì)帶來的變化和改進(jìn),忽略了對(duì)于Kotlin語言本身的設(shè)計(jì)的理解概而,是否正確呼巷?

這些問題,每個(gè)人有不同的思考赎瑰,這里也不是應(yīng)試教育不必追求標(biāo)準(zhǔn)答案王悍,本文也僅給出個(gè)人目前對(duì)于Kotlin語法糖的初步總結(jié):

  • 使代碼更簡(jiǎn)潔專注
  • 使代碼更貼近閱讀習(xí)慣
  • 使代碼更具維護(hù)性
  • 使代碼更加安全

這些內(nèi)容或許可以有更多的維度的解讀和理解,與語法糖本身相比餐曼,語法糖背后的思考與理解或許會(huì)更重要压储。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鲜漩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子集惋,更是在濱河造成了極大的恐慌孕似,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刮刑,死亡現(xiàn)場(chǎng)離奇詭異喉祭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)雷绢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門泛烙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翘紊,你說我怎么就攤上這事蔽氨。” “怎么了帆疟?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵鹉究,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我鸯匹,道長(zhǎng)坊饶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任殴蓬,我火速辦了婚禮,結(jié)果婚禮上蟋滴,老公的妹妹穿的比我還像新娘染厅。我一直安慰自己,他們只是感情好津函,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布肖粮。 她就那樣靜靜地躺著,像睡著了一般尔苦。 火紅的嫁衣襯著肌膚如雪涩馆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天允坚,我揣著相機(jī)與錄音魂那,去河邊找鬼。 笑死稠项,一個(gè)胖子當(dāng)著我的面吹牛涯雅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播展运,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼活逆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼精刷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔗候,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤怒允,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后锈遥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體误算,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年迷殿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了儿礼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庆寺,死狀恐怖蚊夫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情懦尝,我是刑警寧澤知纷,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站陵霉,受9級(jí)特大地震影響琅轧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜踊挠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一乍桂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧效床,春花似錦睹酌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至沪猴,卻和暖如春辐啄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背运嗜。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工壶辜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洗出。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓士复,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阱洪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一便贵、前言 使用kotlin開發(fā)項(xiàng)目已經(jīng)有一段時(shí)間,在使用kotlin的過程中冗荸,發(fā)現(xiàn)了許多很方便的語法糖承璃,可以有效簡(jiǎn)...
    bug喵喵閱讀 512評(píng)論 0 0
  • 一、前言 使用kotlin開發(fā)項(xiàng)目已經(jīng)有一段時(shí)間蚌本,在使用kotlin的過程中盔粹,發(fā)現(xiàn)了許多很方便的語法糖,可以有效簡(jiǎn)...
    冷江明閱讀 10,440評(píng)論 0 10
  • 最近基于gin嘗試寫了一套內(nèi)部使用的框架(如下)程癌,過程中有一些總結(jié)筆記在此記錄舷嗡。 1、打開連接如MySQL嵌莉,red...
    小馬過河R閱讀 321評(píng)論 36 6
  • Kotlin 是一個(gè)用于現(xiàn)代多平臺(tái)應(yīng)用的靜態(tài)編程語言进萄,由 JetBrains 開發(fā)(也就是開發(fā)了號(hào)稱Java界最智...
    wille_89閱讀 647評(píng)論 0 1
  • 在 2019 年 Google I/O 大會(huì)上,Google 宣布了今后 Android 開發(fā)將優(yōu)先使用 Kotl...
    4e70992f13e7閱讀 1,277評(píng)論 0 4