記錄學習《Kotlin極簡教程》 :第三章 語言基礎,上部分

參考地址

參考地址:Kotlin流程控制語句筆記

學習書籍:《Kotlin極簡教程》

Kotlin

1. 新建Kotlin項目

出現異常,下載不下來

Could not resolve org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.61.

切換到在線模式,修改project的gradle

buildscript {
    ext.kotlin_version = '1.2.61'
    repositories {
//        google()
//        jcenter()
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
//        google()
//        jcenter()
        maven {
            url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
        }
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
        google()
        maven { url 'https://jitpack.io' }
    }
}

MainActivity代碼如下:

package com.yoshin.company.kotlin2app

import android.os.Bundle
import android.support.v7.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

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

    }

}

2. 變量類型

2.1 變量和常量

kotlin 中使用 var和val聲明變量。

語法:

val | var 變量名 [: 變量類型] [= 值]

也可以寫成:

val | var 變量名 [: 變量類型]

此處變量會根據類型設置默認值

val | var 變量名 [= 值]

此處省略了類型

例如下:

    val name: String = "yoshin"
    var age: Int = 12
    var compary: String = "國有企業"

    var compary3: Int
        compary3 =123123

    var compary4 = "1";

2.2 Any 父類

對比JAVA:
當 Kotlin 函數中使用 Any 時,它會被編譯成 Java 字節碼中的 Object

理解用途:
Any 類型是 Kotlin 中 所有非空類型(ex: String, Int) 的根類型。

Any?

用途:可空的根類型

那麼Any和Any?誰是父類的根類型呢?
答:Any?

參考地址:Dive Into Kotlin(四):爲什麼 Kotlin 的根類型是「Any?」

2.3 is 類型檢測

用途:
is運算符檢測一個表達式 是否爲 某類型的一個實例
如果檢測後,可以判斷爲某一類型,那麼可以直接使用該類型而不需要顯示轉換

例:

    fun getLength(obj: Any) {
        if (obj is String) {
            Log.i(TAG,obj) 
        }else
        Log.i(TAG,obj)
    }

我們知道 Log.i(TAG,obj) 裏面的obj應該是string類型纔可以調用。在 obj is String 內的Log.i(TAG,obj) 就可以正常調用,但是else內的就會報錯,不讓這麼寫。

3. 字符串與模板表達式

轉義字符:

轉義字符不沿用java的寫法,而是通過 “”“ ”“”
六個引號,引用。

例:
代碼:

        val shenglue = """
            fun getLength(obj: Any) {
                if (obj is String) {
                    Log.i(TAG,obj)
                }
    //              Log.i(TAG,obj)
            }"""

		println(shenglue)

上述代碼,其實只是定義一個常量,並打印。
輸出Log:

I/System.out:             fun getLength(obj: Any) {
I/System.out:                 if (obj is String) {
I/System.out:                     Log.i(TAG,obj)
I/System.out:                 }
I/System.out:     //              Log.i(TAG,obj)
I/System.out:             }

如小括號和大括號都可以直接輸出出來。

字符串插入代碼:

如圖:

        val shenglue = """${name.length}"""
        println(shenglue)

使用:

“”"${ content }"""

4. 流程控制語句

if語句

if在kotlin的使用中存在返回值,java中沒有

作爲表達式(三元表達式):

var obj2 = if (a > b) 1 else 3

作爲代碼塊:

        var obj2 = if (a > b) {
            println("""${name.length}""")
            1
        } else {
            println("""${name.length + 1}""")
            3
        }

最後一行必須爲該塊的返回值.

when表達式

用途:
功能類似switch-case.

作爲表達式:

val hasPrefix = when (x) {
	is String -> x.startsWith("prefix")
	else -> false
}

作爲代碼塊和表達式:

    val validNumbers = 19;
    fun getU(x: Int): Int {
        return when (x) {
            in 1..10 -> {
                println("x is in the range")
                1
            }
            validNumbers -> {
                println("x is valid")
                2
            }
            in 10..20 -> {
                println("x is outside the range")
                3
            }
            else -> {
                println("none of the above")
                4
            }
        }
    }
    
   println( getU(12))

for循環

Kotlin的for循環與現代的程序設計語言基本相同

for循環有三種循環方法,如下:

迭代器

for循環可以對任何提供迭代器(iterator)的對象進行遍歷,語法如下:

for(item in collection){
	//操作item
	println(item)
}

類似JAVA增強for循環

索引遍歷

通過索引遍歷數組或者List,語法如下:

for(i in args.indices){
	print(array[i])
}

功能類似JAVA普通循環

庫函數操作(withIndex)

for((index,value) in array.withIndex()){
	print("the element at $index is $value")

	//        index//下標
    //        element//值
}

有點增強for循環加PTfor循環組合到一起的感覺,同時獲得兩個值。

while 循環

和JAVA、C基本一致

        var c = 2
        while (c > 0){
            c--
        }
        var dow = 0;
        do {
            dow++
        } while (dow < 9)

break和continue

break. 結束最內層的循環.
return. 默認行爲是, 從最內層的函數或 匿名函數 中返回.
continue. 在最內層的循環中, 跳轉到下一次循環.

跟JAVA一致

return

函數返回值:

1.類似JAVA的用法

    fun sum(x: Int, y: Int): Int {
        return x + y
    }

    fun max(a: Int, b: Int): Int {
        if (a > b) return a else return b
    }

2.使用“=”代替return

可以直接使用=符號直接返回一個函數的值

fun dive(a: Int, b: Int): Int = a / b

標籤 label

用途:可以控制 return、break、continue他們的跳轉行爲。

場景:
在Kotlin中任何表達式都可以用標籤標記;

標籤的格式:
標識符後跟@符號,如:abc@、jarOfLove@
調用時:
@abc、@jarOfLove

標記的例子:

顯示標籤的例子:
fun returnDemo3() {
    println(" start " + ::returnDemo3.name)
    val intArray = intArrayOf(1, 2, 3, 4, 5)
    intArray.forEach here@{
        if (it == 3) {
            return@here
        }
        println(it)
    }
}
隱式標籤的例子:
fun returnDemo4() {
    println(" start " + ::returnDemo4.name)
    val intArray = intArrayOf(1, 2, 3, 4, 5)
    intArray.forEach {
        if (it == 3) {
            return@forEach
        }
        println(it)
    }
}

因爲,不管加不加標籤都不會影響功能,所以,這裏的標籤只有標記以便於之用途

改變功能的例子:

標籤不只是能增加代碼可讀性,還可以改變實際功能。

label配合break的使用

寫了三個方法爲了對比一致label的位置對break的影響:

    private fun returnDemo3() {
        println(" start " + ::returnDemo3.name)

        for (outer in 1..5) {
            println("outer ==$outer")
            for (inner in 1..10) {
                println("inner ==$inner")
                if (inner % 2 == 0) {
                    break
                }
            }
        }
    }

    private fun returnDemo4() {
        println(" start " + ::returnDemo4.name)

        for (outer in 1..5) {
            println("outer ==$outer")
            here@ for (inner in 1..10) {
                println("inner ==$inner")
                if (inner % 2 == 0) {
                    break@here
                }
            }
        }
    }

    private fun returnDemo5() {
        println(" start " + ::returnDemo5.name)

        here@ for (outer in 1..5) {
            println("outer ==$outer")
            for (inner in 1..10) {
                println("inner ==$inner")
                if (inner % 2 == 0) {
                    break@here
                }
            }
        }
    }

調用:

        returnDemo3()
        returnDemo4()
        returnDemo5()

Log輸出:

2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out:  start returnDemo3
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==3
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==4
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==5
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out:  start returnDemo4
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==3
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==4
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==5
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out:  start returnDemo5
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: outer ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==1
2020-07-02 09:28:49.086 6717-6717/com.yoshin.company.kotlin2app I/System.out: inner ==2

通過Log分析:

可以看到我們的方法returnDemo3和returnDemo4是輸出一樣的Log。通過代碼也可以看到,returnDemo4裏label的作用就是跳出當前循環,這和returnDemo3裏break的基礎用法是一致的。

returnDemo3和returnDemo5輸出不一致。returnDemo5方法內,可以看到標籤標記在了最外層循環上,這意味着break的作用是終止最外層循環?
分析一下returnDemo5的代碼,如果當break調用後,作用到最外層循環上,應該輸出Log:

 I/System.out: outer ==1
 I/System.out: inner ==1
 I/System.out: inner ==2

這與我們實際打印出來的Log是一致的。

所以結論,break@lable 會終止 label@ 所在的循環(也會終止內部循環)

label配合return的使用

沒有看出有啥用,再說吧!

記住:return是跳出方法,而lable就是隻能在一個方法內使用,所以return是不是和lable配合不了?

那麼能不能通過lable和return配合,讓return不退出方法內,嘗試下:

        fun run() {
            for (outer in 1..5) {
                println("outer ==$outer")
                for (inner in 1..10) {
                    println("inner ==$inner")
                    here@ if (inner % 2 == 0) {
                        return@here
                    }
                }
            }
            println("run end")
        }
        println("returnDemo6 end")
    }

    private fun returnDemo7() {
        println(" start " + ::returnDemo7.name)

        here@ fun run() {
            for (outer in 1..5) {
                println("outer ==$outer")
                for (inner in 1..10) {
                    println("inner ==$inner")
                    if (inner % 2 == 0) {
                        return@here
                    }
                }
            }
            println("run end")
        }
        println("returnDemo7 end")
    }

調用:

        println("------------------")
        returnDemo6()
        returnDemo7()

Log:

2020-07-02 10:08:24.535 9444-9444/? I/System.out: ------------------
2020-07-02 10:08:24.535 9444-9444/? I/System.out:  start returnDemo6
2020-07-02 10:08:24.535 9444-9444/? I/System.out: returnDemo6 end
2020-07-02 10:08:24.535 9444-9444/? I/System.out:  start returnDemo7
2020-07-02 10:08:24.535 9444-9444/? I/System.out: returnDemo7 end

好像沒啥用。

目前結論是:label和return配合沒啥用

label配合return以及lamda的使用
    private fun returnDemo6() {
        println(" start " + ::returnDemo6.name)
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return
            println(it)
        }
        println("returnDemo6 end")
    }

    private fun returnDemo7() {
        println(" start " + ::returnDemo7.name)
        listOf(1, 2, 3, 4, 5).forEach lit@{
            if (it == 3) return@lit
            println(it)
        }
        println("returnDemo7 end")
    }

調用:

        println("------------------")
        returnDemo6()
        returnDemo7()

輸出:

2020-07-02 10:21:55.514 12304-12304/com.yoshin.company.kotlin2app I/System.out: ------------------
2020-07-02 10:21:55.514 12304-12304/com.yoshin.company.kotlin2app I/System.out:  start returnDemo6
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: 1
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: 2
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out:  start returnDemo7
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: 1
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: 2
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: 4
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: 5
2020-07-02 10:21:55.515 12304-12304/com.yoshin.company.kotlin2app I/System.out: returnDemo7 end

returnDemo7中:可以看到return跳過了當前循環,沒有退出方法,而是繼續運行

label和continue的使用

TODO 沒有找到例子,再說

throw 表達式

Kotlin中的throw 表達式,它的類型是特殊類型:Nothing,該類型沒有值。與JAVA、C中的void一個意思。
用途:輸出異常信息

例:

    private fun testThrow(msg: String){
        throw IllegalArgumentException(msg)
    }
	
	//調用
	testThrow("輸出錯誤信息")
     Caused by: java.lang.IllegalArgumentException: 輸出錯誤信息
        at com.yoshin.company.kotlin2app.MainActivity.testThrow(MainActivity.kt:61)
        at com.yoshin.company.kotlin2app.MainActivity.onCreate(MainActivity.kt:57)

如果要接throw表達式的值,可以這麼寫:

    private fun testThrow(msg: String): Nothing{
        throw IllegalArgumentException(msg)
    }

	val no: Nothing = throw Exception("test")

接收好像是沒啥用,反正會異常退出。

5. 代碼註釋

和JAVA JavaScript 類似,多了一個多層嵌套

6. 語法和標識符

記得太長了,這部分換一篇繼續。

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