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
    }
}
相关推荐
雾里看山1 小时前
【MySQL】 库的操作
android·数据库·笔记·mysql
水瓶丫头站住10 小时前
安卓APP如何适配不同的手机分辨率
android·智能手机
xvch10 小时前
Kotlin 2.1.0 入门教程(五)
android·kotlin
xvch14 小时前
Kotlin 2.1.0 入门教程(七)
android·kotlin
望风的懒蜗牛14 小时前
编译Android平台使用的FFmpeg库
android
浩宇软件开发15 小时前
Android开发,待办事项提醒App的设计与实现(个人中心页)
android·android studio·android开发
ac-er888815 小时前
Yii框架中的多语言支持:如何实现国际化
android·开发语言·php
苏金标16 小时前
The maximum compatible Gradle JVM version is 17.
android
zhangphil16 小时前
Android BitmapShader简洁实现马赛克,Kotlin(一)
android·kotlin
iofomo21 小时前
Android平台从上到下,无需ROOT/解锁/刷机,应用级拦截框架的最后一环,SVC系统调用拦截。
android