Android學(xué)習(xí)Kotlin之一、常量-條件-函數(shù)-高階函數(shù)

Kotlin

Java相對(duì)于Kotlin對(duì)比,Java的語(yǔ)法太繁瑣,Kotlin更現(xiàn)代化, 語(yǔ)法更方便簡(jiǎn)潔, 可以作為更好的一個(gè)替代。Kotlin解決了Java中很多的痛點(diǎn),進(jìn)化成一門(mén)優(yōu)秀的語(yǔ)言,給開(kāi)發(fā)者帶來(lái)了更可靠的開(kāi)發(fā)體驗(yàn)。Kotlin可以編譯成Java字節(jié)碼,也可以編譯成JavaScript,方便在沒(méi)有JVM的設(shè)備上運(yùn)行。除此之外Kotlin還可以編譯成二進(jìn)制代碼直接運(yùn)行在機(jī)器上(例如嵌入式設(shè)備或 iOS)。

Kotlin

為什么學(xué)習(xí) Kotlin?

  • 2019 年,谷歌I/O 大會(huì)上則宣布 Kotlin 是 Android 應(yīng)用開(kāi)發(fā)的首選語(yǔ)言。
  • 簡(jiǎn)潔: 語(yǔ)法簡(jiǎn)潔,大大減少樣板代碼的數(shù)量。
  • 安全: 減少應(yīng)用崩潰,避免空指針異常等整個(gè)類(lèi)的錯(cuò)誤。
  • 互操作性: 可以和Java互相操作。

其它Kotlin文章
Android學(xué)習(xí)Kotlin之一、常量-條件-函數(shù)-高階函數(shù)
Android學(xué)習(xí)Kotlin之二、Null安全 -字符串操作- 類(lèi)型轉(zhuǎn)換
Android學(xué)習(xí)Kotlin之三、標(biāo)準(zhǔn)庫(kù)函數(shù)-集合List-Set-Map
Android學(xué)習(xí)Kotlin之四、定義類(lèi)-初始化-繼承
Android學(xué)習(xí)Kotlin之五、對(duì)象-接口-抽象類(lèi)
Android學(xué)習(xí)Kotlin之六、泛型-擴(kuò)展函數(shù)

本編文章會(huì)講到的知識(shí)點(diǎn)

  • 變量與類(lèi)型
    • 數(shù)據(jù)類(lèi)型
    • 數(shù)字類(lèi)型
    • 變量
    • 類(lèi)型推算
    • 查看Kotlin字節(jié)碼
    • Kotlin的引用類(lèi)型和基本數(shù)據(jù)類(lèi)型
  • 條件語(yǔ)句
    • if else
    • range
    • when
  • string模板
  • 函數(shù)
    • 定義函數(shù)
    • 函數(shù)參數(shù)
    • Unit函數(shù)
    • 反引號(hào)中的函數(shù)名
  • 高階函數(shù)
    • 匿名函數(shù)
    • 函數(shù)類(lèi)型與隱式返回
    • 匿名函數(shù)參數(shù)
    • it關(guān)鍵值
    • 類(lèi)型推斷
    • 參數(shù)為函數(shù)
    • 簡(jiǎn)略傳函數(shù)參
    • 函數(shù)引用
    • 函數(shù)類(lèi)型作為返回類(lèi)型
    • 閉包
    • lambda與匿名內(nèi)部類(lèi)

變量與類(lèi)型

數(shù)據(jù)類(lèi)型

kotlin內(nèi)置數(shù)據(jù)類(lèi)型

類(lèi)型 描述 示例
String 字符串 "Hello kotlin"
Char 單字符 "A"
Boolean 布爾值 true\false
Number 數(shù)值 Byte Short Int Long Float Double
Array 集合 List Set Map

數(shù)字類(lèi)型

和java一樣,kotlin中所有的數(shù)字類(lèi)型都是有符號(hào)的,可以有正有負(fù),長(zhǎng)度各不相同。

類(lèi)型 最大值 最小值
Byte 8 127 -128
Short 16 32767 -32768
Int 32 2147483647 -2147483648
Long 64 9223372036854775807 -9223372036854775808
Float 32 3.4028235E38 1.4E-45
Double 64 1.7976931348623157E308 4 9E-324

變量

聲明變量

聲明變量

  • var可變變量 可改變值
var age: Int = 18
age++ //可改變
  • val只讀變量 只能賦值一次
val name: String = "甜心"
 name = "baby" // 會(huì)報(bào)錯(cuò) 使用val定義的變量是不可改變的只能賦值一次

類(lèi)型推算

對(duì)于已聲明并賦值的變量,它允許你省略類(lèi)型定義自動(dòng)推算類(lèi)型

var love = "敲鍵盤(pán)" //自動(dòng)推算類(lèi)型為String

查看Kotlin字節(jié)碼

查看Kotlin編譯后的字節(jié)碼,有助于深入了解Kotlin語(yǔ)言

兩種方式:

  • Shift兩次,輸入Show Kotlin
  • Tools>Kotlin>Show Kotlin Bytecode


    Kotlin字節(jié)碼

Kotlin的引用類(lèi)型和基本數(shù)據(jù)類(lèi)型

  • Java有兩種數(shù)據(jù)類(lèi)型,一種引用類(lèi)型一種基本數(shù)據(jù)類(lèi)型。
  • Kotlin只有引用類(lèi)型這一種類(lèi)型,出于更高性能的需要,Kotlin編譯器會(huì)在Java字節(jié)碼中改用基本數(shù)據(jù)類(lèi)型。

條件語(yǔ)句

if else

  • java一樣
    if (age>18) {
        println("成年了")
    } else {
        println("未成年")
    }
  • 簡(jiǎn)寫(xiě)方式
println(if (age>18) "已經(jīng)成年2" else "未成年2")

range

Range是Kotlin相對(duì)Java新增的一種表達(dá)式,它表示的是值的范圍,類(lèi)似于數(shù)學(xué)中的區(qū)間。Range的表達(dá)式是像這樣子的:1..20,其中..是運(yùn)算符,它表示一個(gè)閉區(qū)間[1, 20]。而右開(kāi)區(qū)間用until表示:1 until 20,即[1, 20)

  • Range表達(dá)式一般是和in和!in操作符一起使用,表示是否包含在該區(qū)間內(nèi)
    if (a in 2..10) {//相當(dāng)于 i >= 2 && i <= 20
        println("我在區(qū)間")
    }
    if (a !in 2..10) {//相當(dāng)于 i < 2 && i > 20
        println("我不在區(qū)間")
    }
  • 對(duì)于一些整形的range(IntRange、LongRange、CharRange)是可以進(jìn)行迭代的,它們可以和for循環(huán)一起使用
    for (i in 1..6) println(i)//輸出123456
  • 使用downTo()函數(shù)可以對(duì)range進(jìn)行倒序迭代
for (i in 6 downTo 1) println(i)//輸出654321
  • 使用step()函數(shù),這里指定為2,則每次遍歷后會(huì)以2個(gè)為單位遍歷
for (i in 8..16 step 2) println(i)//輸出8 10 12 14 16

when

when,大家都會(huì)聯(lián)想到 Java 中的 switch,然而在 kotlin 中,when 顯然比 Java 中的 switch 要強(qiáng)大得多。when 既可以被當(dāng)做表達(dá)式使用也可以被當(dāng)做語(yǔ)句使用。如果它被當(dāng)做表達(dá)式。

  • 作為表達(dá)式使用,也可以將代碼塊作為我們的分支體,這時(shí)候代碼塊中最后一個(gè)表達(dá)式或者變量就是該分支體的返回結(jié)果
    var n = "小芳"
    var m = when (n) {
        "小明" -> "我是小明"
        "小芳" -> {
            println("lailai")
            "我是小芳芳"
        }
        "小強(qiáng)" -> "我是小強(qiáng)"
        else -> "未知人"
    }
    println(m)//打印 lailai 我是小芳芳
  • 作為語(yǔ)句使用
    when (n) {
        "小明" -> println("我是小明2")
        "小芳" -> println("我是小芳2")
        "小強(qiáng)" -> {
            println("我是小強(qiáng)2")
        }
        else -> println("未知人2")
    }
  • 可以檢測(cè)一個(gè)值在(in)或者不在(!in)一個(gè)區(qū)間或者集合中
    when (6) {
        in 1..10 -> {
            var n = 10
            println(n)
        }
        else -> print(66)
    }
  • 檢測(cè)一個(gè)值是(is)或者不是(!is)一個(gè)特定類(lèi)型的值,可以直接使用類(lèi)型的屬性和方法
    var x = "love"
    when (x) {
        is String -> println("love長(zhǎng)度= " + x.length)
        else -> false
    }
  • 無(wú)參使用,if else if可以改成這樣
    when {
        x?.length==4 -> print("長(zhǎng)度對(duì)的")
        else -> print("長(zhǎng)度不對(duì)")
    }

string模板

模板支持在字符串的引號(hào)內(nèi)放入變量值;還支持字符串里計(jì)算表達(dá)式的值并插入結(jié)果,添加在${}中的任何表達(dá)式,都會(huì)作為字符串的一部分求值。

    val man = "沈騰"
    val woman ="賈玲"
    println("$man love $woman")// 打印 沈騰 love 賈玲

    val falg =false
    println("我愛(ài)的人是:${if (falg) "鄧紫棋" else "張靚穎"}")//打印 我愛(ài)的人是:張靚穎

函數(shù)

定義函數(shù)

private fun doSomething(age:Int,flag:Boolean) :String{
    return "運(yùn)動(dòng)"
}
定義函數(shù)

函數(shù)參數(shù)

  • 默認(rèn)值參數(shù)

如果不打算傳入?yún)?shù),可以給參數(shù)設(shè)置默認(rèn)值

private fun setStudent(name:String,age:Int=18){
    println("名字:$name , 年齡:$age")
}
 setStudent("鄭愷")//沒(méi)有傳age  打印  “名字:鄭愷 , 年齡:18”
 setStudent("鄭愷",38)//打印 “名字:鄭愷 , 年齡:38”
  • 具名函數(shù)參數(shù)

使用參數(shù)命名值傳參,就不用管函數(shù)中參數(shù)的順序了

private fun setMotion(motion1:String,motion2:String,motion3:String){
    println("運(yùn)動(dòng)1:$motion1 , 運(yùn)動(dòng)2:$motion2, 運(yùn)動(dòng)3:$motion3")
}
setMotion(motion2="游泳",motion1 = "乒乓",motion3 = "爬山")// “運(yùn)動(dòng)1:乒乓 , 運(yùn)動(dòng)2:游泳, 運(yùn)動(dòng)3:爬山“
  • Unit函數(shù)

Java中沒(méi)有返回值的函數(shù)定義void類(lèi)型,而kotlin沒(méi)有返回值定義Unit返回類(lèi)型,默認(rèn)可以不寫(xiě)。

private fun setStudent(name:String,age:Int=18):Unit{
}
private fun setStudent(name:String,age:Int=18){
}

反引號(hào)中的函數(shù)名

kotlin可以使用空格和特殊字符對(duì)函數(shù)命名,但是函數(shù)名需要用雙引號(hào)括起來(lái)。Kotlin和Java可以互相調(diào)用函數(shù),而kotlin和Java各自有著不同的保留關(guān)鍵字不能作為函數(shù)名,使用反引號(hào)可以解決沖突。

private fun `123`():Int{
    return 666
}
private fun `class`():String{
    return "class"
}
  println(`123`())
  println(`class`())

高階函數(shù)

匿名函數(shù)

定義時(shí)不取名字的函數(shù),我們稱(chēng)之為匿名函數(shù),匿名函數(shù)通常整體傳遞給其它函數(shù)或者從其它函數(shù)中返回。

  • 定義匿名函數(shù)和調(diào)用, {}是匿名函數(shù) ()是調(diào)用匿名函數(shù)可以傳值 匿名函數(shù)不支持參數(shù)默認(rèn)值和具名函數(shù)參數(shù)。
    println({a: Int, b: String ->
        "Welcome to HangZhou, $a!(copyright $b)"
    }(2021, "磐石"))
  • 定義標(biāo)準(zhǔn)庫(kù)中的函數(shù)規(guī)則
    //count()函數(shù)是獲取字符個(gè)數(shù)
    var totalNum:Int = "missyous".count { letter ->
        letter == 's'
    }
    println("共有s個(gè)數(shù)=:"+totalNum)

函數(shù)類(lèi)型與隱式返回

匿名函數(shù)也有類(lèi)型,匿名函數(shù)可以當(dāng)做變量賦值給函數(shù)類(lèi)型變量,和其它變量一樣,匿名函數(shù)就可以在代碼里傳遞了。函數(shù)類(lèi)型由傳入的參數(shù)和返回值類(lèi)型決定。
匿名函數(shù)一般不需要return關(guān)鍵字來(lái)返回?cái)?shù)據(jù),那么為了返回?cái)?shù)據(jù),匿名函數(shù)會(huì)隱式返回函數(shù)體最后一行語(yǔ)句的結(jié)果。

    //定義一個(gè)函數(shù)nowFun返回類(lèi)型是String
    val nowFun:()->String
    nowFun = {
        val name= "西塘河"
        "你好 $name"
    }
    // 簡(jiǎn)寫(xiě)
    val nowFun:()->String= {
        val name= "西塘河"
        "你好 $name"
    }
    println(nowFun()) // 打印 “你好 西塘河”

匿名函數(shù)參數(shù)

參數(shù)的類(lèi)型放在匿名函數(shù)的類(lèi)型定義中,參數(shù)名則放在函數(shù)定義中

    var nowFun2: (String,Int) -> String = {name,age->
        "你好 $name 年齡 $age"
    }
    println(nowFun2("馬云",50))// 打印 “你好 馬云 年齡 50”

it關(guān)鍵值

定義只有一個(gè)參數(shù)匿名函數(shù)時(shí),可以使用it關(guān)鍵字當(dāng)做參數(shù)名,當(dāng)參數(shù)大于1個(gè)時(shí)it就不能用了。

    var oneParamFun: (String) -> String = {
        "我喜歡:$it"
    }
    println(oneParamFun("林憶蓮"))// 打印 “我喜歡:林憶蓮”

類(lèi)型推斷

定義一個(gè)函數(shù)變量時(shí),如果已經(jīng)把匿名函數(shù)賦值給了變量,就不用指定變量類(lèi)型里了。有參數(shù)時(shí),匿名函數(shù)的參數(shù)名和類(lèi)型都必須有

    //省略前
    val typeFun:()->String = {
        "我喜歡:"
    }
    //省略后
    val typeFun = {
        "我喜歡:"
    }
    println(typeFun())

    //省略前
    val typeParamFun:(String,String)->String = { name, yarn ->
        "Happy $name $yarn"
    }
    //省略后
    val typeParamFun = { name: String, yarn: String ->
        "Happy $name $yarn"
    }
    println(typeParamFun("彭彭", "2025"))

參數(shù)為函數(shù)

在函數(shù)參數(shù)中可以傳入函數(shù),可以是匿名函數(shù)也可以是普通函數(shù)。

    val setTime={goodName:String,yarn:Int->
        "$yarn 天貓雙十一 $goodName"
    }

    fun showTime(name:String, showGood:(String,Int)->String){
        val yarn = (2020..2030).shuffled().last()
        println(showGood(name,yarn))
    }

    showTime(name = "關(guān)曉彤",setTime)

簡(jiǎn)略傳函數(shù)參

如果一個(gè)函數(shù)的lambda參數(shù)排在最后或者是唯一的參數(shù),那么括住lambda值的圓括號(hào)就可以省略掉了。

    showTime(name = "容祖兒"){goodName:String,yarn:Int->
        "$yarn 天貓雙十一 $goodName"
    }

函數(shù)引用

上面講過(guò)了 把函數(shù)當(dāng)成參數(shù)傳給一個(gè)函數(shù)使用,不光可以傳遞匿名函數(shù)也可以傳遞具名函數(shù)的引用,只要可以使用lambda表達(dá)式地方都可以使用函數(shù)引用。

    fun setStudent(name:String,age:Int):String{
        return "我是六年級(jí)的 $name 今年 $age 歲了"
    }
    fun setClass(name:String,student:(String,Int)->String){
        println(student(name,12))
    }
    setClass("黃曉明", ::setStudent)//打印 “我是六年級(jí)的 黃曉明 今年 12 歲了”

函數(shù)類(lèi)型作為返回類(lèi)型

一個(gè)函數(shù)的返回值可以使一個(gè)函數(shù)(包括匿名函數(shù)和具名函數(shù))。

    fun getFruit():(String)->String{
        val currYarn = 2021
        return {fruitName:String->
            "$currYarn 我喜歡吃 $fruitName"
        }
    }
    val fruit = getFruit()//返回的是個(gè)匿名函數(shù)
    println(fruit("櫻桃"))// 打印 “2021 我喜歡吃 櫻桃”

閉包

在Kotlin中,匿名好處能夠修改并應(yīng)用定義在自己的作用域之外的變量,匿名函數(shù)引用著定義自身的函數(shù)里的變量,Kotlin中的lambda就是閉包。
能接收函數(shù)或者返回函數(shù)的函數(shù)又叫做高級(jí)函數(shù),高級(jí)函數(shù)廣泛用于函數(shù)式編程當(dāng)中。

lambda與匿名內(nèi)部類(lèi)

為什么要在代碼中使用函數(shù)類(lèi)型?函數(shù)類(lèi)型能讓開(kāi)發(fā)者少寫(xiě)模式化代碼,寫(xiě)出更靈活的代碼。Java8支持lambda表達(dá)式,但不支持將函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù)或者變量,不過(guò)Java的替代方案是匿名函數(shù)。

  • Kotlin使用匿名函數(shù)

kotlin使用匿名內(nèi)部類(lèi)直接創(chuàng)建就行

    //定義一個(gè)函數(shù)最后一個(gè)參數(shù)是lamdba匿名函數(shù)
    fun setPhone(phoneName: String, moneyDeta: (String, Int) -> Unit) {
        val money = if (phoneName == "iphone12") 5800 else 6000
        moneyDeta(phoneName, money)
    }
    // 調(diào)用函數(shù)傳入一個(gè)lamdba匿名函數(shù)
    setPhone("iphone12") { phoneName: String, money: Int ->
        println("$phoneName 價(jià)格為 $money")
    }
  • Java中使用匿名函數(shù)

java使用匿名內(nèi)部類(lèi)需要先創(chuàng)建一個(gè)接口

    public static void main(String[] args) {
      // 通過(guò)new一個(gè)匿名內(nèi)部類(lèi)傳過(guò)去
        setPhone("iphone12", new MoneyDeta() {
            @Override
            public void setMoney(String phoneName, int money) {
                System.out.println(phoneName+" 價(jià)格為 "+ money);
            }
        });
    }
    public static void setPhone(String phoneName,MoneyDeta moneyDeta){
        int money = "iphone12".equals(phoneName)? 5800:6000;
        moneyDeta.setMoney(phoneName,money);
    }
    //定義接口
    public interface MoneyDeta{
        void setMoney(String phoneName,int money);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容