為什么使用 Kotlin

Kotlin

1 JetBrains 親兒子,Google 干兒子

Kotlin 由大名鼎鼎的 JetBrains 開發(fā)維護(hù),并且得到了 Google 的官方認(rèn)可痢毒,可謂是 JetBrains 的親兒子,Google 的干兒子运怖,據(jù)說 Google 還在最新的 Android P 上,在虛擬機(jī)層對 Kotlin 進(jìn)行了專門的性能優(yōu)化。

2 Kotlin 和 Java 完全兼容

Kotlin 和 Java 一樣都是基于 JVM 的語言,所以他們倆其實(shí)就是親兄弟因谎,自然也不存在什么兼容性問題,Java 的 API 在 Kotlin 里會被自動轉(zhuǎn)換成 Kotlin 語法颜懊,反過來 Kotlin 的 API 在 Java 里也會自動轉(zhuǎn)換成 Kotlin 語法财岔,所以你完全不需要擔(dān)心什么兼容性問題。

關(guān)于兩個語言是如何相互轉(zhuǎn)換的河爹,我猜測都是通過字節(jié)碼進(jìn)行解析然后轉(zhuǎn)換的匠璧,僅僅是猜測而已。

3 跟 setter 和 getter 說再見

據(jù)說我們這輩子擼過最多的代碼是 setter 和 getter咸这?因為你得為數(shù)據(jù)封裝類的每一個字段寫 setter 和 getter夷恍,機(jī)智一點(diǎn)的會使用 IDE 生成代碼,而 Kotlin 則一句話就搞定了媳维。

比如我們要寫一個 Person 的數(shù)據(jù)封裝類酿雪,用 Java 的話我們會這樣寫:

public class Person {

    private String name;
    private String addr;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    public String getAddr() {
        return addr;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

}

這段 Java 代碼看起來是不是又臭又長,我們換 Kotlin 寫個 Person 類看看:

data class Person(var name: String, var addr: String, var age: Int)

什么侄刽!這就完了嗎指黎?沒錯這就完了,你需要的 setter 和 getter 方法 Kotlin 都已經(jīng)為你自動生成了州丹!

4 參數(shù)很多看著懵逼醋安?

如果一個方法有很多參數(shù),在調(diào)用的時候難免會出現(xiàn)看不出每個參數(shù)是什么意思的情況墓毒,尤其是傳遞數(shù)字的時候吓揪,比如我們有下面一個方法:

public Rectange createRectange(int x, int y, int width, int height) {}

我們在調(diào)用的時候這樣寫:

createRectangle(20, 30, 40, 50);

什么鬼!對 API 不熟悉的人根本沒辦法一眼看出這個方法調(diào)用傳遞的參數(shù)都是什么意思蚁鳖!我們換 Kotlin 寫個看看:

fun createRectangle(x: Int, y: Int, width: Int, height: Int) {}

Kotlin 允許我們在調(diào)用方法的時候顯式指定參數(shù)的名稱磺芭,如下所示:

createRectangle(x = 20, y = 30, width = 40, height = 50)

怎么樣赁炎!是不是看起來清晰多了醉箕,一眼就看出在坐標(biāo)為 (20, 30) 的位置創(chuàng)建一個寬 40,高 50 的矩形徙垫。

5 跟方法重載說再見

如果一個方法有 N 個參數(shù)讥裤,并且有些參數(shù)是可選的,你是不是要為它寫好幾個重載版本姻报,當(dāng)讓你也可以用 Builder 解決該問題己英,不管哪一種方式我都要多寫很多代碼啊吴旋!在 Kotlin 中你可以給每一個參數(shù)指定默認(rèn)值损肛,具有默認(rèn)值的參數(shù)可以在調(diào)用的時候選填厢破,是不是很爽!

我們來看下面這個 Java 方法:

public void foo() {
    foo(0, 0, 0)
}

public void foo(int a) {
    foo(a, 0, 0)
}

public void foo(int a, int b) {
    foo(a, b, 0)
}

public void foo(int a, int b, int c) {
    this.a = a;
    this.b = b;
    this.c = c;
}

再來看看 Kotlin 的寫法:

fun foo(a: Int = 0, b: Int = 0, c: Int = 0) {}

搞定了治拿!我們來看看這方法怎么調(diào)用:

foo()
foo(a = 1)
foo(b = 2)
foo(c = 3)
foo(a = 1, b = 2)
foo(a = 1, b = 2, c = 3)

6 用 as 代替 () 進(jìn)行類型轉(zhuǎn)換

如果你是 Android 開發(fā)者摩泪,相信你一定對 findViewById() 方法不陌生吧,在獲取每一個 View 的時候都需要進(jìn)行類型轉(zhuǎn)換劫谅,如下所示:

Button button = (Button) findViewById(R.id.button);
ImageView imageView = (ImageView) findViewById(R.id.image_view);

這樣的類型轉(zhuǎn)換方式本身沒什么問題见坑,但是 Kotlin 有更優(yōu)雅的類型轉(zhuǎn)換關(guān)鍵字 as

Button button = findViewById(R.id.button) as Button;
ImageView imageView = findViewById(R.id.image_view) as Button;

兩種方式比較起來,個人更喜歡 Kotlin 的方式捏检,原因如下:

  • as 代替 () 更加具有可讀性
  • 敲代碼的時候打 as 比打 () 更快ヾ(?`Д′?)

7 讓方法重寫或?qū)崿F(xiàn)更明顯

我們來看下面這段代碼:

public class A extends B {
  
    public void foo() {
      
    }
  
}

如果我告訴你 A 的 foo() 方法是重寫 B 的 foo() 方法荞驴,你會怎么想?反正我是想罵人了贯城,標(biāo)記重寫方法的 @Override 被狗吃了嗎熊楼?這樣的寫法雖然編譯器不會報錯,但是卻不利于代碼的閱讀能犯,很容易讓人誤以為 foo() 方法是 A 自己新定義的孙蒙。在 Kotlin 中則不允許你這樣寫,它要求你必須顯式聲明某一個方法是重寫父類或接口的:

class A: B() {

    override fun foo() {
    
    }
  
}

有了 override 這個關(guān)鍵字悲雳,我們一看就知道這是一個重寫的方法挎峦。

8 支持類的方法擴(kuò)展

Kotlin 支持對一類進(jìn)行方法擴(kuò)展,注意這個擴(kuò)展并不是通過繼承合瓢,也就是它可以擴(kuò)展一個 final 類坦胶。例如我們可以擴(kuò)展 String 類,添加一個 log(tag: String) 方法晴楔,讓它可以在日志系統(tǒng)里面輸出自己的內(nèi)容:

fun String.log(tag: String) {
    Log.d(tag, this)
}

然后我們就可以這么用:

val myString: String = 'test'
myString.log(TAG)

上面的 String 擴(kuò)展很無聊顿苇,我們來一個逼格高一些的,例如我們可以擴(kuò)展 SharedPreferences 類的 edit() 方法税弃,讓它支持更便捷的便捷方式:

fun SharedPreferences.edit(action: SharedPreferences.Editor.() -> Unit) {
    val editor = edit()
    action(editor)
    editor.apply()
}

然后我們就可以這么用:

val sp = getSharedPreferences("name",  Context.MODE_PRIVATE)
sp.edit({
    putInt("key1", 0)
    putLong("key2, 1)
    putString("key3", "value")
})

沒錯纪岁,你不需要調(diào)用 apply() 或者 commit() 方法,因為我們的擴(kuò)展方法里面做好了则果,你要做的就是存儲數(shù)據(jù)幔翰。

9 媽媽再也不用擔(dān)心我空指針了

空指針異常是我們經(jīng)常遇到的問題,為什么會出現(xiàn)空指針西壮?要嘛是忘記進(jìn)行判空處理遗增,要嘛就是忘記賦值。當(dāng)然在開發(fā)過程中可以使用 @Nullable 注解來對可能為空的變量或方法返回值進(jìn)行注解款青,但是這樣當(dāng)你沒有進(jìn)行判空的時候做修,也僅僅是收到 IDE 的一個警告信息而已,照樣能夠正常編譯。

在 Kotlin 的語法里饰及,你必須顯示聲明成員變量蔗坯、方法參數(shù)、方法返回值是否可以為空燎含,當(dāng)你在使用一個可能為空的成員變量時沒有進(jìn)行判空處理步悠,編譯器直接就會報錯,而不是形同虛設(shè)的警告瘫镇。下面是一段簡單的代碼鼎兽,通過 ? 關(guān)鍵字聲明成員變量 name 可能為空,然后我們在使用的時候必須判空:

var name: String? = null

if (name != null) {
    // do something
}

10 一句話實(shí)現(xiàn)單例模式

當(dāng)例模式是我們經(jīng)常用到的一個設(shè)計模式铣除,其目的就是為了讓全局只有一個對象實(shí)例谚咬,在 Java 里面我們會這么寫:

public class Singleton {
    public static final Singleton INSTANCE = new Singleton();
    private Singleton() {}
}

在 Kotlin 里面則更加簡單,只需要通關(guān)鍵字 object 就可以生命一個類為單例:

object Singleton {}

11 讓你的代碼僅在模塊內(nèi)可見

有過 SDK 開發(fā)經(jīng)驗的人應(yīng)該會遇到這樣一個問題尚粘,在開發(fā)過程中我們經(jīng)常會將類按照功能進(jìn)行分包择卦,例如 A 屬于com.xxx.pkga,B 屬于 com.xxx.pkgb郎嫁,但是我們又希望 A 的 foo() 方法可以被 B 訪問秉继,但是不被 SDK 之外的其他人訪問,這種情況在 Java 里面是無解的泽铛,要嘛你聲明 foo() 方法為 public尚辑,要嘛你把 A 和 B 放在一個包下,并聲明 foo() 方法為 default盔腔,但是這兩種做法都違背了我們的意愿杠茬。在 Kotlin 里面,專門提供了 internal 關(guān)鍵字弛随,用于聲明一個類或方法只有模塊內(nèi)部可見瓢喉,所謂的模塊在 Android Studio 里面就是一個 Gradle Module,而我們的 SDK 通常都是一個 Module舀透,這就完美解決了上面描述的問題了栓票。

12 比 // TODO 更狠的 TODO()

你是不是經(jīng)常寫了個 // TODO 注釋然后放在那邊幾百年不動它?好吧這不能怪你愕够,因為它只是一段注釋而已走贪,不會主動提示你“快來把我解決掉!”链烈,而 Kotlin 給我提供了一個更給力的方式 TODO() 方法厉斟,用它在代碼中標(biāo)記那些你日后會去處理的邏輯挚躯,并且當(dāng)你跑到這段沒有完成邏輯處理的代碼時强衡,TODO() 會這樣告訴你“來啊码荔!干掉我颁銮凇感挥!不然我就讓你崩潰!”

fun foo() {
    TODO("來霸桨堋触幼!干掉我啊究飞!不然我就讓你崩潰置谦!")
}

其內(nèi)部實(shí)現(xiàn)原理也很簡單,就是給你拋異常亿傅,但是起碼我不用自己寫啦媒峡,而且它默認(rèn)就是引入的:

/**
 * Always throws [NotImplementedError] stating that operation is not implemented.
 */
@kotlin.internal.InlineOnly
public inline fun TODO(): Nothing = throw NotImplementedError()

13 更加靈活的字符串定義

用 Java 拼接字符串是不是很惡心?比如我們要拼接一串 SQL 查詢語句葵擎,用 Java 會這么寫:

String table = ...
String id = ...
String email = ...
String age = ...
String sql = "SELECT * FROM " + table + " WHERE id=" + id + " AND name=" + name + " AND email=" + email + " AND age=" + age;  

使用一堆的 + 拼接起這個查詢語句谅阿,它的可讀性真是不敢恭維,而且寫起來也不方便酬滤,我們用 Kotlin 的字符串模板試試:

val table = ...
val id = ...
val email = ...
val age = ...
val sql = "SELECT * FROM $table WHERE id=$id AND name=$name AND email=$email AND age=$age"

在字符串中的 $table签餐、$id$name盯串、$email$age 會被自動替換為同名變量的值氯檐,再也不需要使用一堆 + 去拼接字符串啦,如果你想讓語句看起來更好看些体捏,可以這么寫:

val table = ...
val id = ...
val email = ...
val age = ...
val sql = """
          SELECT * FROM $table 
          WHERE id=$id 
          AND name=$name 
          AND email=$email 
          AND age=$age
          """

在 Kotlin 中字符串除了用 "字符串" 表示之外男摧,還可以用 """字符串""" 表示,這種方式讓你在定義字符串的時候隨意換行并且保留格式译打。

持續(xù)更新中...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耗拓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子奏司,更是在濱河造成了極大的恐慌乔询,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件韵洋,死亡現(xiàn)場離奇詭異竿刁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)搪缨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門食拜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人副编,你說我怎么就攤上這事负甸。” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵呻待,是天一觀的道長打月。 經(jīng)常有香客問我,道長蚕捉,這世上最難降的妖魔是什么奏篙? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮迫淹,結(jié)果婚禮上秘通,老公的妹妹穿的比我還像新娘。我一直安慰自己敛熬,他們只是感情好充易,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著荸型,像睡著了一般盹靴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瑞妇,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天稿静,我揣著相機(jī)與錄音,去河邊找鬼辕狰。 笑死改备,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔓倍。 我是一名探鬼主播悬钳,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼偶翅!你這毒婦竟也來了默勾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤聚谁,失蹤者是張志新(化名)和其女友劉穎母剥,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體形导,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡环疼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了朵耕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炫隶。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖阎曹,靈堂內(nèi)的尸體忽然破棺而出伪阶,到底是詐尸還是另有隱情煞檩,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布望门,位于F島的核電站形娇,受9級特大地震影響锰霜,放射性物質(zhì)發(fā)生泄漏筹误。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一癣缅、第九天 我趴在偏房一處隱蔽的房頂上張望厨剪。 院中可真熱鬧,春花似錦友存、人聲如沸祷膳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽直晨。三九已至,卻和暖如春膨俐,著一層夾襖步出監(jiān)牢的瞬間勇皇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工焚刺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敛摘,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓乳愉,卻偏偏與公主長得像兄淫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蔓姚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

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