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

相关推荐
モンキー・D・小菜鸡儿1 小时前
Android14 新特性与适配指南
android·kotlin·安卓新特性
モンキー・D・小菜鸡儿4 小时前
Android15 新特性与适配指南
android·kotlin·安卓新特性
儿歌八万首5 小时前
Jetpack Compose 实战:实现手势缩放图片 (Zoomable Image) 组件
kotlin·android jetpack
モンキー・D・小菜鸡儿5 小时前
Android13 新特性与适配指南
gitee·kotlin·安卓新特性
天下无敌笨笨熊10 小时前
kotlin函数式编程
开发语言·数据库·kotlin
QING61812 小时前
Kotlin Flow 去重 (distinctUntilChanged) 详解
kotlin·android studio·android jetpack
QING61812 小时前
Kotlin Flow 节流 (Throttle) 详解
android·kotlin·android jetpack
Kapaseker12 小时前
Context 知多少,组件通联有门道
android·kotlin
儿歌八万首1 天前
Jetpack Compose 实战:打造高性能轮播图 (Carousel) 组件
android·前端·kotlin
QING6181 天前
Kotlin Flow 防抖(Debounce)详解
android·kotlin·android jetpack