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 } }