Kotlin学习

复制代码
package com.example.kotlintest

import android.os.Build
import androidx.annotation.RequiresApi
import kotlinx.coroutines.*
import kotlin.reflect.KProperty

@RequiresApi(Build.VERSION_CODES.N)
suspend fun main() {
    println("aaa")
    var name = "alic"
    var ss = "${name} is a boy"
    println(ss)

    var a: Int = 3
    println("a=${a}")
    var age = 10
    var p = People(33, "alic")
    println("${name} 年龄是 ${p.age}")

    var list = listOf<String>("a", "b", "c", "d")
    for (ss in list) {
        println(ss)
    }
    var listmul = mutableListOf<String>("e", "f", "g")
    listmul.add("h")
    for (ss in listmul) {
        println(ss)
    }

    println("sum=${sum(3, 7)}")
    var ii = 20
    if (ii == 10) {
        println("ii=${ii}")
    } else if (ii == 20) {
        println("ii=${ii}")
    }

    println(large(3, 6))
    println(getName("alic"))
    getName1(3.0f)
    //for循环
    val num = 0..10
    val num1 = 0 until 10
    for (i in num) {
        println("forEach 0..10 i= ${i}")
    }
    for (i in num1) {
        println("forEach 0 unti 10 i= ${i}")
    }
    for (i in num1 step 2) {
        println("forEach step i= ${i}")
    }

    for (i in 10 downTo 1) {
        println("forEach downTo i= ${i}")
    }

    val student = Student(12, "alic")
    student.eat()
    student.studyChinese()
    student.studyEnglish()
    //数据类 data
    var phone = Phone("dddd", 1233333)
    println(phone)
    //map
    var map = HashMap<String, Int>()
    map.put("alic", 11)
    map.put("xiaoming", 33)
    map.put("xiaomei", 55)
    map["xiaoqiang"] = 74
    println(" xiaoqiang的年龄是:${map["xiaoqiang"]}")
    val mapof = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
    println(SingleInstanch.getName("aaaaa"))
    //Lambda 表达式的语法结构:
//    {参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
    val listof1 = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
    val lambda = { fruit: String -> fruit.length }
    val maxLengthFruit = listof1?.let {
        for (s in it) {
            println(s)
        }

    }

    val listmap = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
    //map函数 统一对整个map进行处理
    val newList = listmap.map { it.toUpperCase() }
    for (fruit in newList) {
        println(fruit)
    }
    println("-------------")
    //filter 过滤
    val newList1 = listmap.asSequence().filter { it.length <= 5 }
        .map { it.toUpperCase() }
    for (fruit in newList1) {
        println(fruit)
    }

    //any all 返回一个boolean值
    val anyResult = list.any { it.length <= 5 }
    val allResult = list.all { it.length <= 5 }
    println("anyResult is " + anyResult + ", allResult is " + allResult)

    var thread = Thread {
        println("Thread is running")
    }.start()


    doStudy(Student(333, "ddddd"))

//    with函数 with函数接收两个参数:第一个参数可以是一个任意类型的对
//象,第二个参数是一个Lambda 表达式
//    val result = with(obj) {
//    这里是obj的上下文
//        "value" // with函数的返回值
//    }

    val builder = StringBuilder()
    builder.append("Start eating fruits.\n")
    for (fruit in list) {
        builder.append(fruit).append("\n")
    }
    builder.append("Ate all fruits.")
    val result = builder.toString()
    println(result)

    val result1 = with(StringBuilder()) {
        append("Start eating fruits.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruits.")
        toString()
    }
    println(result1)
    //run函数
//    首先run函数通常不会直接调用,
//    而是要在某个对象的基础上调用;其次run函数只接收一个Lambda 参数,并且会在Lambda 表
//    达式中提供调用对象的上下文。其他方面和with函数是一样的,包括也会使用Lambda 表达式
//    中的最后一行代码作为返回值返回
    val result3 = StringBuilder().run {
        append("Start eating fruits.\n")
        for (fruit in list) {
//            第 3 章 先从看得到的入手,探究 Activity 164
            append(fruit).append("\n")
        }
        append("Ate all fruits.")
        toString()
    }
    println(result3)

//    apply函数 apply函数和run函数也是极其类似的,都要在某
//个对象上调用,并且只接收一个Lambda 参数,也会在Lambda 表达式中提供调用对象的上下
//文,但是apply函数无法指定返回值,而是会自动返回调用对象本身
    val result4 = StringBuilder().apply {
        append("Start eating fruits.\n")
        for (fruit in list) {
            append(fruit).append("\n")
        }
        append("Ate all fruits.")
    }
    println(result4.toString())
//    apply 用于初始化对象或修改对象属性 是T的扩展函数 内部使用this ,返回值是本身
//    also 将数据指派给接收对象的属性之前验证对象 是T的扩展函数,内部使用it,返回值是本身
//    let 如果将对象进行空检查并访问或修改其属性 ,是T的扩展函数,内部使用it,最后一行是返回值
//    run 如果计算某个值,或者限制多个本地变量的范围 是T的扩展函数 内部使用this ,最后一行是返回值
//    with 需要传入对象 不是T的扩展函数,不能判空,最后一行是返回值

//    infix自定义操作符
//    比如1 to 2  1 add 2
    //单例
    Util.doAction()
    //静态方法
    var com = ComUtil()
    com.doAction1()
    ComUtil.doAction2()

    //对变量延迟初始化 声明为非空类型的属性在构造函数中初始化 不方便
//    延迟初始化使用的是lateinit关键字,它可以告诉Kotlin 编译器,我会在晚些时候对这个变量
//    进行初始化,这样就不用在一开始的时候将它赋值为null了。
    lateinit var people: People
    people = People(33, "alic")
    println(people)
    if (!::people.isInitialized) {
//        adapter = MsgAdapter(msgList)
    }


//    使用密封类优化代码 sealed修饰
    println(getResultMsg(Success("yes")))

    //扩展函数 fun ClassName.methodName(param1: Int, param2: Int): Int {
    //    return 0
    //}
//    相比于定义一个普通的函数,定义扩展函数只需要在函数名的前面加上一个ClassName.的语
//    法结构,就表示将该函数添加到指定类当中了。
    val count = "ABC123xyz!@#".lettersCount()
    println("字符串中的字母个数是:${count}")

    //高阶函数 一个函数接收另一个函数作为参数,或者返回值的类型是
    //另一个函数,那么该函数就称为高阶函数。
    //函数类型的 语法规则是
//    (String, Int) -> Unit 箭头左边参数 右边返回值
//    exaple()

    //协程 1、GlobalScope
    // 顶层协程 类似Thread不推荐
    GlobalScope.launch {
        println("codes run in coroutine scope")
    }
    Thread.sleep(1000)

    //不推荐 可以保证在协程作用域内的所有代码
    //和子协程没有全部执行完之前一直阻塞当前线程
//    会挂起外部线程,如果你恰好又在主线
//    程中当中调用它的话,那么就有可能会导致界面卡死的情况
    //2、runBlocking
    runBlocking {
        println("codes run in coroutine scope")
        delay(1500)
        println("codes run in coroutine scope finished")
    }

    //创建多个协程
    runBlocking {
        launch {
            println("launch1")
            delay(1000)
            println("launch1 finished")
        }
        launch {
            println("launch2")
            delay(1000)
            println("launch2 finished")
        }
    }

//    val start = System.currentTimeMillis()
//    runBlocking {
//        repeat(100000) {
//            launch {
//                println(".")
//            }
//        }
//    }
//    val end = System.currentTimeMillis()
//    println(end - start)

    //3、CoroutineScope
    //使用协程进行主线程子线程切换
//    CoroutineScope(Dispatchers.IO).launch {
//        //io线程执行耗时操作
        val image = getImage(imageId)
//        launch(Dispatchers.Main) {
//            //切换到主线程更新ui
            avatarIv.setImageBitmap(image)
//        }
//    }

    //Dispatchers.Main 代表主线程,只有在android项目中才生效,在纯kotlin项目中会报错
//    CoroutineScope(Dispatchers.Main).launch {      // 👈 在 UI 线程开始
//        val image = withContext(Dispatchers.IO) {  // 👈 切换到 IO 线程,并在执行完成后切回 UI 线程
            getImage(imageId)                      // 👈 将会运行在 IO 线程
//        }
        avatarIv.setImageBitmap(image)             // 👈 回到 UI 线程更新 UI
//    }


//    coroutineScope函数只会阻塞当前协程,既不影响其他协程,也不影响任何线程,因此是不
//    会造成任何性能上的问题的。而runBlocking函数由于会挂起外部线程,如果你恰好又在主线
//    程中当中调用它的话,那么就有可能会导致界面卡死的情况,所以不太推荐在实际项目中使
//    用。

    //挂起函数 suspend
//    当协程域中的逻辑多 需要抽出来函数,但是函数里的逻辑还需要在协程域里才能生效,就需要将函数改为suspend 挂起
    printDot()
    printDotSuspend()
    getImage(111)
    //获取协程域里的执行结果 1、async 2、withContext
    //async await 获取结果
    //launch函数只能用于执行一段逻辑,却不能获取执行的结果,因为它的返回值 永远是一个Job对象
    // async await 获取结果
    runBlocking {
        var result = async {
            5 + 5
        }.await()
        println("async await result=${result}")
    }

    runBlocking {
        val result = withContext(Dispatchers.Default) {
            5 + 34
        }
        println(result)
    }

    //java 转成kotlin 1、复制java代码到kotlin文件,会提示是否转成kotlin 2、Code→Convert Java File to Kotlin File,
    //kotlin不能自动转成java Kotlin 拥有许多Java 中并不存在的特性

    //匿名内部类 object:xxxcallback
//    xxx.setOnClickListener(object : xxxcalbbaic())


//    类委托的核心思想是将一个类的具体实现委托给另一个类去完成,而委托属性的核心思想是将
//    一个属性(字段)的具体实现委托给另一个类去完成。

//解构 将一个类对象中的参数拆解出来,成为一个一个单独的变量,对变量进行单独操作
//    var teacher: Teacher = Teacher(33, "")
//    val (age, name) = teacher

    //1、类委托 操作对象自己不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理

    // 2、属性委托
    val pd = PropertyDelegation()
    //读取属性,实际上是调用属性的委托对象的getter方法
    println(pd.name)
    //写入属性,实际上是调用属性的委托对象的setter方法
    pd.name = "Kotlin"
    println(pd.name)

    //3、延迟属性 lazy()函数,该函数接受一个Lambda表达式作为参数,并返回一个Lazy对象。
    //第一次程序会计算Lambda表达式并得到返回值,以后再调用,就不会计算lambda表达式,直接返回计算结果

    //两次访问lazyProp属性
    println(lazyProp)
    println(lazyProp)
    //第一次输出结果
    //第一次访问时执行代码块
    //Kotlin

    //第二次输出结果
    //Kotlin

    //kotlin高阶函数的实现原理,每调一次Lambda表达式在底层被转换成了匿名类的实现方式,都会创建匿名内部类对象,造成额外的内存和性能开销    // 内联函数 inline 作用是在编译kotlin文件时直接将内联函数内联掉,这样就把内联函数执行过程放在调用此内联函数的位置,避免了java中多调用方法的操作,减少性能消耗
    //kotlin编译器在编译的时候,将内联函数自动替换到调用它的地方,不存在运行时的开销了,避免了java的多调用方法的操作,减小内存开销
    //noinline 对某个函数非内联
    //内联函数和非内联函数的区别,内联函数lamdba表达式可以return进行函数返回,而非内联函数只能进行局部返回
    //高阶函数转成java代码
//    int res = number1AndNumber2(int num1, int num2,new Function(){
//        @Override
//        public Integer invoke(Integer n1,Integer n2){
//            return n1+n2;
//        }
//    })
    //Sequences 处理集合高效 减少循环次数
    //map filter count会循环三次,asSequence 几个循环共用一个迭代器,一次循环就就可以完成
    //map处理一个数据完成直接传递给filter继续处理
//    list.asSequence()
//        .map { it ++ }
//        .filter { it % 2 == 0 }
//        .count { it < 3 }

    //协程是轻量级线程,线程是由系统调度的,线程切换或线程阻塞的开销比较大,协程依赖线程,协程挂起不需要阻塞线程,

    //安全处理可空类型
    a?.let { }
    //如果a为空,不会报空指针,会返回null

    //kotlin遍历的方式
    //for foreach while do while

    //协程Flow kotlin协程中使用挂起函数可是实现非阻塞地执行任务并将结果返回,但是只能返回单个计算结果,多个计算结果的话,就用到Flow

    //@JVMOverLoads 修饰函数,自动暴漏多个重载方法
//    @JvmOverloads
//    fun f(a:Int,b:String,c:Double){}
//    fun f(a:Int){}
//    fun f(a:Int,b:String){}
//    fun f(a:Int,b:String,c:Double){}

    //List 只读,不能修改元素,继承EmptyList 没有add remove方法
// MultableList 可读可写 继承ArrayList

    //data 数据类 自动实现equal hashCode toString
    // == 对比内容 ===对比对象地址

    //解构 将一个类的对象的参数拆分出来,成为一个个单独变量,使用这些单独变量进行操作
//    var girl1: Student = Student(24,"嫚嫚")
//    var (a,b,c,d) = girl1
//    println("$a,$b,$c,$d")

//    val const 都是不可变的,const必须在编译时知道 val也可以在运行时分配
//    lateinit\lazy区别 lazy修饰val lateinit修饰var,不能保证不变性
    //lateinit可以延迟初始化变量,声明时不用设置为可空
// 判断一个lateinit变量是否init  this::name.isInitialized
    list.forEach {
        println("forEach:${it}")
    }

    //init代码块 在主构造方法执行完执行,想在构造方法里执行代码,就需要在init代码块里执行
    //Conroutines launch async区别 async有返回值 配合await返回协程结果

    //高阶函数 参数或者返回值是函数类型 如(num1:Int,num2:Int -> Int)
    //高阶函数允许函数类型的参数决定函数的执行逻辑
    var resultn: Int = number1AndNumber2(3, 5, ::minus)
    println("number1AndNumber2:${resultn}")
    println(example("alic",39, ::test))
    var result8:Int = number1AndNumber2(44, 99) { n1, n2 ->
        n1 * n2
    }
    println(result8)
    var result9 =number1AndNumber2(44, 99) { n1, n2 ->
        n1 / n2
    }
    println(result9)

    var res=StringBuffer().build(){
        append("Start English")
        list.forEach {
            append(it)
        }
        append("End English")
    }
    println(res)
}
//1、拓展函数build 参数是函数类型的
fun StringBuffer.build(block:StringBuffer.()->Unit):StringBuffer{
    block()
    return this
}
fun number1AndNumber2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    return operation(num1, num2)
}

fun plus(num1: Int, num2: Int): Int {
    return num1 + num2
}

fun minus(num1: Int, num2: Int): Int {
    return num1 - num2
}

fun example(name: String, age: Int, abc: (String, Int) -> String):String {
    return abc(name, age)
}

fun test(name: String,age: Int):String{
    return "${name} is ${age}"
}
val lazyProp: String by lazy {
    println("第一次访问时执行代码块")
    "Kotlin"
}

fun sum(a: Int, b: Int): Int {
    return a + b
}

fun large(a: Int, b: Int): Boolean {
    return a > b
}

fun large1(a: Int, b: Int) = if (a > b) true else false

fun getName(name: String) = when (name) {
    "alic" -> 3
    "lili" -> 4
    "meimei" -> 5
    else -> 0
}

fun getName1(name: Number) {
    when (name) {
        is Double -> {
            println("我是Double:${name}")
        }
        is Int -> {
            println("我是Int:${name}")
        }
        is Float -> {
            println("我是Float:${name}")
        }

    }
}

fun getTextLength(text: String?) = text?.length ?: 0
fun doStudy(study: Study?) {
    study?.let { stu ->
        stu.studyChinese()
        stu.studyEnglish()
    }
}

object Util {
    fun doAction() {
        println("do action")
    }
}

//只让某个方法变成静态
//companion object这个关键字实际上会
//在Util类的内部创建一个伴生类,而doAction2()方法就是定义在这个伴生类里面的实例方
//法。只是Kotlin 会保证Util类始终只会存在一个伴生类对象,因此调用Util.doAction2()方
//法实际上就是调用了Util类中伴生对象的doAction2()方法。
class ComUtil {
    fun doAction1() {
        println("do action1")
    }

    companion object {
        fun doAction2() {
            println("do action2")
        }
    }
}

//给单例类或companion object中的方
//法加上@JvmStatic注解,那么Kotlin 编译器就会将这些方法编译成真正的静态方法
class TurUtil {
    fun doAction1() {
        println("do action1")
    }

    companion object {
        @JvmStatic
        fun doAction2() {
            println("do action2")
        }
    }
}

fun getResultMsg(result: Result) = when (result) {
    is Success -> result.msg
    is Failure -> result.error.message
    else -> throw IllegalArgumentException()
}

interface Result
class Success(val msg: String) : Result
class Failure(val error: Exception) : Result

fun getResultMsg1(result: Result1) = when (result) {
    is Success1 -> result.msg
    is Failure1 -> result.error.message
}

sealed interface Result1
class Success1(val msg: String) : Result1
class Failure1(val error: Exception) : Result1

//统计字符串中字母的数量 拓展String类中的方法
fun String.lettersCount(): Int {
    var count = 0
    for (char in this) {
        if (char.isLetter()) {
            count++
        }
    }
    return count
}

fun exaple(func: (String, Int) -> Unit) {
    func("323fsfsf", 55)
}

//当协程域中的逻辑多 需要抽出来函数,但是函数里的逻辑还需要在协程域里才能生效,就需要将函数改为suspend 挂起
//    suspend挂起 suspend关键字只能将一个函数声明成挂起函数
//    launch函数要求必须在协程作用域当中才能调用。
suspend fun getImage(imageId: Int) = withContext(Dispatchers.IO) {
    // IDE 报错 Suspend function'withContext' should be called only from a coroutine or another suspend funcion
}

suspend fun printDot() {
    println("suspend 函数")
    delay(1000)
    //suspend只是关键字 声明函数可挂起 但是不能提供协程域
//    launch{
//
//    }

}

suspend fun printDotSuspend() = coroutineScope {
    launch {
        println("suspend 函数 增加协程域")
        delay(1000)
    }
}


class Delegate {
    var propValue: Any? = null
    operator fun getValue(myClass: MyClass, prop: KProperty<*>): Any? {
        return propValue
    }

    operator fun setValue(myClass: MyClass, prop: KProperty<*>, value: Any?) {
        propValue = value
    }
}

class MyClass {}

//    类委托 操作对象自己不会去处理某段逻辑,而是会把工作委
//托给另外一个辅助对象去处理
class MySet<T>(val helperSet: HashSet<T>) : Set<T> {
    override val size: Int
        get() = helperSet.size

    override fun contains(element: T) = helperSet.contains(element)
    override fun containsAll(elements: Collection<T>) = helperSet.containsAll(elements)
    override fun isEmpty() = helperSet.isEmpty()
    override fun iterator() = helperSet.iterator()
}

class MySetBySomeClass<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {
    fun helloWorld() = println("Hello World")
    override fun isEmpty() = false
}

//Kotlin属性委托,属性委托可以将多个类的类似属性统一交给委托对象集中实现,这样就可避免每个类都需要单独实现这些属性。
class PropertyDelegation {
    //该属性的委托对象是MyDelegation
    var name: String by MyDelegation()
}

class MyDelegation {
    private var _backValue = "默认值"
    operator fun getValue(thisRef: PropertyDelegation, property: KProperty<*>): String {
        println("${thisRef}的${property.name}属性执行getter方法")
        return _backValue
    }

    operator fun setValue(thisRef: PropertyDelegation, property: KProperty<*>, newValue: String) {
        println("${thisRef}的${property.name}属性执行setter方法,传入参数值为${newValue}")
        _backValue = newValue
    }
}
相关推荐
诸神黄昏EX1 小时前
Android 分区相关介绍
android
大白要努力!2 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee2 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood2 小时前
Perfetto学习大全
android·性能优化·perfetto
Dnelic-5 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen7 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年15 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿17 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神18 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛18 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee