Kotlin簡介
歡迎來到 Kotlin 的神秘世界,Kotlin? 嗯,沒錯就是它! 也許你僅僅是聽過它還沒開始嘗試; 也許你嘗試過它但是放棄了; 也許你正在使用它遇到了一些些問題,也許你很喜歡它并且把它使用得如火純青了。不管你現(xiàn)在是處于哪個(gè)階段,我都希望你能從本教程中得到一些有用的東西。
本教程不打算按照書本上那樣平鋪直序闡述,而是帶著問題和目的性展開,每個(gè)語法點(diǎn)主要都圍繞著為什么使用它、它是什么、它是如何使用的、它的應(yīng)用場景此外最后還會帶你了解它語法糖背后的原理。因?yàn)?Kotlin 是一個(gè)門非常講究實(shí)用主義的編程語言,所以一定是要用于解決實(shí)際的場景問題,或者相比現(xiàn)有的語言(比如 Java)它如何更高效解決實(shí)際問題。每節(jié)教程都會留有一個(gè)對應(yīng)的語法練習(xí),下一節(jié)會公布上一節(jié)的答案。
最后,歡迎一起努力來到 Kotlin 世界探險(xiǎn),一起領(lǐng)悟這門語言背后的設(shè)計(jì)哲學(xué)和實(shí)用價(jià)值。
1. Kotlin 是什么?
Kotlin 是一門用于現(xiàn)代多平臺應(yīng)用的靜態(tài)編程語言,其中被廣泛用于 Android 平臺的開發(fā),被稱之為Android 世界的 Swift。它由大名鼎鼎的 JetBrains 公司設(shè)計(jì)開發(fā)并開源,著名的 IDE 工具 IntelliJ IDEA 就是他們的產(chǎn)品,所以無疑他們是對編程語言設(shè)計(jì)領(lǐng)域最為熟悉的專家。
Kotlin 從 2016 年發(fā)布 1.0 的 release 版本開始至今,使用的開發(fā)者數(shù)量快速增長。
此外 Kotlin 已經(jīng)擁有強(qiáng)大的生態(tài)和社區(qū)開發(fā)者的支持:
- Kotlin 是著名的 IDE 廠商 JetBrains 公司開發(fā)的編程語言;
- 在 Google I/O 2017中,Google 宣布在 Android 上為 Kotlin 提供最佳支持;
- Kotlin 在 Spring5.0 后端開發(fā)框架中的支持;
- Kotlin DSL 1.0 將在 Gradle5.0 得以應(yīng)用,Kotlin 成為繼 Groovy 語言開發(fā) Gradle 另一門編程語言;
- Kotlin 成為 2018 年 Github 中增長速度最快的語言;
- 2018年10月,Google 和 JetBrains 在 KotlinConf18 上公開宣布了 Kotlin 基金會;
- 2019年5月,谷歌宣布 Kotlin 作為 Android 的首選語言。;
- 2019年7月,Kotlin 在 O’Reilly 開源軟件大會(OSCON)2019上贏得了享有聲望的年度突破項(xiàng)目獎;
2. 為什么選擇 Kotlin?
2.1 簡潔
可以大大減少樣板代碼。
- 例如實(shí)現(xiàn)一個(gè)簡單的
Student
的 POJO 類:
//在Java實(shí)現(xiàn)一個(gè)Student POJO類,需要寫setter,getter模板代碼
class Student {
private String name;
private int age;
private String address;
private String phoneNumber;
public Student(String name, int age, String address, String phoneNumber) {
this.name = name;
this.age = age;
this.address = address;
this.phoneNumber = phoneNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
//Kotlin實(shí)現(xiàn)一個(gè)Student POJO類,僅僅需要1行代碼,就能創(chuàng)建一個(gè)包含setter,getter,equals,toString等POJO類
data class(val name: String, val age: Int, val address: String, val phoneNumber: String)
- 例如實(shí)現(xiàn)一個(gè)簡單的單例模式:
//Java實(shí)現(xiàn)一個(gè)單例模式
public class Singleton implements Serializable {
private Singleton() {
}
private static final Singleton mInstance = new Singleton();
public static Singleton getInstance() {//提供公有獲取單例對象的函數(shù)
return mInstance;
}
public final void doSomething() {
System.out.println("do some thing");
}
}
//Kotlin實(shí)現(xiàn)上面Java一樣的一個(gè)單例模式,僅僅只需要創(chuàng)建object即可
object Singleton : Serializable {//object對象表達(dá)式天生的單例模式
fun doSomething() {
println("do some thing")
}
}
- 例如Kotlin中的
kotlin-android-extension
助力 Android 開發(fā),從此告別findViewById()
模板代碼:
//Java實(shí)現(xiàn)
public class MainActivity extends Activity {
private TextView mTvName;
private TextView mTvAddress;
private TextView mTvDes;
private ImageView mIvCover;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvName = (TextView) findViewById(R.id.tv_name);
mTvAddress = (TextView) findViewById(R.id.tv_address);
mTvDes = (TextView) findViewById(R.id.tv_des);
mIvCover = (ImageView) findViewById(R.id.iv_cover);
mTvName.setText("Kotlin");
mTvAddress.setText("圣彼得堡附近的科特林島");
mTvDes.setText("Kotlin 是一門用于現(xiàn)代多平臺應(yīng)用的靜態(tài)編程語言");
mIvCover.setImageDrawable(R.drawable.icon_kotlin_cover);
}
}
//kotlin利用kotlin-android-extension實(shí)現(xiàn)
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//無需findViewById直接使用
tv_name.setText("Kotlin")
tv_address.setText("圣彼得堡附近的科特林島")
tv_des.setText("Kotlin 是一門用于現(xiàn)代多平臺應(yīng)用的靜態(tài)編程語言")
iv_cover.setImageDrawable(R.drawable.icon_kotlin_cover)
}
}
2.2 安全
可以能夠很好地避免空指針(NPE)異常的出現(xiàn)。
大家都知道NPE異常是運(yùn)行時(shí)異常,編譯期很難發(fā)現(xiàn)NPE異常,Kotlin之所以能夠很好避免NPE,主要關(guān)鍵在于它對類型系統(tǒng)做了非空和可空類型的劃分,并且能在編譯期將可能出現(xiàn)NPE的問題提前暴露出來。
- 聲明處賦值處進(jìn)行 NPE 保護(hù):
//聲明處賦值處進(jìn)行NPE保護(hù)
var name: String //定義一個(gè)非空String類型
name = null//當(dāng)非空類型遇到null賦值,則會出現(xiàn)編譯錯誤
var age: Int?//定義一個(gè)可空Int類型
age = null //只有當(dāng)可空類型遇到null賦值,才會編譯正常
- 可以保護(hù)避免對可空類型的誤操作:
//可以保護(hù)避免對可空類型的誤操作
val address: String? = null //可空類型
println(address.length());//直接對可空類型操作,會編譯錯誤,此時(shí)IDE會提示你這是可空類型變量,不能直接操作,你可能需要判斷NPE的問題
- 更安全的類型檢測和類型轉(zhuǎn)化:
//更安全的類型檢測和類型轉(zhuǎn)化
fun getStringLength(obj: Any): Int? {
if (obj !is String)
return null
//在這個(gè)分支中, obj的類型會被自動轉(zhuǎn)換為String
return obj.length
}
2.3 互操作性
可以充分利用 JVM、Android 和瀏覽器的現(xiàn)有庫。
- 可以和 JVM 上的任何現(xiàn)有庫有 100% 的兼容性:
//使用RxJava庫
fetchUrlList()
.flatMap {
return@flatMap Observable.from(it)
}
.filter {
return@filter it.startWith("https")
}
.onErrorResumeNext {
return@onErrorResumeNext Observable.just("https://kotlinlang.org/")
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<String> {
override fun onCompleted() {
//handle on onCompleted
}
override fun onError(e: Throwable) {
//handle on onError
}
override fun onNext(url: String) {
//handle on onNext
}
})
- 可以和現(xiàn)有的 Android 庫有很好的兼容性:
import android.graphics.Typeface
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.SpannedString
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
//Android API中的Spannable庫的擴(kuò)展函數(shù)
inline fun buildSpannedString(builderAction: SpannableStringBuilder.() -> Unit): SpannedString {
val builder = SpannableStringBuilder()
builder.builderAction()
return SpannedString(builder)
}
//實(shí)現(xiàn)混合Span樣式-擴(kuò)展函數(shù)inSpans
inline fun SpannableStringBuilder.inSpans(
vararg spans: Any,
builderAction: SpannableStringBuilder.() -> Unit
): SpannableStringBuilder {
val start = length
builderAction()
for (span in spans) setSpan(span, start, length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
return this
}
//實(shí)現(xiàn)加粗Span樣式-擴(kuò)展函數(shù)bold
inline fun SpannableStringBuilder.bold(builderAction: SpannableStringBuilder.() -> Unit) =
inSpans(StyleSpan(Typeface.BOLD), builderAction = builderAction)
//實(shí)現(xiàn)斜體Span樣式-擴(kuò)展函數(shù)italic
inline fun SpannableStringBuilder.italic(builderAction: SpannableStringBuilder.() -> Unit) =
inSpans(StyleSpan(Typeface.ITALIC), builderAction = builderAction)
//實(shí)現(xiàn)下劃線Span樣式-擴(kuò)展函數(shù)underline
inline fun SpannableStringBuilder.underline(builderAction: SpannableStringBuilder.() -> Unit) =
inSpans(UnderlineSpan(), builderAction = builderAction)
//調(diào)用處
tv_des = buildSpannedString {
bold {
append("Kotlin")
}
append("是一門用于")
italic {
append("現(xiàn)代多平臺應(yīng)用")
}
underline {
append("靜態(tài)編程語言")
}
}
- 可以和JavaScript 平臺有很好的兼容性,都可用 Kotlin 寫代碼然后部署到你想要的地方:
import kotlin.browser.window
fun onLoad() {
window.document.body!!.innerHTML += "<br/>Hello, Kotlin!"
}
2.4 工具友好
可以用任何 Java IDE 或者使用命令行構(gòu)建。
3. Kotlin能做什么?
如果對 Kotlin 的能力僅僅停留在 JVM平 臺,那是片面的。如今的 Kotlin 已經(jīng)從當(dāng)初的更好 Java 目標(biāo)完成了它華麗的大變身,他們的目標(biāo)已經(jīng)瞄準(zhǔn)了星辰大海。目前 Kotlin 可以適用于移動端跨平臺、原生 JVM、服務(wù)端開發(fā)、Web 開發(fā)、Android 開發(fā)、數(shù)據(jù)科學(xué)等多個(gè)領(lǐng)域。此外近年來 Kotlin 團(tuán)隊(duì)已經(jīng)將重心轉(zhuǎn)移到了語言層面的跨平臺,多平臺的支持。
另一方面,Kotlin 得益于 Kotlin/JVM、Kotlin/JS、Kotlin/Native 三個(gè)語言編譯器的后端實(shí)現(xiàn),它不僅僅可以編譯成 Java 字節(jié)碼(Kotlin/JVM),也可以編譯成JavaScript(Kotlin/JS),還能編譯成直接運(yùn)行在不需要任何VM平臺的機(jī)器代碼(Kotlin/Native),可以輕松實(shí)現(xiàn)語言層面的跨平臺,并實(shí)現(xiàn)在多個(gè)平臺之間共享代碼。目前已經(jīng)部分支持了Linux、Windows、macOS、WebAssembly、Android、iOS以及watchOS和tvOS平臺。
4. 本教程能學(xué)到哪些 Kotlin 技能 ?
-
Kotlin的基本語法和代碼規(guī)范 ;
-
Kotlin的面向?qū)ο螅?/p>
-
Kotlin的函數(shù)式編程;
-
擴(kuò)展函數(shù) ;
-
屬性代理 ;
-
空指針類型安全 ;
-
運(yùn)算符重載 ;
-
lambda表達(dá)式和高階函數(shù);
-
類型系統(tǒng);
-
泛型和型變 ;
-
注解和反射 ;
-
協(xié)程的基本使用;
-
Kotlin 的 DSL;
-
Kotlin 高效實(shí)現(xiàn)常用的設(shè)計(jì)模式;
-
Kotlin 在 Android、IntelliJ IDEA 插件、Gradle、服務(wù)端、Web、iOS 等實(shí)際應(yīng)用開發(fā)。
5. 本教程適合哪些人群?
-
零基礎(chǔ)的開發(fā)者(會從編程語言的最基礎(chǔ)開始講起);
-
有一定 Java、C 或 C++ 開發(fā)基礎(chǔ)開發(fā)者想學(xué)習(xí) Kotlin 開發(fā);
-
Android 開發(fā)者想學(xué)習(xí) Kotlin 開發(fā) Android 應(yīng)用;
-
Java 后端開發(fā)者想學(xué)習(xí) Kotlin 開發(fā)后端應(yīng)用;
-
對 Kotlin 語言感興趣的所有開發(fā)者。
6. 總結(jié)幾條學(xué)習(xí) Kotlin 的建議?
-
如果有 Java 編程基礎(chǔ),記住千萬不要用 Java 編程思維來寫 Kotlin 代碼,換句話說不要硬生生把 Java 代碼轉(zhuǎn)化成 Kotlin 代碼來寫,更需要換個(gè)思維想如果用 Kotlin 某個(gè)語法糖實(shí)現(xiàn)的話更優(yōu)呢,否則將無法真正體會Kotlin這門語言精髓;
-
記住要善于使用 Kotlin 中的反編譯代碼插件,就是將 Kotlin 代碼反編譯成 Java 代碼。這是一條非常重要和實(shí)用的建議,通過它將會真正看透 Kotlin 語法糖背后原理,從而更高效地使用它;
-
學(xué)會經(jīng)常去看 Kotlin 源碼實(shí)現(xiàn),其實(shí) Kotlin 源碼很短的,當(dāng)知道如何使用某個(gè)語法,更需要知道它背后原理以及善于總結(jié)它適用的場景;
-
最后就是多多實(shí)踐,最好是自己弄個(gè)實(shí)際的項(xiàng)目,從0到1全部使用 Kotlin 開發(fā),每天一點(diǎn)一點(diǎn)給它舔磚加瓦,通過它來學(xué)習(xí)每一個(gè) Kotlin 語法技能點(diǎn)。