初識Kotlin

這是一個新文集,專門用於記錄學習 Kotlin 時遇到的一些問題或者心得體會。由於個人水平有限,文章難免會有錯誤之處,望大佬不吝指教。

Kotlin 由來已久,在17年被谷歌納爲了 Android 開發的一級語言,相必大家也多少有些許瞭解。在開發工作中,還沒能正式的將項目來使用 Kotlin 開發,但是瞭解 Kotlin 顯然已是迫在眉睫了。

舊項目引入 Kotlin 開發

如果你原來的項目使用 Java 編寫的,可以完全放心,我們可以從現在開始每一個新文件都使用 Kotlin 來編寫,Kotlin 與 Java 是百分百的可互相操作的。我們完全可以在保持原項目結構不便的情況下,來使用 Kotlin 進行後續的開發。

1 引入 Kotlin

  1. 在項目級 build.gradle 文件中引入
buildscript {
    ext.kotlin_version = '1.2.41'
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
  1. 在模塊級 build.gradle 文件中引入
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
  1. 同步項目,開始使用 Kotlin 開始開發

此時你新建一個 Activity 的話,AS 將提示你可以選擇使用 Kotlin 來進行開發;
新建Activity

2 開始開發

打開我們剛剛新建的這個 Activity,我們來看看 Kotlin 新建的頁面與 Java 文件有那些區別;

class TestActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
    }
}

在 Kotlin 中申明類也是使用關鍵字 “class”,類之間的繼承使用 “:” ,注意如果被繼承的父類也是一個 Kotlin 類文件(.kt),那麼這個父類必須要使用 open 關鍵字修飾。在 Kotlin 中類默認狀況相當於在 Java 中使用 final 修飾。

另外 Kotlin 支持 override 父類的成員變量,在父類中使用 open 關鍵字修飾的成員變量,在子類中可以使用 override 來重寫,這一點在 Java 中是不支持的。

由於我們在前面引入了 apply plugin: 'kotlin-android-extensions' ,這使得我們可以直接在 Activity 中使用控件的 id 來調用控件,而無需在採用聲明 - findViewById這種方式來實例化空間了。

例如我們在 xml 文件中放一個 TextView 控件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/mTvText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="這是一個測試的文字"
        android:textColor="#ff00ff"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

我們可以這樣在 Activity 中操作:

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
        var oldText = mTvText.text
        var newText = "這是一個新的字符串"
        mTvText.text=newText
    }

上述代碼中,我們可以把 text 直接看成是 TextView 的一個公開的成員變量來使用,省去了 get/set 方法,這樣的例子在 Kotlin 中還有很多。

在 Kotlin 中,我們使用 var 來聲明一個可以讀寫的變量,使用 val 來聲明一個只讀變量。使用 val 聲明的變量,在初始化其值後不允許再次賦值。與 Java 不同的是,在 Kotlin 中申明一個變量不一定需要顯示聲明,Kotlin 可以自動的推斷出一個變量的類型,一個變量在類型確定之後不可以修改其類型。

var a: String = ""  //顯示聲明 a 爲 String 類型
var b=1                //自動推斷出 b 爲 int

空安全

Kotlin 是默認空安全的,除非在變量在聲明時使用 “?” 來標註該變量可以爲 null,否則所有變量默認都是不可爲 null,這樣可以最大程度的避免空指針異常。

手動聲明該變量可以爲null

通常我們在 Android 編程時,都會在類中事先聲明大量的變量,這些變量並不是都能在聲明時初始化,往往很多都是在 Activity 的聲明週期裏完成的初始化。

但是在 Kotlin 中 你會發現有這種情況:
屬性必須初始化或者是抽象的

面對這種情況有兩種解決方法:
1. 在 init 代碼塊中初始化
init代碼塊
2. 使用 lateinitlazy 進行延時初始化
lateinit 用於 var 變量,lazy 用於 val 只讀變量。
lateinit 延時初始化

空判斷

如果我們已經顯式的聲明瞭一個變量可以爲 null,那麼在對這個變量進行操作時,我們需要對改變了進行空判斷,這一點 Java 中也是一樣的。

這樣寫在 Java 中是可以通過的,但是 Kotlin 中不可以
Java 中允許這樣書寫代碼

顯而易見的,如果是 Java 代碼,運行到此處的時候回報空指針異常,導致程序崩潰。

在Kotlin 中我們有多重方式來進行空判斷:
1. 傳統的 Java 式在條件中顯示檢查 null

fun print(){
        var nullString: String? = null
        if (nullString != null) {
            println(nullString.length)
        } else {
            println("empty")
        }
    }
  1. 使用安全調用 “?.” 操作符
    ?. 安全調用操作符
    使用該操作符時,如果對象爲 null,則不會調用該對象的方法,並且返回 null,不爲 null 則正常執行
    相當於:
if(nullString == null){
    return null
}else{
    return nullString.lenght
}
  1. Elvis 貓王操作符 “?:
    當我們有一個可空的引用 r 時,我們可以說“如果 r 非空,我使用它;否則使用某個非空的值 x”,如下(注意:這是 kotlin 特有的操作,相當於 Java 中的三元操作符,但是 Kotlin 更爲強大允許將 if - else 語句塊中最後一句當成返回值返回):
val l: Int = if (b != null) b.length else -1

我們可以將它簡化爲:

val l = b?.length ?: -1

Elvis 操作符
可以看出,變量 b 直到運算的一刻才轉型成字符型,這一操作在 Java 中是不可以的。需要注意的是,如果一個對象被聲明爲可能爲空,那麼除非是採取方法1在條件中判斷 null,否則我們必須採用安全調用的方式。

4.使用 “!!” 運算符
上述的幾種方式都是讓我們如何避免空指針異常,但有時我們需要在代碼裏拋出這個異常,這一操作需求在 Java 裏是不需要的,因爲只要我們沒有做空判斷,代碼執行到此處如果對象爲空,必然會 NPE (NullPointerException)。但是在 Kotlin 裏一個被聲明爲可空的變量是不能直接被調用的(見上文),這時我們就需要 “!!” 操作符,這個操作符可以使編譯器忽略此處的空檢查,當對象爲空時,運行到此處會 NPE。
!! 操作符拋出 NPE

上述的四種方法就是我們在 Kotlin 中最常用的四種空判斷方式,下面我們來總結一下:
- 當我們需要一個常規的空判斷時,使用方法1;
- 當我們需要在對象爲空時,表達式結果爲空,使用方法2;
- 當我們需要在對象爲空時,返回另一個表達式或者值,使用方法3;
- 當我們需要在對象爲空時能正常的拋出 NPE,使用方法4;

最後給大家看一個在 Kotlin 中才能使用的騷操作
安全調用 、Elvis 操作符、if 表達式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章