Kotlin 學(xué)習(xí)筆記之 —— Kotlin 的變量毅人、函數(shù)和類型

課程地址:https://kaixue.io/kotlin-basic-1/

為項(xiàng)目添加 Kotlin 支持

根目錄下的 build.gradle

buildscript {
    // 這里配置一個(gè)全局版本號
    ext.kotlin_version = '1.3.31'
    dependencies {
        // 這里添加依賴
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

app 目錄下的 build.gradle

// 使用 kotlin 的 plugin
apply plugin: 'kotlin-android'
dependencies {
    // 添加依賴
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

Kotlin 文件都是以 .kt 結(jié)尾的

變量

變量的聲明與賦值

var view : View
  • 有一個(gè) var 關(guān)鍵字
  • 變量名在前德绿,類型在后舷手,冒號分隔
  • 結(jié)尾不需要分號

Kotlin 空安全設(shè)計(jì)

非空類型

  • Kotlin 中變量是沒有默認(rèn)值的眉尸,需要手動初始化
  • Kotlin 默認(rèn)聲明變量是非空的秒紧,不能賦值為 null

可空類型

  • 聲明可空變量需要在類型右邊加一個(gè)問號栗恩,被稱為可空類型
var name: String? = null
  • 調(diào)用可空類型變量時(shí)不能手動判斷是否為空透乾,需要使用 ?. ,被稱為「safe call」
view?.setBackgroundColor(Color.RED)
  • 還有一種雙嘆號的寫法磕秤,被成為「斷言式寫法」乳乌,編譯器不再做檢查
view!!.setBackgroundColor(Color.RED)

關(guān)于空安全,最重要的是記住一點(diǎn):所謂「可空不可空」市咆,關(guān)注的全都是使用的時(shí)候汉操,即「這個(gè)變量在使用時(shí)是否可能為空」。

Kotlin 和 Java 的空安全設(shè)計(jì)兼容

  • Kotlin 中調(diào)用 Java 中 @Nullable 變量
name?.length
  • Java 中 @Nullable 和 @NonNull 注解可以自動轉(zhuǎn)化為 Kotlin 代碼
// Java
@Nullable
String name;
@NonNull
String value = "hello";
// Kotlin
var name: String? = null
var value: String = "hello"

延遲初始化

lateinit 關(guān)鍵字適用于聲明時(shí)不能賦值蒙兰,但是能保證使用之前一定會賦值的場景磷瘤,例如 Activity 中的 View:

lateinit var view: View

override fun onCreate(...) {
    view = findViewById(R.id.view)
}

類型推斷

可以在聲明變量時(shí)不指定變量類型其弊,自動推斷。

var name = "Daniel"

動態(tài)類型指變量的類型在運(yùn)行時(shí)可以改變膀斋,類型推斷指在代碼里不用寫變量類型梭伐,編譯器會自動推斷,Kotlin 是靜態(tài)語言仰担,不支持動態(tài)類型糊识。

var 和 val

val 是只讀變量,只能復(fù)制一次摔蓝,類似 Java 中的 final赂苗。

var 是 variable 的縮寫,val 是 value 的縮寫

可見性

Kotlin 中的變量默認(rèn)是 public 的贮尉。

函數(shù)

函數(shù)的聲明

fun cook(name: String): Food {
    ...
}
  • 以 fun 關(guān)鍵字開頭
  • 返回值寫在函數(shù)名和參數(shù)后面
  • 沒有返回值對應(yīng)的類型是 Unit拌滋,并且可以省略
  • 函數(shù)參數(shù)和返回值類型可以是可空類型

可見性

默認(rèn)也是 public

屬性的 getter/setter 函數(shù)

調(diào)用屬性時(shí)其實(shí)調(diào)用的是它的 getter 和 setter。

var name = "Daniel"
    get() {
        return field + " nb!!"
    }
    set(value) {
        field = "good " + value
    }
  • getter / setter 函數(shù)有了專門的關(guān)鍵字 get 和 set
  • getter / setter 函數(shù)位于 var 所聲明的變量下面
  • setter 函數(shù)參數(shù)是 value
  • 使用 field 表示背后的字段
  • val 變量不能重寫 setter猜谚,但可以重寫 getter败砂,而且取值時(shí)還能修改
fun main() {
    // 雖然 name 是 val,但這里打印的值每次都不一樣
    println(Dog().name)
}
class Dog{
    val name = "dog"
        get() {
            return field + System.currentTimeMillis()
        }
}

類型

基本類型

在 Kotlin 中魏铅,所有的東西都是對象昌犹,使用的基本類型有:數(shù)字、字符览芳、布爾值斜姥、數(shù)組與字符串。

var number: Int = 1 // 還有 Double Float Long Short Byte 等
var c: Char = 'c'
var b: Boolean = true
var array: IntArray = intArrayOf(1, 2) // 還有 FloatArray DoubleArray CharArray 等
var str: String = "string"

和 Java 中的區(qū)別:

  • Int 是否裝箱根據(jù)場合來定
var a:Int = 1 // unbox
var b: Int? = 2 // box
var list: List<Int> = listOf(1, 2) // box
  • 數(shù)組的寫法是有區(qū)別的
var array: IntArray = intArrayOf(1, 2) // unbox
  • 不可空類型沧竟、使用 IntArray铸敏、FLoatArray 等不會裝箱
  • 個(gè)人理解,是否裝箱取決于背后使用的是不是對象引用以及會不會為空

類和對象

  • Kotlin 中的類默認(rèn)是 public 的悟泵,可以省略

  • 類的繼承使用 : 代替 extends 或者 implement

  • 構(gòu)造方法寫法不同

    • Java 中會省略默認(rèn)構(gòu)造函數(shù)
    • Kotlin 下面這幾種寫法都可以
    // 省略構(gòu)造函數(shù)的寫法
    class MainActivity : AppCompatActivity() {}
    // 等價(jià)的寫法
    class MainActivity constructor() : AppCompatActivity() {}
    // 更像 Java 的寫法
    class MainActivity : AppCompatActivity {
        constructor() {
        }
    }
    
    • Kotlin 構(gòu)造函數(shù)使用 constructor 關(guān)鍵字
  • override 的不同

    • Java 中使用 @Override 注解
    • Kotlin 使用 override 關(guān)鍵字
    • Kotlin 中省略了 protected 關(guān)鍵字杈笔,Kotlin 中的 override 函數(shù)的可見性是繼承自父類的
  • Kotlin 中的類默認(rèn)是 final 的,可以使用 open 關(guān)鍵字解除

    • 子類不繼承 open 屬性
    • 子方法會繼承 open 屬性魁袜,可以使用 final 關(guān)閉
  • Kotlin 中也可以用 abstract 關(guān)鍵字聲明抽象類桩撮,同 Java

  • Kotlin 中創(chuàng)建對象不需要 new 關(guān)鍵字

類型的判斷和強(qiáng)轉(zhuǎn)

  • Kotlin 中使用 is 判斷類型,并且可以省略強(qiáng)轉(zhuǎn)
fun main() {
    var activity: Activity = SubActivity()
    if (activity is SubActivity) {
        // 強(qiáng)轉(zhuǎn)由于類型推斷被省略了
        activity.subFun()
    }
}
  • Kotlin 使用 as 關(guān)鍵字強(qiáng)轉(zhuǎn)(同 Java )峰弹,使用 as? 來進(jìn)行安全強(qiáng)轉(zhuǎn)
// 強(qiáng)轉(zhuǎn)
fun main() {
    var activity: Activity = SubActivity()
    (activity as SubActivity).subFun()
}
// 安全強(qiáng)轉(zhuǎn)
fun main() {
    var activity: Activity = SubActivity()
    // 注意安全強(qiáng)轉(zhuǎn)后是可空類型,需要使用 ?. 調(diào)用
    (activity as? SubActivity)?.subFun()
}

思考題

  1. 子類重寫父類的 override 函數(shù)芜果,能否修改它的可見性鞠呈?

可以放寬,不能收窄右钾,否則多態(tài)調(diào)用的時(shí)候?qū)o法調(diào)用子方法蚁吝,同 Java旱爆。

open class Bird {
    protected open fun fly(){
        print("bird fly...")
    }
}

class Eagle : Bird(){
    // 可以
    public override fun fly(){
        print("eagle fly...")
    }
}

class Canary : Bird(){
    // 報(bào)錯(cuò)
    private override fun fly(){
        print("canary fly...")
    }
}
  1. 以下的寫法有什么區(qū)別?
activity as? NewActivity
activity as NewActivity?
activity as? NewActivity?

as? 表示安全強(qiáng)轉(zhuǎn)窘茁,NewActivity? 表示轉(zhuǎn)換為可空類型怀伦,兩者并不矛盾,分情況討論山林。

activity 值 null NewActivity 非空實(shí)例 其它類型
activity as? NewActivity 不執(zhí)行 轉(zhuǎn)換成功 不執(zhí)行
activity as NewActivity? 轉(zhuǎn)換結(jié)果為 null 轉(zhuǎn)換成功 ClassCastExecption
activity as? NewActivity? 轉(zhuǎn)換結(jié)果為 null 轉(zhuǎn)換成功 不執(zhí)行
  • 第一種寫法只有當(dāng) activity 為 NewActivity 非空實(shí)例時(shí)會做強(qiáng)轉(zhuǎn)房待,否則不執(zhí)行;
  • 第二種寫法是不安全強(qiáng)轉(zhuǎn)驼抹,不管 activity 是什么類型桑孩,也不管是不是 null 都會強(qiáng)轉(zhuǎn),轉(zhuǎn)換失敗會拋出 ClassCastException框冀;
  • 第三種寫法也是安全強(qiáng)轉(zhuǎn)流椒,如果 activity 是 NewActivity 的實(shí)例或者 null,都會安全轉(zhuǎn)換為 NewActivity? 類型明也,否則不執(zhí)行宣虾。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市温数,隨后出現(xiàn)的幾起案子安岂,更是在濱河造成了極大的恐慌,老刑警劉巖帆吻,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件域那,死亡現(xiàn)場離奇詭異,居然都是意外死亡猜煮,警方通過查閱死者的電腦和手機(jī)次员,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來王带,“玉大人淑蔚,你說我怎么就攤上這事°底” “怎么了刹衫?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搞挣。 經(jīng)常有香客問我带迟,道長,這世上最難降的妖魔是什么囱桨? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任仓犬,我火速辦了婚禮,結(jié)果婚禮上舍肠,老公的妹妹穿的比我還像新娘搀继。我一直安慰自己窘面,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布叽躯。 她就那樣靜靜地躺著财边,像睡著了一般。 火紅的嫁衣襯著肌膚如雪点骑。 梳的紋絲不亂的頭發(fā)上酣难,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天,我揣著相機(jī)與錄音畔况,去河邊找鬼鲸鹦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛跷跪,可吹牛的內(nèi)容都是我干的馋嗜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼吵瞻,長吁一口氣:“原來是場噩夢啊……” “哼葛菇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起橡羞,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤眯停,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后卿泽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莺债,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年签夭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了齐邦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,435評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡第租,死狀恐怖措拇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情慎宾,我是刑警寧澤丐吓,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站趟据,受9級特大地震影響券犁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜之宿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一族操、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧比被,春花似錦色难、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至尺迂,卻和暖如春笤妙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背噪裕。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工蹲盘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膳音。 一個(gè)月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓召衔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親祭陷。 傳聞我的和親對象是個(gè)殘疾皇子苍凛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評論 2 359

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