声明
大家好,这里是懒羊羊学长,如果需要pdf版以及其他资料,请加入群聊。群里每天更新面经、求职资料,经验分享等,大家感兴趣可以加一下。
Kotlin
- 声明
- 1.Kotlin基础
- 2. Kotlin函数
- 3.Kotlin进阶
- 4.Kotlin集合
- 5.Kotlin高级
- 6.kotlin实战
- 6.1协变 逆变
- 7. 手写内置函数
- 7.1 Kotlin的单例模式
- 7.2 Kotlin的注解
- 7.3 手写RxJava
1.Kotlin基础
- Kotlin的空指针检查
var name:String?=null
//村民1使用null
//TODO 第一种补救措施,变量后边加上?,这样的话name如果真的是null,后边就不会执行,就不会引发空指针异常
name?.length
//TODO 第二种补救措施,不论name是不是null,都会执行
name!!.length
//TODO 第三种补救措施 ,(和Java一样)
if(name!=null){
name.length
}
- var 和val
//TODO val修饰的变量只读不能改 var修饰的变量可读可改 我们修饰变量时尽可能用val修饰
- 类型推断(函数也可以类型推断)
fun main(){
//TODO 类型推断
val name:String="Derry"
val info:String ="真的很帅"
val name1="Derry"
val age=35
val sex='c'
//kotlin在编译期就决定好了类型,那么他就是静态语言。
}
fun add(number1:Int,number2:Int)=number1+number2
-
Java中称为方法,kotlin中称为函数,可以写在类的外面
-
Kotlin内置数据类型 这些在Java里边相当于一个包装类
String 字符串
Char 单字符
Boolean true、false
Int 整数
Double 小数
List 元素集合
Set 无重复的元素集合
Map 键值对的集合 -
编译时常量
const val PI=3.14 //编译时常量,不能放在函数里边。如果在函数里边的话只能在运行时运行,何来编译时常量之说。
fun main(){
val infoValue="Derry is Ok" //这个是只读类型的变量,并不能成为编译时常量
println(infoValue)//只能读取,只读类型
}
- kotlin引用数据类型
const val PI=3.14 //编译时常量,不能放在函数里边。如果在函数里边的话只能在运行时运行,何来编译时常量之说。
fun main(){
val infoValue="Derry is Ok" //这个是只读类型的变量,并不能成为编译时常量
println(infoValue)//只能读取,只读类型
}
- range表达式
package com.example.myapplication.kotlinlearn
//TODO kotlinrange表达式讲解
class kt13 {
}
fun main(){
val number=148
//range 范围从哪里到哪里
if(number in 10..59){
println("分数不及格")
}else if(number in 0..9){
println("分数不及格并且分数很差")
}else if (number in 60..100){
println("分数合格")
}else if (number !in 0..100){
println("分数不在1到100范围内")
}
}
- when表达式
package com.example.myapplication.kotlinlearn
//TODO when表达式详解
class kt14 {
}
fun main() {
//Java中if语句是执行代码
//Kotlin中是表达式,能够有返回值
val week = 1
val resultInfo = when (week) {
1 -> "星期一"
2 -> "星期二"
3 -> "星期三"
4 -> "星期四"
5 -> "星期五"
6 -> "星期六"
7 -> "星期日"
else -> "不知道星期几了"
}
println(resultInfo)
}
- String模板
package com.example.myapplication.kotlinlearn
class kt15 {
}
//TODO 15.String 模板
fun main() {
val garden = "梅溪湖公园"
val time = 6
println("今天天气很晴朗,去玩" + garden + "玩了" + time + "小时")//Java的写法
println("今天天气很晴朗,去玩$garden,玩了${time}小时")//String模板的写法
//KT是表达式
println()
val isLogin = false
println("resposne result:${if (isLogin) "恭喜" else "不恭喜"}")
}
2. Kotlin函数
- 函数格式
package com.example.myapplication.kotlinlearn02
class K1Base {
}
//TODO 16.Kotlin的函数头讲解
fun main() {
method01(1, "33")
}
//函数不加修饰符的话默认就是public
//kotlin函数是先有输入,再有输出
private fun method01(age: Int, name: String): Int {
println("name$name,age:$age")
return 200
}
- 默认参数
package com.example.myapplication.kotlinlearn02
class K1Base {
}
//TODO 16.Kotlin的函数头讲解
fun main() {
method01(1, "33")
}
//函数不加修饰符的话默认就是public
//kotlin函数是先有输入,再有输出
private fun method01(age: Int, name: String): Int {
println("name$name,age:$age")
return 200
}
- 具名函数参数
package com.example.myapplication.kotlinlearn02
class K1Base {
}
//TODO 16.Kotlin的函数头讲解
fun main() {
method01(1, "33")
}
//函数不加修饰符的话默认就是public
//kotlin函数是先有输入,再有输出
private fun method01(age: Int, name: String): Int {
println("name$name,age:$age")
return 200
}
- Unit关键字
package com.example.myapplication.kotlinlearn02
class kt19 {
}
//TODO KotlinUnit函数的特点
fun main() {
val r: Unit = doWork()
println(r)
}
//:Unit不写默认也有,相当于无参数返回 忽略类型 相当于Java里的void,Unit是一个类型 不是关键字
private fun doWork(): Unit {
}
- Nothing关键字
package com.example.myapplication.kotlinlearn02
class kt19 {
}
//TODO KotlinUnit函数的特点
fun main() {
val r: Unit = doWork()
println(r)
}
//:Unit不写默认也有,相当于无参数返回 忽略类型 相当于Java里的void,Unit是一个类型 不是关键字
private fun doWork(): Unit {
}
- 反引号的使用
package com.example.myapplication.kotlinlearn02
//TODO kotlin反引号特点讲解
class kt21 {
}
private fun a() {
//1 '方法名' 用反引号写的kotlin方法名在低版本的时候是可以使用的,但先高版本已经废弃了
kt21.`is`()//如果别的Java文件里恰好定义了这两个方法,那么得用反引号括起来
kt21.`in`()
//3.第三种情况
//private fun `2123456`(){ 加密函数作用,维护一个文档,里边写明这个函数的饿作用
//
//}
}
private fun `2123456`() {
}
- 匿名函数
package com.example.myapplication.kotlinlearn02
//TODO 22.匿名函数讲解
fun main() {
//没有名字的函数是匿名函数
val length = "derry".count() {// 由于没有名字,会默认给这个Char类型,一个名字,一般情况下 都是it。传入参数是把字符串的每一个字符依次传入进来
it == 'r'
}
println(length) //这里会打印出2,因为字符串中只有两个字符是满足lambda表达式的条件
}
- Kotlin函数类型
package com.example.myapplication.kotlinlearn02
class kt23 {
}
//TODO 23.Kotlin的函数类型和隐式返回讲解
fun main() {
val methodAction: () -> String//函数的输入与输出的声明 声明区域
methodAction = { //实现区域
"xyr" //匿名函数不用写return 以最后一行作为返回值
}
//调用函数
println(methodAction())
println(methodAction.invoke()) //这种调用方式仅限于lambda,普通函数就不支持这种方式了
}
fun methodAction(): String //声明区域
{
return "xyz" //实现区域
}
- lambda函数的参数
package com.example.myapplication.kotlinlearn02
fun main() {
//第一步:函数输入 输出 和声明,第二步是函数的实现
val methodAction: (Int, Int, Int) -> String = { number1, number2, number3 -> //大括号里是函数的实现
"number1:$number1,number2:$number2"
}
//第三步调用
println(methodAction(1, 2, 3))
}
//真正的函数
fun methodAction(number1: Int, number2: Int, number3: Int) {
}
- it关键字的用法
package com.example.myapplication.kotlinlearn02
fun main() {
//第一步:函数输入 输出 和声明,第二步是函数的实现
val methodAction: (Int, Int, Int) -> String = { number1, number2, number3 -> //大括号里是函数的实现
"number1:$number1,number2:$number2"
}
//第三步调用
println(methodAction(1, 2, 3))
}
//真正的函数
fun methodAction(number1: Int, number2: Int, number3: Int) {
}
- 匿名函数类型推断
package com.example.myapplication.kotlinlearn02
//TODO 26.Kotlin的匿名函数类型自动推断
fun main() {
//
val fun2: () -> Unit
//fun1 必须指定参数类型和返回类型
val fun1 = {
println("你好")
}
//如果没有指定,则以最后一行作为返回值类型
val fun3 = { v1: Double, v2: Float, v3: Int ->
"啦啦啦v1$v1,v2$v2,v3$v3"
}
//fun3 就是(Double,Float,Int)->String 这个类型 ,fun4并不是匿名函数,只是一个变量,后边的函数体才是匿名函数
println(fun3(2.2, 3f, 5))
fun1.invoke()
}
- lambda表达式
package com.example.myapplication.kotlinlearn02
//TODO 27.Kotlin的lambda的表达式
fun main() {
//匿名函数
val fun1 = {
}
//匿名函数等价于后边要讲的Lambda
val addResultFun = { number1: Int, number2: Int ->
println("两个数相加的结果是${number1 + number2}")
}
val weekResult: (Int) -> Any = { number: Int ->
when (number) { //when关键字也可以作为一个返回值
1 -> "星期一"
else -> -1
}
}
}
- 函数中定义参数是函数包函数
package com.example.myapplication.kotlinlearn02
//TODO 28.函数中定义参数是函数包函数
fun main() {
//用户
loginAPI("Derry", "123456") { msg, code ->
println("用户最终登录的成果如下msg:$msg,code是:$code")
}
}
//模拟:数据库SQLServer
const val USER_NAME_SAVE_DB = "Derry"
const val USER_PWD_SAVE_DB = "123456"
//模拟,登录API前端
public fun loginAPI(userName: String, userPwd: String, responseResult: (String, Int) -> Unit) {
if (userName == null || userPwd == null) {
TODO("用户名密码是null")
}
responseResult.invoke(userName, 3)
}
- 内联函数
package com.example.myapplication.kotlinlearn02
//TODO 内联函数
fun main() {
//TODO 如果函数没有内联,那么在调用端,会生成多个对象来完成Lambda的调用(会造成性能的损耗)
//TODO 如果此函数使用内联,在调用端会采用宏替换,替换到调用处,好处(没有任何函数开辟、对象开辟等性能的损耗)
//如果一个函数里的参数有Lambda,那么,就需要声明内联
//TODO 如果函数参数有Lambda,尽量使用inline修饰,这样内部会做优化,减少函数、对象开辟的损耗。
}
- 函数引用
package com.example.myapplication.kotlinlearn02
//TODO 31,函数引用类型调用
fun main() {
//方式一
login("张三", "123") { msg, code ->
{
}
//函数引用环节 ,函数通过函数引用::来变成函数类型的对象
login("张三", "李四", ::responseResultImp)
}
}
fun responseResultImp(msg: String, pwd: Int): Unit {
}
inline fun login(name: String, pwd: String, resposneResult: (String, Int) -> Unit) {
}
- Kotlin中函数类型作为返回值类型
package com.example.myapplication.kotlinlearn02
//TODO 32.Kotlin的函数类型作为返回类型
fun main() {
val result = showFun("你好")//result是个函数类型
result("dd", 3)
}
fun show(info: String): Boolean { //函数返回Boolean值
return false;
}
fun showFun(info: String): (String, Int) -> String {
println("我是show函数info:$info")
return { name, age ->
"name=$name,age=${age}"
}
}
- 匿名函数和具名函数
package com.example.myapplication.kotlinlearn02
//TODO 33.Kotlin中的匿名函数和具名函数
fun main() {
//匿名函数
showPersonInfo("Derry", 38, '男', "学习KT语言中") {
println(it)
}
println()
//具名函数
showPersonInfo("Derry", 38, '男', "学习KT语言中", ::showResultImpl)
}
fun showResultImpl(it: String) {
println("显示具名:$it")
}
inline fun showPersonInfo(
name: String,
age: Int,
sex: Char,
study: String,
showResult: (String) -> Unit
) {
val str = "name:$name,age:$age,sex:$sex,study:$study"
showResult(str)//这个lambda只是起了一个名字,并不是一个真正的函数,真正的实现是上边的println语句
}
- kotlin可空的特性
package com.example.myapplication.kotlinlearn03
//TODO 34.Kotlin语言可空性的特点
fun main() {
//TODO name不能为空,如果为空,编译会报错
var name: String = "Derry"
//TODO 第二种情况 声明的时候指定为可空
var name2: String? = "Derryhello"
name2 = null
println(name2?.length)//如果name2为null,就不执行?后边的区域
}
- kotlin安全调用操作符
package com.example.myapplication.kotlinlearn03
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.capitalize
//TODO 35.Kotlin语言的安全调用操作符
fun main() {
var name: String? = "xuyuanzhi"
val c = name?.capitalize() //name是可空类型,可能是null,如果想要使用name,必须给出补救措施
//如果name是Null,就不会执行?后边的区域代码,所以就不会崩溃。
println(c)
}
- Kotlin中带let的安全调用
package com.example.myapplication.kotlinlearn03
//TODO 36.kotlin中使用带let的安全调用
fun main() {
val name: String? = null
//如果name真的是null,就不执行?.let{}这一大块区域的代码
var r = name?.let {
// it==name本身,所以是String类型的
if (it.isBlank()) {
"Default"
} else {
"[$it]"
}
}
println(r)
}
- Kotlin中的非空断言操作符
package com.example.myapplication.kotlinlearn03
import androidx.compose.ui.text.capitalize
//TODO 37.Kotlin语言中的非空断言操作符
fun main() {
var name: String? = null
name!!.capitalize()//!!是断言,不管name是不是null,都会执行.capitalize(),所以就报空指针异常了,所以要慎用
//结论,如果百分百能够保证name是有值的,才能使用!!(否则有Java空指针异常),否则进来使用?
}
- if判断null值的情况
package com.example.myapplication.kotlinlearn03
//TODO kotlin中使用if判断Null值情况
fun main() {
var name: String? = null
//if(补救措施)
if (name != null) {
var r = name.capitalize()
println(r)
} else {
println("name is null")
}
}
- Kotlin的空合并操作符
package com.example.myapplication.kotlinlearn03
//TODO kotlin中使用if判断Null值情况
fun main() {
var name: String? = null
//if(补救措施)
if (name != null) {
var r = name.capitalize()
println(r)
} else {
println("name is null")
}
}
- 异常处理与自定义异常
package com.example.myapplication.kotlinlearn03
//TODO kotlin中使用if判断Null值情况
fun main() {
var name: String? = null
//if(补救措施)
if (name != null) {
var r = name.capitalize()
println(r)
} else {
println("name is null")
}
}
- kotlin中先决条件函数
package com.example.myapplication.kotlinlearn03
//TODO 41.kotlin中的先决条件函数
fun main() {
val value1: String? = null
var value2: Boolean = false
checkNotNull(value1) //抛个异常
requireNotNull(value1)//
require(value2) {
println("我是傻逼")
}
}
- kotlin中的substring
package com.example.myapplication.kotlinlearn03
//TODO 42.Kotlin中的substring
const val INFO = "xyz is Success"
fun main() {
val indexOf = INFO.indexOf('i')
println(INFO.substring(0, indexOf))
println(INFO.substring(0 until indexOf))
}
- 43 kotlin中的split操作
package com.example.myapplication.kotlinlearn03
//TODO 43.Kotlin语言的split操作
fun main() {
val jsonText = "x1,x2,x3,x4"
val list: List<String> = jsonText.split(',')
println("分割后的list里面的元素有${list}")
list.forEach {
println(it)
}
//C++解构 KT也有解构
val (v1: String, v2, v3, v4) = list
println("$v1,$v2,$v3,$v4")
}
- kotlin中使用repace完成加密解密的操作
package com.example.myapplication.kotlinlearn03
//TODO 44.Kotlin中的replace完成加密解码操作
fun main() {
val sourcePwd = "AbcdefdsAKMNOfafadfagg"
println("原始密码为:$sourcePwd")
val newPwd = sourcePwd.replace(Regex("AKMNO")) {
"-"
}
println(newPwd)
//解密操作
val sourcePwdNew = newPwd.replace(Regex("[-]")) {
when (it.value) {
"-" -> "AKMNO"
else -> it.value
}
}
println("解密后的密码为$sourcePwdNew")
}
kotlin中==和===的比较
package com.example.myapplication.kotlinlearn03
//TODO 45.Kotlin中 ==与===的比较
fun main() {
// ==是内容的比较。相当于Java的equals
//===是引用的比较
val n1: String = "aaa"
val n2: String = "aaa"
println(n1.equals(n2))
println(n1 == n2)
println(n1 === n2)
}
- kotlin中字符串的遍历操作
package com.example.myapplication.kotlinlearn03
//TODO 46.Kotlin中字符串的遍历操作
fun main() {
val str = "abcdefg"
str.forEach {
println("字符是$it")
}
}
- Kotlin中数字类型安全转换操作符
package com.example.myapplication.kotlinlearn03
//TODO 47.Kotlin中数字类型的安全转换函数
fun main() {
val number: Int = "666".toInt()
println(number)
//如果转换成Int成功就返回Int,如果转换失败就返回Null
val number2: Int? = "666.6".toIntOrNull()
println(number2)
}
- Double与Int类型相互转化
package com.example.myapplication.kotlinlearn03
import kotlin.math.roundToInt
//TODO 48.Double转Int与类型格式化
fun main() {
println(65.4.toInt()) //toInt没有四舍五入的效果,是取低位的
println(66.8.roundToInt())//roundToInt有四舍五入的效果,”%“
val r: String = "%.3f".format(66.5554511)//后边保留小数点后三位
println(r)
}
3.Kotlin进阶
- apply函数的用法
package com.example.myapplication.kotlinlearn03
import androidx.compose.ui.text.toLowerCase
//TODO 49.Kotlin中apply的内置函数
fun main() {
val info = "Derry is successful"
//普通传统方式
println(info.length)
println("info的最后一个字符是${info[info.length - 1]}")
println("info全部转化成小写${info.toLowerCase()}")
//apply方式
info.apply {
//一般大部分情况下,匿名函数都会持有一个it,但是apply不会持有it,但会持有this this==info本身
//apply函数始终是返回info本身String类型
println(this)
println(length)
println("info的最后一个字符是${this[length - 1]}")
println("info全部转化成小写${this.toLowerCase()}")
}
//TODO apply函数的写法规则如下
//apply函数始终返回info本身,所以可以进行链式调用
info.apply {
println("info的长度是${this.length}")
}.apply {
println("info的最后一个字符是${this[length - 1]}")
}.apply {
println("info全部转化成小写${this.toLowerCase()}")
println(readLine())
}
//TODO 结论 apply的返回值 谁.apply,返回谁本身
//apply里没有it,只有this,this==xxx本身
//TODO 用法,使用中,不需要用apply的返回值,而是尽量使用链式调用,功能分层
}
- let函数
package com.example.myapplication.kotlinlearn03
//TODO 50.kotlin语言let的内置函数
//普通方式 对集合第一个元素相加
//let方式 对集合第一个元素相加
//普通方式 对值判null 并返回
//let方式 对值判null 并返回
fun main() {
val list: List<Int> = listOf(1, 2, 3, 4)
val value1 = list.first()
println(value1 + value1)
//TODO let方式对集合第一个元素相加
listOf(1, 2, 3, 4).let {
//it ==集合本身
//let作为内置函数,会以最后一行作为返回值
it.first() + it.first()
}
//TODO apply总结
//1.apply函数的返回类型 永远是调用者本身
//2. apply函数的匿名函数体{持有的是this==info本身}
//TODO let总结
// 1.let函数的返回值是 函数最后一行的返回值
// let函数持有的是it,it等于调用者本身
//TODO 普通方式,对值判null 并返回
//TODO let解决对值判null 并返回
}
fun get(value: String?): String {
return value?.let { //如果value为null 则不会执行函数体里的东西,如果不为null ,则执行?:后边的东西
"欢迎${value}回来"
} ?: "你传递的是null"
}
//简化版本
fun get2(value: String?) = value?.let { //如果value为null 则不会执行函数体里的东西,如果不为null ,则执行?:后边的东西
"欢迎${value}回来"
} ?: "你传递的是null"
- run函数的综合案例
package com.example.myapplication.kotlinlearn03
//TODO 51.Kotlin语言中run内置函数
fun main() {
//1.run函数的特点 字符串演示
val str = "xyz is successful"
//TODO run函数的返回,根据匿名函数
str.run {
//以最后一行作为返回值,run函数函数体持有this,this==调用者本身
"a"
}
//TODO 2.具名函数判断长度
//这个是匿名函数
str.run {
}
//这个是具名函数,配合run
str.run(::isLong) //this==str
.run(::showText) //this==isLong函数返回类型Boolean的值本身
.run(::mapTest)
.run {
println(this)
}
println()
//TODO 上面的函数全部是具名函数调用给run运行
str.run {
if (length > 5) true else false
}.run {
if (this) "你的字符串合格" else "你的字符串不合格"
}.run {
"$this"
}.run {
println(this)
}
}
fun isLong(str: String) = if (str.length > 5) true else false
fun showText(isLong: Boolean) = if (isLong) "你的字符串合格" else "你的字符串不合格"
fun mapTest(str: String) = "[$str]"
- with操作符
package com.example.myapplication.kotlinlearn03
//TODO 52.kotlin中with函数
fun main() {
//TODO 和run函数是一模一样 持有this
val n1 = "hello"
with(n1) {
//this==str本身
}
val result1: Int = with(n1, ::getStrLenAction)
val result2: String = with(n1, ::getStrInfo)
//匿名操作
with(with(n1) {
n1.length
}) {
"你的字符串长度为$this"
}
}
fun getStrLenAction(str: String) = str.length
fun getStrInfo(str: String) = str
- also的用法
package com.example.myapplication.kotlinlearn03
import androidx.compose.ui.text.toLowerCase
//TODO also操作符
// str.also和apply差不多,永远是返回调用者本身
fun main() {
val str = "XUYUANZHI"
val r1: String = str.also {
}.also {
//可以链式调用
it == "a"
}
str.also {
println("str的原始值是$it")
}.also {
println("str转换成小写的效果是${it.toLowerCase()}")
}
}
- takeif操作符
package com.example.myapplication.kotlinlearn03
//TODO 54.takeIf海曙的使用
fun main() {
val name: String? = "aa"
val result = name.takeIf {
false
}
//如果为true,这个表达式返回name本身,如果为false,则返回null
println(result)
//企业用法,takeif+空合并操作符
name.takeIf { true } ?: "权限不够,被拒绝访问"
}
//TODO 总结:一般大部分情况下,都是takeIf+空合并操作符
- takeunless函数
package com.example.myapplication.kotlinlearn03
//TODO 55.takeUnless
fun main() {
"aaa".takeUnless {
false
} ?: "未经过任何初始化的值"
//takeUnless和takeif判断条件相反,但是效果一样
//false会返回调用者本身,true会返回null
}
4.Kotlin集合
- list的创建与获取
package com.example.myapplication.kotlinlearn03
//TODO 56.Kotlin语言的list创建与元素获取
fun main() {
val list: List<String> = listOf("张三", "李四", "王五")
//普通取值方式 ,索引
println(list[0])
println(list[1])
println(list[2])
println(list.get(0))
println(list.get(1))
println(list.getOrElse(2) { "越界" })
println(list.getOrElse(3) { "越界了" })
println(list.getOrNull(20))
println(list.getOrNull(2333) ?: "你越界了哦")
//总结:开发过程中,尽量使用getOrElse 或者 getOrNull 才能体现出Kotlin中的亮点
}
- 可变list集合的学习
package com.example.myapplication.kotlinlearn03
//TODO 57.Kotlin可变List集合学习
fun main() {
val list: MutableList<String> = mutableListOf("Derry", "zhangsan", "lisi")
//可变的集合
list.add("赵六")
list.remove("lisi")
println(list)
//不可变集合
val list2: List<Int> = listOf(123, 456, 789)
println(list2)
//不可变转为可变集合
val list3: MutableList<Int> = list2.toMutableList()
//可变集合变为不可变集合
val list4 = list3.toList() //无法完成可变的操作
//小结:KT语言中,分为可变集合与不可变集合 ,Kotlin中更加推荐使用不可变集合,防止造成数据丢失
}
- mutator学习
package com.example.myapplication.kotlinlearn03
//TODO 58.Kotlin语言的mutator函数学习
fun main() {
//1.mutator += -=操作
val list: MutableList<String> = mutableListOf("Derry", "DerryAll", "zhangsan", "lisi")
list += "张三"
list -= "李四"
println(list)
//2.removeIf
// list.removeIf{ //如果是true,自动遍历整个可变集合,一个一个元素的删除
// true
// }
list.removeIf {
it.contains("D") //过滤包含D的元素
}
println(list)
}
- list集合的遍历
package com.example.myapplication.kotlinlearn03
//TODO 59.List集合遍历学习
fun main() {
val mList: List<Int> = listOf<Int>(1, 2, 3, 4, 5, 6)
println(mList)//输出list详情而已,不是遍历集合
//第一种遍历
for (item: Int in mList) {
println("item:$item")
}
//第二种遍历
mList.forEach {
//it==每一个元素
println("item:$it")
}
//第三种方式
mList.forEachIndexed { index, i ->
println("下标是$index,值是$i")
}
}
- kotlin中解构语法过滤元素学习
package com.example.myapplication.kotlinlearn04
//TODO 60.Kotlin语言解构语法过滤元素学习
fun main() {
val list: List<String> = listOf("李元霸", "李小龙", "李连杰")
var (v1, v2, v3) = list
var (_, va1, va2) = list //_不是变量,是用来过滤结构赋值的,拒收值,不接收赋值给我
}
- 61Set元素的创建与获取
package com.example.myapplication.kotlinlearn04
//TODO 61.Kotlin中Set创建与元素获取
//set 定义不允许重复
//
fun main() {
val set: Set<String> = setOf("张三", "李四", "王五", "李四")
println(set)
println(set.elementAt(0))
println(set.elementAt(3))//越界 ,会崩溃
println()
println(set.elementAtOrElse(3) { "越界了" })
println(set.elementAtOrNull(3)) //得不到会返回null
}
- 可变集合set
package com.example.myapplication.kotlinlearn04
fun main() {
val set: MutableSet<String> = mutableSetOf("李元霸", "李连杰")
set += "张三"
set -= "李四"
set.remove("王五")
}
- Kotlin集合转换和快捷函数学习
package com.example.myapplication.kotlinlearn04
//TODO 63.Kotlin语言集合转换和快捷函数学习
fun main() {
//1.定义可变list集合
val list: MutableList<String> = mutableListOf("张三", "李四", "王五")
println(list)
//2.list转set自动去重
val set: Set<String> = list.toSet()
println(set)
//4.快捷函数去重distinct
println(list.distinct())
}
- Kotlin中的数组类型
package com.example.myapplication.kotlinlearn04
//TODO 64.Kotlin中的数组类型
// IntArray inArrayOf
// DoubleArray doubleArrayOf
fun main() {
val intArray = intArrayOf(1, 2, 3, 4)
println(intArray[1])
println(intArray.elementAtOrNull(0) ?: "aaa")//尽量不会崩溃
//OrNull要配合空合并操作符来使用
println(intArray.elementAtOrElse(55) { 3 })
//TODO 3.List集合转数组
listOf<Char>('a', 'b', 'c', 'd').toCharArray()
}
- map集合
package com.example.myapplication.kotlinlearn04
import androidx.compose.animation.scaleOut
//TODO 65.Kotlin中Map的创建
fun main() {
//第一种方式
val map1: Map<String, Double> = mapOf<String, Double>("xuyuanzhi" to 22.3, "lal" to 33.3)
//第二种方式
val map2 = mapOf(Pair("aaa", 33.2), Pair("ddd", 22.5))
//TODO 读取map的值
println(map1["xuyuanzhi"])//运算符重载了
println(map1.get("xuyuanzhi"))//运算符重载
//方式二
println(map1.getOrDefault("xuyuanzhi", -1))
println(map1.getOrDefault("xuyuanzhi") { -1 })
//方式三,和Java一样,获取不到会崩溃
println(map1.getValue("xuyuanzhi"))
//TODO 遍历map的值
//第一种方式
map2.forEach {
// it 每一个元素都是一个map,key value 结构。 it类型为 Map.Entry<String,Int>
println("K:${it.key},V:${it.value}")
}
println()
//第二种方式
map2.forEach { key: String, value: Double -> //把it覆盖了
println("key是$value,value 是 $value")
}
//第三种方式
map2.forEach { (key: String, value: Double) ->
println("key 是$key,value是$value")
}
//第四种方式
for (item: Map.Entry<String, Double> in map2) {
println("${item.key},value是${item.value}")
}
//TODO 可变集合Map的操作
val map3: MutableMap<String, Int> = mutableMapOf(Pair("Derry1", 123), Pair("xuyuanzhi", 456))
map3 += "aaa" to 23
map3 += "BBB" to 45
map3 -= "Derry"
map3["cc"] = 888
map3.put("Dddd", 999)
//如果在map里没有找到999的元素,那么先把999添加到里边去,然后再从map里边获取999的元素
map3.getOrPut("999") {
66
}
println(map3)
}
- Kotlin的计算属性与防范竞态条件
package com.example.myapplication.kotlinlearn04
//TODO 70.Kotlin语言的计算属性与防范竞态条件
class Derry {
val number: Int = 0
get() = field
//计算属性 (field 永远是描述name的值),如果一个变量没有赋值,那么就没有field这个东西。
//TODO 防范静态条件 当你调用成员,这个成员可能为null,可能为空值,就必须采用防范竞态条件,这个是KT编程的规范化
// 防范静态条件尽量使用(?+内置函数+空合并操作符)
var info: String? = null
fun getStudentInfo(): String {
return info?.let { //info如果不为null,则执行let函数里的,如果为null,则执行?:后边的语句
if (it.isBlank()) {
"你原来是空值"
} else {
"$it"
}
} ?: "info你原来是null,请检查代码"
}//,
}
fun main() {
//val修饰的变量 没有set函数
Derry().number
// 计算属性
}
- kotlin的主构造函数
package com.example.myapplication.kotlinlearn04
//主构造函数:规范来说,都是增加_xxx的方式,临时的输入类型,不能直接用,需要接收下来,成为变量才能用
class Students(_name: String, _age: Int) {
val name: String = _name
fun show() {
println("nieg")
}
}
//TODO 71.Kotlin语言的主构造函数学习
fun main() {
val student = Students("张三", 56)
}
- Kolin中的构造函数
package com.example.myapplication.kotlinlearn04
class Student2(var name: String, var age: Int) { //主构造函数 ,推荐这样写
//如果想完成多个构造函数重载的话,就用次构造才能做到
//次构造函数必须调用主构造函数,否则编译不通过
constructor(name: String) : this(name, 33) {
}
//三个参数的构造函数
constructor(name: String, age: Int, sex: Char) : this(name, 33) {
}
}
//TODO 构造函数的默认参数
// 主构造和次构造都有默认参数时,优先使用主构造,然后再使用次构造
class Animal(name: String = "啦啦啦") {
val name = name
override fun toString(): String {
println("ddd")
return "aa"
}
}
fun main() {
val s1 = Student2("张三", 18, '男') //调用三个参数的构造函数,首先会去先调用主构造函数,然后调用次构造函数
val a1 = Animal()
println(a1.toString())
}
- 类的初始化顺序
package com.example.myapplication.kotlinlearn03
//TODO 76.Kotlin语言构造初始化顺序学习
fun main() {
//重点:Init代码块和类成员是同时生成的,
}
- lateinit学习 延迟初始化
package com.example.myapplication.kotlinlearn04
//TODO 77.Kolin里边延迟初始化lateinit学习
class kt77 {
lateinit var name: String;
fun show() {
if (::name.isInitialized) {//判断name有没有初始化
}
}
//TODO 我们再使用延迟初始化字段的时候,一定要用::name.isInitialized 这个来判断,因为这个字段一碰就会崩溃,所以不要随便用
}
fun main() {
}
- by lazy 的使用
package com.example.myapplication.kotlinlearn04
class k78 {
val database: String by lazy {
"aaa" //只有用的时候才会加载
}
}
//TODO 78.惰性初始化by lazy
// lateinit 是在使用的时候,手动加载的懒加载方式,然后再使用
// by lazy 是在使用的时候,自动加载的懒加载方式,然后再使用
fun main() {
}
- 崩溃小陷阱
package com.example.myapplication.kotlinlearn04
class kt79(_info: String) {
val content: String = getInfoMethod()
private val info = _info
private fun getInfoMethod() = info
}
//TODO 1.陷阱一:如果init函数里要用到类属性,那么属性初始化要放在init函数之前
// 2.陷阱二: 类后边的函数要用到变量,要在这个函数之前进行初始化
// 3.陷阱三:
// 总结:为了以后不出现陷阱三,所有的类成员都放到最前面就好了
fun main() {
println("${kt79("Derry").content.length}") //会崩,因为执行先执行构造方法,然后执行getInfoMentod,这个时候info还没有初始化,所以会崩
}
5.Kotlin高级
- 继承与重载的open关键字
package com.example.myapplication.kotlinlearn05
import androidx.compose.animation.scaleOut
import com.example.myapplication.kotlinlearn04.Student2
// public final class Person
// open 去除 final修饰
open class Person(private val name: String) { //构造参数私有化,子类不可访问
private fun showName() = "父类的名字是$name"
fun showName1() = "父类的名字是$name"
open fun myPrintln(): Unit = println(showName())
}
class Student(private val subName: String) : Person(subName) {
private fun showName() = "子类的名字是$subName"
override fun myPrintln(): Unit = println(showName()) //此函数以及被子类重写了
}
//TODO 82.Kotlin的继承与重载的open关键字
fun main() {
val person: Person = Student("aa")
person.myPrintln()
println(person is Person)
println(person is Student)
// is +as 配合来使用
if (person is Student) {
// (person as Person).myPrintln() 这个就算转换到父类,也是调用到子类的方法
println((person as Person).showName1())
}
}
- Kotlin类型转换
package com.example.myapplication.kotlinlearn05
class kt84 {
}
fun main() {
//智能类型转换
// xxx as xxx 从一个类型转换到另一个类型
}
- Kotlin中Any类的超类
package com.example.myapplication.kotlinlearn05
//TODO 85.Kotlin的Any超类
// 在kt中,所有的类都隐式继承了Any(),你不写默认就有
// 在Java中,所有的类都隐式集成了 extends Object,你不写 ,默认就有
// Any在Kotlin设计中,只提供标准,看不到实现,实现在各个平台处理好了
class Person3 {
}
fun main() {
}
- Kotlin对象声明
package com.example.myapplication.kotlinlearn05
object kt86 {
/*
object 对象类背后做了什么
public static final K86 INSTANCE;
private K86() {} //主构造废除一样的效果
static {
K86 var0=new k86()
INSTANCE =var0
//直接把init代码搬到这里来了,因为主构造函数被私有化,所以把东西搬到这里来了
String var1="K86 init..."
System.out.println(var1)
}
public final void show(){
}
*/
}
//TODO 86.Kotlin的对象声明
fun main() {
}
- Kotlin中的对象表达式
package com.example.myapplication.kotlinlearn05
open class kt87 {
open fun add(info: String) = println("K87 add: $info")
open fun del(info: String) = println("K87 del: $info")
}
//TODO 87.Kotlin的对象表达式
fun main() {
//TODO 匿名 对象表达式方式
val p1: kt87 = object : kt87() {
override fun add(info: String) {
println("我是匿名表达方式$info")
}
override fun del(info: String) {
println("我是匿名表达方式:$info")
}
}
p1.add("aaa")
p1.del("ddd")
val p2: kt87 = k87Impl()
p2.add("张三")
p2.del("李四")
//TODO 对Java的接口 用对象表达式方式
val p3: Runnable = object : Runnable {
override fun run() {
println("Java Runnable run...")
}
}
p3.run()
val p4: Runnable = Runnable { //Kotlin不支持这种简洁方式,只有Java可以
println("aaa")
}
p4.run()
}
class k87Impl : kt87() {
override fun add(info: String) {
println("我是具名函数add$info")
}
override fun del(info: String) {
println("我是具名函数del${info}")
}
}
- kotlin中的伴生对象
package com.example.myapplication.kotlinlearn05
class kt88 {
companion object {
//伴生对象 ,本身是一个静态内部类
val name = "许远志" //直接会生成静态的 private static final String name="许远志”
val info = "lalala是吧"
fun showInfo() = println("显示:$info")
// public static final kt88.companion companion =new kt88.companion()//给外界调用的
}
}
//TODO 88.Kotlin的伴生对象,
// 伴生对象很大程度上和Java的static静态差不多的 不管kt88实例化多少次,伴生对象只加载一次, 伴生对象只初始化一次
fun main() {
}
- 内部类
package com.example.myapplication.kotlinlearn05
//TODO 内部类
class Body() { //外部类
val name: String = "aaa"
class Heart { //嵌套类 加上inner修饰符才能变成内部类 ,
val nameHeart: String = "bbb"
fun show() {
//println(name)
}
}
}
//嵌套类的特点,外部的类能访问内部的嵌套类, 内部的嵌套类不能访问外部类的成员
// 内部类的特点: 内部的类能访问外部的类 外部的类能访问内部的类
class kt89 {
inner class kt899 {
}
}
fun main() {
//内部类
kt89().kt899()
//嵌套类
Body.Heart()
}
- Kotlin的数据类
package com.example.myapplication.kotlinlearn05
//普通类
class ResponseResultBean(var msg: String, var code: Int, var data: String) : Any()
//TODO set get 构造函数
//相当于接收 服务器返回的JavaBean 现在kotlin叫做数据类
data class ResponseResultBean2(var msg: String, var code: Int, var data: String) : Any()
//TODO set get 构造函数 copy 克隆 toString hashCode equals 结论:数据类 生成更加丰富
//TODO 90.Kotlin的数据类
fun main() {
//TODO 1.ToString方法
println(ResponseResultBean("aa", 12, "aa"))
//普通类 toString 调用了windows打印的toString
println(ResponseResultBean2("aa", 12, "aa"))
// 数据类 any,重写了父类的toString
//TODO 2.==方法
//普通类==的实现 Any父类的实现 是equals 是比较两个对象的引用
//数据类==是值的比较,所以 内容一样就是true
//TODO 总结:普通类的Any 的== 是引用的比较 数据类any的==被重写了 是值的比较
}
- Kotlin的解构操作
package com.example.myapplication.kotlinlearn05
//普通类
class Student1(var name: String, var age: Int, var sex: Char) {
//解构操作 必须从component1开始
operator fun component1() = name
operator fun component2() = age
operator fun component3() = sex
}
class kt92 {
}
//TODO 92.Kotlin的解构操作
fun main() {
var (name, age, sex) = Student1("张三", 89, '男')
//数据类默认就有解构操作
}
- Kt的运算符重载
package com.example.myapplication.kotlinlearn05
//TODO 93.Kotlin的运算符重载
class AddClass(var number1: Int, var number2: Int) {
operator fun plus(p1: AddClass) = (number1 + p1.number1) + (number2 + p1.number2)
}
fun main() {
//运算符重载
println(AddClass(2, 2) + AddClass(3, 3))
}
- 枚举类
package com.example.myapplication.kotlinlearn05
//枚举的值等于枚举本身
enum class Week {
星期一,
星期二,
}
fun main() {
}
- 枚举类型定义函数
package com.example.myapplication.kotlinlearn05
data class LimbInfo(var limbInfo: String, var length: Int) {
fun show() = println("$limbInfo,长度是 $length")
}
enum class Limbs(private var limbsInfo: LimbInfo) {
LEFT_HAND(LimbInfo("左手", 88)),//左手
RIGHT_HAND(LimbInfo("左手", 88)),//左手
; //结束枚举值
fun show() = "四肢是${limbsInfo.limbInfo} ,长度是${limbsInfo.length}"
fun update(limbsInfoUpdate: LimbInfo) {
this.limbsInfo.limbInfo = limbsInfoUpdate.limbInfo //也可以更新枚举值,这个枚举值的对象是实例化的时候传进来的
}
}
//结论:枚举的主构造参数必须与枚举值保持一致
// 95.枚举类型定义函数
fun main() {
println(Limbs.LEFT_HAND.show()) //枚举值的主构造参数不要管,是枚举值直接调用show来显示的
}
- Kotlin的代数数据类型
package com.example.myapplication.kotlinlearn05
enum class Exam {
Fraction1,//分数差
Fraction2,//分数及格
Fraction3,//分数良好
Fraction4,//分数优秀
;//枚举结束
}
class Teacher(private val exem: Exam) {
fun show() =
when (exem) {
Exam.Fraction1 -> "该学生的分数很差"
Exam.Fraction2 -> "该学生的分数及格"
Exam.Fraction3 -> "该学生的分数良好"
Exam.Fraction4 -> "该学生的分数优秀"
//不需要使用else ,由于我们的函数是用枚举类型来判断处理的,这个就属于代数数据类型,不需要写else了
//因为when表达式非常明确了,只有四种类型,不会出现else其他,所以不需要写
}
}
//TODO 96.Kotlin的代数数据类型讲解
//定义
fun main() {
}
- 密封类
package com.example.myapplication.kotlinlearn05
//密封类 :在于控制子类数量可控,以免被非法继承
// 枚举类:在于控制状态数量可控
//
sealed class kt97 {
}
//TODO 97.密封类 我们的成员必须要有类型(object class) 2. 并且是继承本类
fun main() {
}
- 数据类使用条件
package com.example.myapplication.kotlinlearn05
//TODO 98.数据类使用条件
// 数据类至少必须有一个参数的主构造函数 ;必须有val var 修饰的参数,数据类不能使用abstract,inner, open 等修饰
fun main() {
}
6.kotlin实战
- 接口的定义
package com.example.myapplication.kotlinlearn06
interface IUSB {
var usbVersionInfo: String //USB版本信息
var usbInsertDevice: String// 插入的设备信息
fun insertUSB(): String //被插入的动作
}
open class Mouse(override var usbVersionInfo: String, override var usbInsertDevice: String) : IUSB {
override fun insertUSB(): String {
TODO("Not yet implemented")
}
}
class shubiao : Mouse("aa", "a"), IUSB {
override fun insertUSB(): String {
return super.insertUSB()
}
}
//TODO 99.Koltin的接口定义详解
// 1.接口里面和接口本身都是public open的,所以不需要open
// 2.接口不能有主构造
// 3.实现类不仅仅要重写接口的函数,也要重写接口的成员
// 4.接口实现代码区域要加Override来修饰
fun main() {
}
- 接口的默认实现(只是有这个功能,很少使用)
package com.example.myapplication.kotlinlearn06
interface IUSB2 {
val usbVersionInfo: String
get() = "你好小白" //接口的默认实现
}
class Mouse2 : IUSB2 {
override val usbVersionInfo: String
get() = super.usbVersionInfo
}
// TODO 接口的默认实现
fun main() {
val iusb: IUSB2 = Mouse2()
println(iusb.usbVersionInfo)
}
- Kotlin的抽象类
package com.example.myapplication.kotlinlearn06
abstract class BaseActivity {
fun onCreate() {
setContentView(getLayoutID())
initView()
initData()
initXXX()
}
private fun setContentView(layoutID: Int) = println("你好啦啦啦")
abstract fun getLayoutID(): Int
abstract fun initView()
abstract fun initData()
abstract fun initXXX()
}
class MainActivity : BaseActivity() {
override fun getLayoutID(): Int {
return 1223
}
override fun initView() {
}
override fun initData() {
}
override fun initXXX() {
}
fun show() = super.onCreate()
}
//TODO 101-Kotlin的抽象类详解
fun main() = MainActivity().show()
- 泛型类讲解
package com.example.myapplication.kotlinlearn06
abstract class BaseActivity {
fun onCreate() {
setContentView(getLayoutID())
initView()
initData()
initXXX()
}
private fun setContentView(layoutID: Int) = println("你好啦啦啦")
abstract fun getLayoutID(): Int
abstract fun initView()
abstract fun initData()
abstract fun initXXX()
}
class MainActivity : BaseActivity() {
override fun getLayoutID(): Int {
return 1223
}
override fun initView() {
}
override fun initData() {
}
override fun initXXX() {
}
fun show() = super.onCreate()
}
//TODO 101-Kotlin的抽象类详解
fun main() = MainActivity().show()
- 内置函数+泛型
package com.example.myapplication.kotlinlearn06
class kt103<T>(private val isR: Boolean, private val obj: T) {
fun getObj(): T? = obj.takeIf { isR }
}
//TODO 103.内置函数+泛型
fun main() {
val s1 = Student("张三", 33)
println(kt103(true, s1).getObj())
println(kt103(false, s1).getObj())
kt103(true, s1).getObj().apply {
println(this)
}!!
}
- Kotlin泛型变换实战
package com.example.myapplication.kotlinlearn06
class kt104<T>(val isMap: Boolean, val inputType: T) {
//false,返回null
//true ,返回调用者本身
inline fun <R> map(mapAction: (T) -> R): R? = mapAction(inputType).takeIf { isMap }
}
//TODO 104.Kotlin的泛型变换实战;’
fun main() {
val p1: kt104<Int> = kt104(isMap = true, inputType = 333)
val r: String? = p1.map {
"aaa"
}
println("变换后的结果是$r")
}
-
kotlin泛型类的约束
T:Person 这样写的话只有Person 以及Person的子类才可以传进去。 -
Kotlin抽象类
package com.example.myapplication.kotlinlearn06
abstract class BaseActivity {
fun onCreate() {
setContentView(getLayoutID())
initView()
initData()
initXXX()
}
private fun setContentView(layoutID: Int) = println("你好啦啦啦")
abstract fun getLayoutID(): Int
abstract fun initView()
abstract fun initData()
abstract fun initXXX()
}
class MainActivity : BaseActivity() {
override fun getLayoutID(): Int {
return 1223
}
override fun initView() {
}
override fun initData() {
}
override fun initXXX() {
}
fun show() = super.onCreate()
}
//TODO 101-Kotlin的抽象类详解
fun main() = MainActivity().show()
- kotlin中vararg关键字
package com.example.myapplication.kotlinlearn06
class kt106<T>(vararg objects: T, var isMap: Boolean) {
//out 我们的T只能被读取,不能被修改
private val objectArray: Array<out T> = objects
fun showObj(index: Int): T? = objectArray[index].takeIf { isMap }
}
//TODO 106.kotlin的vararg关键字(动态参数)
fun main() {
val p = kt106("aaa", "ddd", isMap = true)
println(p.showObj(0))
println(p.showObj(1))
println(p.showObj(2))
}
- Kotlin的[]操作符
package com.example.myapplication.kotlinlearn06
class kt107<T>(vararg objects: T, var isMap: Boolean) {
//out 我们的T只能被读取,不能被修改
private val objectArray: Array<out T> = objects
fun showObj(index: Int): T? = objectArray[index].takeIf { isMap }
//运算符重载
operator fun get(index: Int): T? = objectArray[index].takeIf { isMap }
}
//TODO 107.Kotlin的[]操作符讲解
fun main() {
val p = kt107("aaa", "ddd", isMap = true)
p[0]
println(p[1])
}
6.1协变 逆变
- 协变讲解
package com.example.myapplication.kotlinlearn06
interface Producer<out T> {//out T 代表此泛型在整个生产者里边 这个T只能被读取,不能被修改了
fun getT(): T
}
interface Consumer<in T> {
//消费者 ,只能修改 不能被读取
fun consumer(item: T) //只能被修改
}
//TODO 108.协变讲解-KT
fun main() {
//TODO 协变 相当于Java里的? extends Person 这样保证了只能接受 Person以及Person的子类
}
- 协变讲解
package com.example.myapplication.kotlinlearn06
interface Producer<out T> {//out T 代表此泛型在整个生产者里边 这个T只能被读取,不能被修改了
fun getT(): T
}
interface Consumer<in T> {
//消费者 ,只能修改 不能被读取
fun consumer(item: T) //只能被修改
}
//TODO 108.协变讲解-KT
fun main() {
//TODO 协变 相当于Java里的? extends Person 这样保证了只能接受 Person以及Person的子类
// 协变 可以在使用处协变 也可以在生命处协变【Java只有在使用处协变】
// 逆变 子类去接收父类 in T 相当于Java 里的 ? super Person 这样保证了 能接收Person以及 Person的父类
// 总结: 协变:out 父类 = 子类
// 逆变: in 子类=父类
}
- Kotlin中使用in 和out
package com.example.myapplication.kotlinlearn06
class kt110 {
}
// 小结,当我们对整个类里边的泛型,只能修改,不能读取时,可以声明为逆变
// 当我们对泛型,只能读取,不能给外界修改更新时,可以声明为协变
class SetClass<out T>(item: T) { //声明式逆变泛型,Java不能在声明处,只能在使用处
// 200个函数,对T只能修改,不能对外界读取
val res = item
fun get(): T {
return res
}
}
// TODO 110-Kotlin中使用in和out
fun main() {
val list: List<Int> //不可变
val list2: MutableList<Int> //可变集合
}
- reified关键字 监测 泛型T的类型
package com.example.myapplication.kotlinlearn06
class Object1
inline fun <reified T> showTypeInfo(item: T) {
if (Object1() is T) {
println("aa")
} else if (item is Object1) {
}
val list = listOf("aa", "bb")
list.shuffled().first()//随机获取集合中的元素
}
class kt111 {
}
//TODO reified 是真泛型类型的监测
fun main() {
}
- Kotlin 的 扩展函数
package com.example.myapplication.kotlinlearn06
class Object1
inline fun <reified T> showTypeInfo(item: T) {
if (Object1() is T) {
println("aa")
} else if (item is Object1) {
}
val list = listOf("aa", "bb")
list.shuffled().first()//随机获取集合中的元素
}
class kt111 {
}
//TODO reified 是真泛型类型的监测
fun main() {
}
- 超类上定义扩展函数
package com.example.myapplication.kotlinlearn06
private fun Any.showPrintlnContent() = println("当前的内容是$this") //将方法私有化,this永远是调用者本身
//TODO kt113-超类上定义扩展函数
fun main() {
true.showPrintlnContent()
}
- Kotlin泛型的扩展函数
package com.example.myapplication.kotlinlearn06
//TODO 114.Kotlin的泛型扩展函数
fun <T> T.showContentInfo() =
println("${if (this is String) "你的字符串长度是$length" else "你不是字符串,你的内容是$this"}")
fun main() {
"许远志".showContentInfo()
true.showContentInfo()
}
- Kotlin的标准函数与泛型扩展函数
package com.example.myapplication.kotlinlearn06
//TODO 115.Kotlin的标准函数与泛型扩展函数
fun main() {
"string".mLet {
true
"aa"
}
}
private inline fun <I, O> I.mLet(lambda: (I) -> O): O = lambda(this)
- Kotlin的内置函数与扩展属性
package com.example.myapplication.kotlinlearn06
class kt116
//扩展属性
val String.myInfo: String
get() = "许远志"
fun String.showPrintln(): String {
println("aaa")
return this
}
//TODO 116.Kotlin内置函数与扩展属性
fun main() {
// run 和let会根据最后一行的返回值作为返回值
// run 持有this let 持有it
//TODO 扩展属性
println("this".myInfo)
"333".showPrintln().myInfo
}
- Kotlin可空类型扩展函数
package com.example.myapplication.kotlinlearn06
class kt116
//扩展属性
val String.myInfo: String
get() = "许远志"
fun String.showPrintln(): String {
println("aaa")
return this
}
//TODO 116.Kotlin内置函数与扩展属性
fun main() {
// run 和let会根据最后一行的返回值作为返回值
// run 持有this let 持有it
//TODO 扩展属性
println("this".myInfo)
"333".showPrintln().myInfo
}
- infix中缀表达式
package com.example.myapplication.kotlinlearn06
//TODO 118.Kotlin的infix关键字
//自定义的中级表达式+扩展函数一起使用
// infix 中缀表达式是简化我们的代码
private infix fun <C1, C2> C1.go(c2: C2) {
}
fun main() {
123.go("许远志")
123 go "许远志"
}
- 导入扩展文件
package com.example.myapplication.kotlinlearn06
//导入扩展文件
import com.example.myapplication.kotlinlearn06.randomItemValue
//TODO 119.Kotlin的定义扩展文件
fun main() {
val list: List<String> = listOf("张三", "李四", "王五")
//第一种不使用扩展文件
println(list.shuffled().first())
println(list.randomItemValue())
}
package com.example.myapplication.kotlinlearn06
fun <E> Iterable<E>.randomItemValue() = shuffled().first()
- 重命名扩展函数
package com.example.myapplication.kotlinlearn06
//导入扩展文件
import com.example.myapplication.kotlinlearn06.randomItemValue as p
//TODO 119.Kotlin的定义扩展文件
fun main() {
val list: List<String> = listOf("张三", "李四", "王五")
//第一种不使用扩展文件
println(list.shuffled().first())
println(list.p())
}
7. 手写内置函数
- 手写apply函数
package com.example.myapplication.kotlinlearn06
class kt121 {
}
fun main() {
"许远志".mApply {
"aaa"
}.apply { }
}
/*
private 表示私有
inline 因为我们的函数是高阶函数,需要使用内联对lambda进行优化处理
fun<INPUT> 函数中声明一个泛型
INPUT.mApply 表示所有的类型都能调用这个函数,
INPUT.()代表对这个泛型进行了匿名函数扩展 ,函数扩展持有的this,this持有的调用者本身
Unit 永远返回调用者本身
lambda(this) 永远都有this ,this可以省略
*/
private inline fun <INPUT> INPUT.mApply(lambda: INPUT.() -> Unit): INPUT {
lambda()
return this;
}
- DSL学习
package com.example.myapplication.kotlinlearn06
import java.io.File
//TODO 122.Kotlin的DSL学习
// TODO dsl学习 就是领域专用语言(Domain Specified Language/DSL) Gradle,Json,XML等
inline fun File.applyFile(action: (String, String) -> Unit): File {
action(name, this.name)
return this
}
fun main() {
}
- Kotlin的map变换函数
package com.example.myapplication.kotlinlearn06
class kt123 {
}
//TODO 123.Kotlin的map变换函数
fun main() {
var list: MutableList<String> = mutableListOf("张三", "李四", "王五")
//原理:及时吧匿名函数最后一个返回值加入到新的集合里面去,
var list2 = list.map {
//it 等于 每一个元素 ”张三" "李四" "王五"
"it 是$it"
"$it"
}.map {
"$ it的长度是${it.length}"
}
println(list2)
}
- 变换函数flatmap
package com.example.myapplication.kotlinlearn06
class kt124 {
}
//TODO 124.Kotlin的变换函数flatMap
fun main() {
val list: List<String> = mutableListOf("张三", "李四", "王五")
val list2 = list.flatMap { //每次都会返回一个集合 ,把买一个集合加到新集合里
listOf("aaa", "bbb", "ccc") //会做扁平化处理 ,把每个元素变成一个新的集合,然后又加入到新的集合去
}
val list3 = list.map {
"赵六"
}
println(list2)
println(list3)
}
- 过滤函数filter
package com.example.myapplication.kotlinlearn06
class kt125 {
}
//TODO 125.过滤函数 filter
fun main() {
val names = listOf("张三", "李四", "王五")
val result = names.filter {
it == "张三" //如果为true 会加入到新的集合 如果为false 则过滤掉
}
names.filter {
it.contains('张')
}.map {
println("$it")
}
println(result) //新集合 把过滤后的元素加入新集合
}
- 合并函数zip
package com.example.myapplication.kotlinlearn06
class kt126 {
}
//TODO 126.Kotlin的合并函数zip
fun main() {
val names = listOf("张三", "李四", "王五")
val ages = listOf(1, 2, 3)
val zip: List<Pair<String, Int>> = names.zip(ages)
println(zip.toMap())
println(zip)
//遍历
zip.forEach {
//
println("姓名是${it.first},年龄是${it.second}")
}
//解构
zip.toMap().forEach { (k, v) ->
println("k是$k,v是$v")
}
}
- 函数式编程(响应式编程)
package com.example.myapplication.kotlinlearn06
class kt126 {
}
//TODO 126.Kotlin的合并函数zip
fun main() {
val names = listOf("张三", "李四", "王五")
val ages = listOf(1, 2, 3)
val zip: List<Pair<String, Int>> = names.zip(ages)
println(zip.toMap())
println(zip)
//遍历
zip.forEach {
//
println("姓名是${it.first},年龄是${it.second}")
}
//解构
zip.toMap().forEach { (k, v) ->
println("k是$k,v是$v")
}
}
- Kotlin的互操作性和可空性
package com.example.myapplication.kotlinlearn06
//TODO 128.Kotlin的互操作性与可空性
fun main() {
var name: String? = "a"//接收Java的变量的时候要用string?来接收Java的值
name = null
println(name?.length)
}
7.1 Kotlin的单例模式
package com.example.myapplication.kotlinlearn06
//TODO 单例模式
//1.饿汉式的实现 KT版本 先把实例实例化出来
object Singleton
//2. 懒汉式实现
class Singleton2 private constructor() {
companion object {
private var instance: Singleton2? = null
get() {
if (field == null) {
field = Singleton2()
}
return field
}
fun getInstance(): Singleton2? = instance
}
}
// 3.线程安全版本
class Singleton3 private constructor() {
companion object {
private var instance: Singleton3? = null
get() {
if (field == null) {
field = Singleton3()
}
return field
}
@Synchronized
fun getInstance(): Singleton3? = instance
}
}
//4. 双重校验锁版本
class Singleton4 private constructor() {
companion object {
val instance: Singleton4 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { Singleton4() }
}
}
7.2 Kotlin的注解
- @JvmName
@file:JvmName("Stu") //在编译时把类名改成自定义的名称
package com.example.myapplication.kotlinlearn06
class kt130 {
}
//TODO 130.注解@jvmName
fun main() {
println("hello world")
}
- JvmField注解
package com.example.myapplication.kotlinlearn06
class kt131 {
@JvmField //把反编译后的Java代码修饰符变成public
val names = listOf("张三", "李四", "王五")
}
// TODO 131.注解@JvmField
fun main() {
}
- JvmStatic注解
package com.example.myapplication.kotlinlearn06
class MyObject {
companion object {
@JvmField
val TARGET = "张三"
@JvmStatic //加上这个注解之后,在Java里使用这个方法就可以直接用了,
fun showAction(name: String) = println("$name 要去 $TARGET 玩")
}
}
//TODO 133.注解@JvmStatic与Kotlin的关系
fun main() {
//KT 端
println(MyObject.TARGET)
MyObject.showAction("啦啦啦")
}
7.3 手写RxJava
package com.example.myapplication.kotlinlearn06
class kt134 {
}
// TODO 134.手写RxJava操作符
// Lambda是以最后一行作为返回值
fun main() {
create {
"333"
}.map {
"张三"
true
"ddd"
}.map {
}
}
class RxJavaCoreClassObject<T>(val valueItem: T)
inline fun <INPUT, OUTPUT> RxJavaCoreClassObject<INPUT>.map(mapAction: INPUT.() -> OUTPUT): RxJavaCoreClassObject<OUTPUT> {
val mapResult = valueItem.mapAction()
return RxJavaCoreClassObject(mapResult)
}
//create 接收一个lambda表达式作为参数,然后执行lambda的函数体,然后等create参数调用
inline fun <CREATE_OUTPUT> create(createLambda: () -> CREATE_OUTPUT): RxJavaCoreClassObject<CREATE_OUTPUT> {
val createResult: CREATE_OUTPUT = createLambda()
return RxJavaCoreClassObject(createResult)
}