Kotlin语言基础笔记

Kotlin是一门非常方便的开发语言,它的语法糖有很多,要想要很熟练的掌握kotlin语言,只有不断地使用kotlin写代码,从而达到量到质的一个改变。本文也只是介绍其中的一点内容,内容很松散,有些知识点需要自己动手去写,去实现才能真正体会其中的魅力。

1 高阶函数

1.1 Lambda表达式

分析高阶函数的基础是lambda表达式,先看一下常见的Lambda表达式的使用方式。

Kotlin 复制代码
fun main() {

    // () -> Unit    空参函数  并且 没有返回值  函数名=method01

    // TODO 定义没有问题,调用不行
    /*var method01 : () -> Unit
    method01() // 不能调用  没有具体的实现

    var method02 : (Int, Int) -> Int
    method02(9, 9)

    var method03: (String, Double) -> Any?
    method03("Derry", 543354.4)

    var method04 : (Int, Double, Long, String ? ) -> Boolean
    method04(1, 545, 3543, null)

    var method05 : (Int, Int) -> Int
    method05(9, 9)*/

    // : (形参类型)
    // = {具体详情}

    // TODO 定义没有问题,调用OK ,因为有实现了
    var m06 : (Int, Int) -> Int = {number1, number2 -> number1 + number2}
    println("m06:${m06(9, 9)}")

    var m07 = { number1: Int , number2: Int -> number1.toDouble() + number2.toDouble()}
    println("m07:${m07(100, 100)}")

    var m08 : (String, String) -> Unit = {aString, bString -> println("a:$aString,  b:$bString")}
    m08("李元霸", "王五")

    var m09 : (String) -> String = {str -> str}
    println("m09:${m09("降龙十八掌")}")

    var m10 : (Int) -> Unit = {
        when(it) {
            1 -> println("你是一")
            in 20..30 -> println("你是 二十 到 三十")
            else -> println("其他的数字")
        }
    }
    m10(29)

    var m11 : (Int, Int, Int) -> Unit = { n1, n2, n3 ->
        println("n1:$n1, n2:$n2, n3:$n3")
    }
    m11(29,22,33)

    var m12 = { println("我就是m12函数,我就是我") }
    m12()

    val m13 = {sex: Char -> if (sex == 'M') "代表是男的" else "代表是女的"}
    println("m13:${m13('M')}")

    // 覆盖操作
    var m14 = {number: Int -> println("我就是m14  我的值: $number")}
    m14 = {println("覆盖  我的值: $it")}
    m14(99)

    // 需求:我想打印, 并且,我还想返回值,就是 我什么都想要
    var m15 = { number: Int -> println("我想打印: $number")
        number + 1000000
    }
    println("m15:${m15(88)}")
}

代码中的注释有对应的解释,此处我们不做过多的赘述,上面一共展示了15中Lambda表达式的使用方式,其实总结下来就2种形式:

Kotlin 复制代码
// : (形参类型)
// = {具体详情}

对于Lambda表达式,至于说到底什么是Lambda表达式,其实我理解他就是一种规则,允许在编程过程中使用的一种规则。说穿了没有什么高深的东西,就是多多练习使用后熟能生巧的一个过程,这里只介绍这种语法糖即可。

1.2 扩展函数

java 复制代码
fun main() {
    val stu = Student()
    stu.add(100, 200)

    // KT本来就有
    val file = File("///")
    file.readText()
    file.show()
}

// 扩展 函数
fun Student.add(n1: Int, n2: Int) {
    println("结果:${n1 + n2}")
}

fun Student.show() {
    println("Student show")
}

// 给 java File 增加 扩展函数
fun File.show() {
    println("给 java File 增加 扩展函数")
}

扩展函数可以理解为在外部对已有的类添加函数,什么意思呢,说穿了就是不想改动原来的类,但是呢又想对类的功能进行扩展,保持了原有的实现,然后又扩展了一项功能,使得其他的该类的变量都能够进行使用,这就是扩展函数的核心。

1.3 高阶函数

高阶函数的理解:如果在函数上用到了Lambda表达式,那该函数就属于高阶函数。

Kotlin 复制代码
fun main() {
    show(true) {
        // println(it)
        'M'
    }
}

// TODO  loginMethod:(Boolean)->Unit

fun loginMethod(b: Boolean) : Unit {

}

// loginMethod 方法名
// (Boolean)方法的那个括号
// -> 方法体 干活
// Unit == void

fun show(isLogin: Boolean, loginMethod:(Boolean)->Char) {
    if (isLogin) {
        println("登录成功")
        val r = loginMethod(true)
        println(r)
    } else {
        println("登录失败")
        loginMethod(false)
    }
}

上面简单的举了一个扩展函数的例子,具体的解释代码中已经注释了,其实高阶函数,就是在参数中定义了一个Lambda表达式。

其实我们平时使用的let、run、with、apply、also都是一些高阶的扩展函数,我们来分析一下具体的实现,感受一下高阶函数的魅力:

Kotlin 复制代码
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, Invoc ationKind.EXACTLY_ONCE)
    }
    return block(this)
}

@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

总结:

also let :

使用的参数传递调用者对象的方式,也就是将调用者的对象以参数的形式传入到高阶函数中,然后通过"调用者对象参数.方法"的方式调用调用者对象中的方法。

返回值不一样,also的返回值是调用者对象本身,let的返回值是高阶函数实现体的最后一行代码的返回值类型。

apply、with、run:

都是通过对调用者对象增加匿名函数的方式实现,这样做的好处是在高阶函数的具体实现中全局的增加了一个this对象,随时都可以直接调用调用者对象中的其他方法,不需要使用"this.方法"的方式。

返回值不一样,apply返回的是调用者本身,with run返回的是高阶函数的最后一行代码的返回类型。

1.4 Kt关键字in out

此处多提一下,kotlin中有2个关键字:in和out,其实这2个关键字比较好理解,只要你理解了之前分析的泛型中的extend和super关键词,那么我们肯定就能理解,来看一下Java中泛型的读取模式:

java 复制代码
    // 泛型读取模式
    void test01() {

        // ? extends FuClass  == 只能获取,不能修改
        List<? extends FuClass> list = new ArrayList<ZiClass>();

        // 不能修改
        /*list.add(fuClass);
        list.add(ziClass);*/

        // 能获取
        FuClass fuClass = list.get(0);

        // TODO  =============================================


        // ? super ZiClass == 只能修改,不能获取
        List<? super ZiClass> list2 = new ArrayList<FuClass>();

        // 能添加
        list2.add(ziClass);

        // 不能获取
        // ZiClass ziClass = list2.get(0);
    }

extend是只能获取不能修改,super是只能修改不能获取。那么kotlin中extend对应的out,super对应的in。

Kotlin 复制代码
fun test01() {
    // out 只能取,不能修改   == ? extends FuClass
    val list: MutableList<out FuClass> = ArrayList<ZiClass>()

    // in 只能修改(存), 不能获取   === ? super ZiClass
    val list2: MutableList<in ZiClass> = ArrayList<FuClass>()
}
Kotlin 复制代码
// 这个类,就是只能获取,不能修改了
// 声明的时候加入  一劳永逸了<in T>
class Worker <out T> {

    // 能获取
    fun getData() : T? = null

    // 不能修改
    /*fun setData(data: T) {

    }

    fun addData(data: T) {

    }*/
}
Kotlin 复制代码
// 这个类,就是只能修改, 不能获取
// 声明的时候加入  一劳永逸了<in T>
class Student<in T> {

   /*fun a(list: MutableList<in T>) {

    }

    fun a2(list: MutableList<in T>) {

    }

    fun a3(list: MutableList<in T>) {

    }

    fun a4(list: MutableList<in T>) {

    }

    fun a5(list: MutableList<in T>) {

    }*/

    fun setData(data: T) {}

    fun addData(data: T) {}

    // 不能获取
    // fun getData() : T
}

2 协程

2.1 协程的使用

协程的使用主要是2个方式runBlocking和GlobalScope.launch的方式,具体看一下实现

Kotlin 复制代码
fun click3(view: View) = runBlocking {
	// TODO 完成这种  异步线程  和  主线程  的切换,  这个需求:之前我们用RxJava实现过了哦
	// 1.注册耗时操作
	// 2.注册耗时操作完成后,更新注册UI
	// 3.登录耗时操作
	// 4.登录耗时操作完成后,更新登录UI

	// main
	launch {

		val pro = ProgressDialog(this@MainActivity)
		pro.setMessage("正在执行中...")
		pro.show()

		withContext(Dispatchers.IO) {
			// 1.注册耗时操作  异步
			Log.d("click3", "1.注册耗时操作: ${Thread.currentThread().name}")
			Thread.sleep(2000)
		}

		// 2.注册耗时操作完成后,更新注册UI  main
		Log.d("click3", "2.注册耗时操作完成后,更新注册UI: ${Thread.currentThread().name}")

		withContext(Dispatchers.IO) {
			// 3.登录耗时操作  异步
			Log.d("click3", "3.登录耗时操作: ${Thread.currentThread().name}")
			Thread.sleep(3000)
		}

		// 4.登录耗时操作完成后,更新登录UI
		Log.d("click3", "4.登录耗时操作完成后,更新登录UI: ${Thread.currentThread().name}")

		// pro.dismiss()
	}

}

runBlocking平时的开发中一般是不用的,一般是在测试过程中使用,因为runBlocking是阻塞式的。

Kotlin 复制代码
// 非阻塞
fun click4(view: View)  {
	// TODO 完成这种  异步线程  和  主线程  的切换,  这个需求:之前我们用RxJava实现过了哦
	// 1.注册耗时操作
	// 2.注册耗时操作完成后,更新注册UI
	// 3.登录耗时操作
	// 4.登录耗时操作完成后,更新登录UI

	// main
	GlobalScope.launch (Dispatchers.Main) {

		val pro = ProgressDialog(this@MainActivity)
		pro.setMessage("正在执行中...")
		pro.show()

		withContext(Dispatchers.IO) {
			// 1.注册耗时操作  异步
			Log.d("click3", "1.注册耗时操作: ${Thread.currentThread().name}")
			Thread.sleep(2000)
		}

		// 2.注册耗时操作完成后,更新注册UI  main
		Log.d("click3", "2.注册耗时操作完成后,更新注册UI: ${Thread.currentThread().name}")
		textView.text = "注册成功,你可以去登录了"
		pro.setMessage(textView.text.toString())

		withContext(Dispatchers.IO) {
			// 3.登录耗时操作  异步
			Log.d("click3", "3.登录耗时操作: ${Thread.currentThread().name}")
			Thread.sleep(3000)
		}

		// 4.登录耗时操作完成后,更新登录UI
		Log.d("click3", "4.登录耗时操作完成后,更新登录UI: ${Thread.currentThread().name}")
		textView.text = "登录成功,欢迎回来"
		pro.setMessage(textView.text.toString())

		pro.dismiss()
	}

}

2.2 协程的原理

至于原理,有一篇博客讲解的很好,大家可以参考:https://www.jianshu.com/u/a324daa6fa19

相关推荐
帅次6 小时前
Flutter 边框按钮:OutlinedButton 完全手册与设计最佳实践
android·flutter·macos·ios·kotlin·android studio
岸芷漫步8 小时前
串口通信分析与实例
kotlin
QING61812 小时前
Android AIDL 开发指南:包含注意事项、兼容性问题
android·kotlin·app
帅次12 小时前
Flutter FloatingActionButton 从核心用法到高级定制
android·flutter·macos·ios·kotlin·android-studio
moz与京15 小时前
【记】如何理解kotlin中的委托属性?
android·开发语言·kotlin
左少华15 小时前
Kotlin-inline函数特效
android·开发语言·kotlin
氦客16 小时前
Kotlin知识体系(一) : Kotlin的五大基础语法特性
android·开发语言·kotlin·基础语法·特性·知识体系
每次的天空1 天前
kotlin中的行为组件
android·开发语言·kotlin
wangz761 天前
Kotlin,jetpack compose,Android,MPAndroidChart,折线图示例
android·kotlin·mpandroidchart