记录学习《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. 语法和标识符

记得太长了,这部分换一篇继续。

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