侧边栏壁纸
博主头像
叩钉壹刻博主等级

7分技术,3分管理,2分运气

  • 累计撰写 25 篇文章
  • 累计创建 13 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

kotlin 语言基础

鹿心肺语
2022-08-22 / 0 评论 / 0 点赞 / 12 阅读 / 67744 字

第一章 kotlin 前提

1.1 kotlin与JVM虚拟机关系

[Kotlin/Java/Groovy] → 编译环节 → 产生字节码 → JVM产生指令 → 系统命令式执行

1.2 kotlin的意义

  1. 各个语言的核心集合
  2. 可以作为全栈语言

第二章 kotlin 基础篇

2.1 hello word 输出

fun main(){
	println("hello world")
}

2.2 Kotlin内置数据类型(引用类型)

  1. 字符类型:
    • String(字符串)
    • Char(单字符)
  2. 数值类型:
    • Int(整型)
    • Float(浮点数)
    • Double(小数)
  3. 布尔类型
    • Boolean True/False
  4. 集合类型
    • List(列表元素)
    • Set(无重复的集合元素)
    • Map(键值对)

2.3 声明变量

  1. 格式1: var 变量名:数据类型 [= 初始值]

    作用: 可以读写

    fun main(){
    	var name:String = "demo"
    	println(name)
    }
    
  2. 格式2: val 变量名:数值类型 [= 初始值]

    作用: 只能读

    fun main(){
    	val name:String = "demo"
    	// name = "demo1"  --> 报错
    	println(name)
    }
    

2.4 const val、val、var 声明区别

  1. const val 定义在函数外,编译时常量
  2. val 只读类型
  3. var 读写类型

2.5 查看字节码和反编译的java代码

  1. 查看字节码

    图2-1: 查看字节码

  2. 反编译java代码

    图2-2: kotlin字节码转java代码

2.6 Range表达式: ..

  1. 格式: 初始值..结束值

    作用: 从初始值到结束值

    fun main() {
        var num: Int = 59
        if (num in 0..59) {
            println("不及格")
        } else {
            println("及格")
        }
    }
    

2.7 When表达式: when

  1. 格式: val 变量名:变量类型 = when(入参值){ 匹配入参值1 → 返回信息 … else → 返回信息}

    作用: 一值多匹配结果

    fun main() {
    	var week: Int = 1
    	var result: Any = when (week % 7) {
    		0 -> "星期天"
    		1 -> "星期一"
    		2 -> "星期二"
    		3 -> "星期三"
    		4 -> "星期四"
    		5 -> "星期五"
    		6 -> "星期六"
    		else -> "没有匹配到"
    	}
    	println(result)
    }
    

2.8 String模版: 输出模版

  1. 格式: “{变量名}” 或 ”变量名”

    作用: 简化模版格式,其中 ”$变量名” 只能用于无文本紧密连接的情况

    fun main() {
    	val name: String = "zhangsan"
    	val age: Int = 18
    	println("姓名:${name},年龄:$age")
    }
    

2.9 控制台键入值: 输入内容

  1. 格式: readline()

    作用: 读取输入的一行内容

    fun main(args: Array<String>) {
    	print("请输入内容: ")
    	val content: String? = readLine()
    	println("你所输入的内容为:${content}")
    }
    
  2. 格式: val input:Scanner = Scanner(System.in)

    作用: 声明Java版本的读取

    import java.util.Scanner
    
    fun main(args: Array<String>) {
    	val input: Scanner = Scanner(System.`in`)
    	print("请输入内容:")
    	val content: String = input.nextLine()
    	println("你所输入的内容为:${content}")
    }
    

2.10 常规函数

  1. 参数中不含默认的函数

    格式: 函数修饰符 fun 函数名(参数名1:参数类型1…参数名n:参数类型n):返回数据类型 { 代码段 }

    注意: 函数修饰符默认为public

    fun main() {
    	var result = add(2, 3)
    	println("2 + 3 = $result")
    }
    
    public fun add(x: Int, y: Int): Int {
    	return x + y
    }
    
  2. 参数中含默认值的函数

    格式: 函数修饰符 fun 函数名(参数名1:参数类型1,参数名2:参数类型2=默认值…参数名n:参数类型n):返回数据类型 { 代码段 }

    注意: 默认值可以没有顺序,但传参赋值一定是从左到右

    fun main() {
    	var result = add(3)
    	println(result)
    }
    
    public fun add(x: Int = 2, y: Int = 4): Int {
    	return x + y
    }
    
  3. 具名参数的函数

    格式[调用]: val 变量名[:变量类型] = 函数名(参数名1=参数值1…参数名n=参数值n)

    注意: 调用时,不需要从左到右依次赋值

    fun main() {
    	var result = add(y = 3)
    	println(result)
    }
    
    public fun add(x: Int = 2, y: Int): Int {
    	return x + y
    }
    

2.11 空返回: Unit

  • 返回类型可以为空,空时可以输出内容[ kotlin.Unit ]

    注意: 不加返回值类型,默认为Unit

    fun main() {
    	method()
    	method1()
    	
    	//输出 kotlin.Unit
    	var result = method2()
    	println(result)
    }
    
    //默认为Unit, 可加入return语句,但必须为Unit类型
    fun method() {
    	return println()
    }
    
    //返回类型Unit, 可加入return语句,但必须为Unit类型
    fun method1(): Unit {
    	return println()
    }
    
    fun method2(): Unit {
    	println()
    }
    

2.12 无法正常返回: Nothing

  • 一般正常返回的值,都是有返回类型的,默认都是为空返回. 但存在无法返回的情况,例如抛出异常等,所以就存在了Nothing

    注意: Nothing是所有类型的子类

    fun main() {
    	throwError()
    }
    
    fun throwError(): Nothing {
    	// throw 和 TODO 都是可以抛出异常的
    	//TODO("主动抛出异常")
    	throw Exception("主动抛出异常")
    }
    

2.13 反引号: `

  • 用途: 1. 用做函数的名称; 2. 在调用其他语言过程中含有Kotlin语法的关键字(经常); 3. 具体功能的转译

    public class JavaClass {
    	public void in(String content) {
    		System.out.println("输出的内容为:" + content);
    	}
    }
    
    fun main(args: Array<String>) {
    	val javaCode: JavaClass = JavaClass()
    	javaCode.`in`("kotlin 传递给 java代码的内容")
    }
    

2.14 进阶函数

  1. 匿名函数

    函数实现在方法之后,不需要显式声明调用

    fun main(args: Array<String>) {
    	val len: Int = "hello".count()
    	println("hello的个数为${len}")
    
    	val lenforL: Int = "hello".count {
    		it == 'l'
    	}
    	println("hello中的l的个数为${lenforL}")
    }
    
  2. 函数的隐式返回: 函数不需要单独定义,在需要处直接声明实现

    不带参数: 可直接使用声明的名称调用

    fun main(args: Array<String>) {
    	//函数的声明
    	val method: () -> String
    
    	//函数的实现
    	method = {
    		"这是返回的字符"
    	}
    
    	//函数的使用
    	println(method)
    }
    

    带参数: 需要进行传递所需参数内容。在只有一个参数时,注意默认会有一个 it 关键字

    fun main(args: Array<String>) {
    	val add: (x: Int, y: Int, z: Int) -> Int = { x: Int, y: Int, z: Int ->
    		x + y + z
    	}
    
    	println("1,2,3 三值只和为:${add(1, 2, 3)}")
    }
    
  3. 函数返回的lambda推导

    在不确定返回值的情况下,可不用写返回类型,自动推导出返回值的类型

    注意: 当返回值类型不止一种的时候,返回的类型则为Any

    fun main(args: Array<String>) {
    	var method = { x: String, y: Int ->
    		"输入内容,字符串:${x},数值:${y}"
    	}
    
    	println(method("demo", 1))
    }
    
  4. 函数中的参数为函数

    参数为函数作为返回值,处理返回来的内容信息

    fun main() {
    
    	loginSQL("root", "123456") { code: Int, status: String, msg: String ->
    		println("请求的结果如下:状态值:${code},状态:${status},提示信息:${msg}")
    	}
    
    	//其余写法
    	loginSQL("root", "123456", { code: Int, status: String, msg: String ->
    		println("请求的结果如下:状态值:${code},状态:${status},提示信息:${msg}")
    	})
    
    	loginSQL("root", "123456", Response = { code: Int, status: String, msg: String ->
    		println("请求的结果如下:状态值:${code},状态:${status},提示信息:${msg}")
    	})
    }
    
    //模拟前端发送请求
    public fun loginSQL(username: String, password: String, Response: (code: Int, status: String, msg: String) -> Unit) {
    	if (username != null && password != null) {
    		if (loginSQLAPI(username, password)) {
    			Response(200, "ok", "数据库访问成功")
    		} else {
    			Response(500, "error", "数据库访问失败")
    		}
    	} else {
    		TODO("用户名或者密码为空")
    	}
    }
    
    //数据库的数据
    const val name = "root"
    const val pwd = "123456"
    
    //后台接口API
    private fun loginSQLAPI(username: String, password: String): Boolean {
    	return if (username == name && password == pwd) true else false
    }
    

2.15 内联模式: inline

  • 作用对象: 存在函数中参数为函数的方法

    优点: 1. 不会存在性能损耗; 2. 不存在对象的开辟

    注意: 使用内联模式的函数,其调用的函数方法属性必须为public

    fun main() {
    
    	loginSQL("root", "123456") { code: Int, status: String, msg: String ->
    		println("请求的结果如下:状态值:${code},状态:${status},提示信息:${msg}")
    	}
    
    	//其余写法
    	loginSQL("root", "123456", { code: Int, status: String, msg: String ->
    		println("请求的结果如下:状态值:${code},状态:${status},提示信息:${msg}")
    	})
    
    	loginSQL("root", "123456", Response = { code: Int, status: String, msg: String ->
    		println("请求的结果如下:状态值:${code},状态:${status},提示信息:${msg}")
    	})
    }
    
    //模拟前端发送请求
    public inline fun loginSQL(username: String, password: String, Response: (code: Int, status: String, msg: String) -> Unit) {
    	if (username != null && password != null) {
    		if (loginSQLAPI(username, password)) {
    			Response(200, "ok", "数据库访问成功")
    		} else {
    			Response(500, "error", "数据库访问失败")
    		}
    	} else {
    		TODO("用户名或者密码为空")
    	}
    }
    
    //数据库的数据
    const val name = "root"
    const val pwd = "123456"
    
    //后台接口API
    public fun loginSQLAPI(username: String, password: String): Boolean {
    	return if (username == name && password == pwd) true else false
    }
    

2.16 函数类型引用: ::

  • 作用对象: 存在函数中参数为函数的方法

    优点: 可以将返回参数的函数进行显式的声明和实现

    fun main() {
    	login("root", "123456", ::processResponse)
    }
    
    fun processResponse(code: Int, status: String, msg: String) {
    	println("访问结果信息:状态值:${code},状态:${status},信息提示:${msg}")
    }
    
    public inline fun login(name: String, pwd: String, Response: (code: Int, status: String, msg: String) -> Unit) {
    	if (name == "root" && pwd == "123456") {
    		Response(200, "ok", "访问成功")
    	} else {
    		Response(200, "error", "访问失败")
    	}
    }
    

2.17 返回值为函数

  • 将函数的返回值由类型改为函数,可双重调用,调取函数返回函数的值

    fun main(args: Array<String>) {
    
    	val subMethod: (age: Int) -> String = method("zhangsan")
    
    	println(subMethod(19))
    
    }
    
    inline fun method(name: String): (age: Int) -> String {
    	println("你的名字是:${name}")
    	return {
    		"实际的年龄为:${it - 1}"
    	}
    }
    

2.18 具名函数和匿名函数对比

  • 区别: 具名函数可以将函数声明实现在其他地方,匿名函数必须在调用的时候实现

    关联: 具名函数 == 函数类型引用 ; 匿名函数 == 函数中的参数为函数

    fun main(args: Array<String>) {
    	//匿名调用
    	method("zhangsan", 18) {
    		println("实际年龄为:${it - 1}")
    	}
    	//具名调用
    	method("zhangsan", 18, ::optionImpl)
    }
    
    fun method(name: String, age: Int, option: (age: Int) -> Unit) {
    	println("你的姓名为:${name},虚岁年龄为:${age}")
    	return option(age)
    }
    
    fun optionImpl(age: Int): Unit {
    	println("实际年龄为:${age - 1}")
    }
    

2.19 属性可空特性: ?

  • 注意: 默认声明一般是为不空

    fun main(args: Array<String>) {
    	//不可空属性
    	var name: String = "demo"
    	println(name)
    
    	//可空属性
    	val num: Int? = null
    	println(num)
    }
    

2.20 属性安全调用

  1. 可空类型的安全调用

    格式: 属性名?.方法名()

    作用: 通过判断属性名是否为空,从而判断是否进行执行属性名后的方法

    fun main(args: Array<String>) {
    	var name: String? = "demo"
    	//属性名?.方法 ,当属性值不为空时执行后面的方法,属性值为空时不执行后面的方法
    	println("当前值为:${name?.capitalize()}")
    	name = null
    	println("改变后的值为:${name?.capitalize()}")
    }
    
  2. let安全调用

    格式: 属性名?.let{ 代码段 }

    作用: 当属性名不为空时,执行后面的代码段,且返回最后一行的值

    fun main(args: Array<String>) {
    	var name: String? = "demo"
    	val result1: String? = name?.let {
    		it.capitalize()
    	}
    	println("当前值为:${result1}")
    
    	name = null
    	val result2: String? = name?.let {
    		it.capitalize()
    	}
    	println("改变之后的值为:${result2}")
    }
    
  3. 非空断言

    格式: 属性名!!.方法名()

    注意: 断言的内容一定要事先知道预期的结果,因为方法是会执行,不论属性为什么值

    fun main(args: Array<String>) {
    	var name: String? = null
    	//非空断言,属性值无论是什么都会执行后续的方法
    	println(name!!.capitalize()) //这里会报错,空指针异常
    }
    
  4. if判空

    格式: if(属性名 [比较] 预设值) 操作

    fun main(args: Array<String>) {
    	var name: String? = null
    
    	if (name == null) {
    		println("当前的name值为空")
    	} else {
    		println("当前的name值不为空")
    	}
    }
    
  5. 空合并

    格式: 属性名?:为空时的值

    fun main(args: Array<String>) {
    	var name: String? = null
    
    	val result: String = name ?: "null"
    	println("当前的name值为:${name}")
    }
    

2.21 异常处理: try…catch

  • 作用: 主要为了预防一些可见的异常和一些不可见的异常

    fun main(args: Array<String>) {
    	try {
    		var info: String? = null
    		checkNotNullException(info)
    
    	} catch (e: Exception) {
    		e.printStackTrace()
    	}
    }
    
    fun checkNotNullException(value: String?) {
    	value ?: throw ValueIsNullException()
    }
    
    public class ValueIsNullException : NullPointerException("空指针异常")
    

2.22 先决条件

  • 作用: 为了判断属性是否为空

    fun main(args: Array<String>) {
    	var name: String? = null
    
    	//为null时进行异常提示:java.lang.IllegalStateException: Required value was null.
    	checkNotNull(name)
    
    	//定义带有返回提示的异常信息:java.lang.IllegalStateException: 属性值不能为空
    	checkNotNull(name, lazyMessage = { "属性值不能为空" })
    
    	//当为false是抛出异常,为true正常执行:java.lang.IllegalStateException: Check failed.
    	check(name?.let { true } ?: false)
    
    	//带有返回提示的异常信息:java.lang.IllegalStateException: 属性值不能为空
    	check(name?.let { true } ?: false, lazyMessage = {"属性值不能为空"})
    
    	//同理 require和check相似,requireNotNull和checkNotNull相似
    	requireNotNull(name)
    
    	requireNotNull(name, lazyMessage = { "属性值不能为空" })
    
    	require(name?.let { true } ?: false)
    
    	require(name?.let { true } ?: false, lazyMessage = { "属性值不能为空" })
    }
    

2.23 String类常用的方法

  1. subString方法

    用途: 分割字符串

    fun main(args: Array<String>) {
    	var str: String = "hello world"
    
    	val subStr1: String? = str.substring(0..5)
    	println("字符串0-5的字符为:${subStr1}")
    
    	val subStr2: String? = str.substring(0, str.indexOf(' '))
    	println("字符串从头到第一个为空格的字符为:${subStr2}")
    
    	val subStr3: String? = str.substring(0 until str.indexOf(' '))
    	println("字符串从头到第一个为空格的字符为:${subStr3}")
    }
    
  2. split方法

    用途: 分割字符串成若干子字符串数组

    fun main(args: Array<String>) {
    	var str: String = "hello world"
    
    	var splitStr: List<String> = str.split(' ')
    	println("当前分割结果为;${splitStr}")
    }
    
  3. replace方法

    用途: 替换字符中的部分内容

    fun main(args: Array<String>) {
    	var str: String = "hello world"
    
    	var result: String = str.replace('o', 'e')
    	println("替换后的结果为:${result}")
    }
    
  4. foreach方法

    用途: 用于循环某个内容

    fun main(args: Array<String>) {
    	var str: String = "hello world"
    
    	print("循环输出的结果为: ")
    	str.forEach {
    		print("${it} ")
    	}
    }
    
  5. ==和===比较

    区别: == 用于值或者内容的比较; === 除了值或内容比较外,还有引用的比较

    fun main(args: Array<String>) {
    	var str1: String = "hello world"
    	var str2: String = "hello world"
    
    	// == 用于值或内容的比较,与java中的equals相同
    	println("str1 == str2 的结果为:${str1 == str2}")
    	println("str1 == str2 的结果为:${str1.equals(str2)}")
    	
    	// === 用于引用比较
    	println("str1 === str2 的结果为:${str1 === str2}")
    }
    

2.24 类型转换

  1. String类型 → Int类型

    作用: 将String类型的值转化为Int类型的值

    fun main(args: Array<String>) {
    	val num: Int = "66".toInt()
    	println(num)
    
    	//转化失败将为null
    	var num1: Int? = "66.6".toIntOrNull()
    	println(num1)
    
    	var num2: Int? = "99".toIntOrNull()
    	println(num2)
    
    	var num3: Int? = "66.6".toIntOrNull()
    	println(num3 ?: "null值")
    }
    
  2. Double类型 → Int类型

    作用: 将Double类型的值转化为Int类型

    import kotlin.math.roundToInt
    
    fun main(args: Array<String>) {
    	// toInt()和roundToInt()四舍五入方式
    	println(65.13451234.toInt())
    	println(65.13451234.roundToInt())
    	println(65.612345.roundToInt())
    }
    
  3. Double类型 → String类型

    作用: 将Double类型格式化String类型

    fun main(args: Array<String>) {
    	var r: String = "%.3f".format(65.13451234)
    	println(r)
    }
    

2.25 内置函数

  1. apply内置函数

    特点: 入参默认含有this对象,返回对象本身类型

    fun main(args: Array<String>) {
    	var name: String = "demo"
    
    	//apply入参默认含有this对象
    	var result: String = name.apply {
    		println("你的名字为:${this.capitalize()}")
    	}
    
    	//apply返回对象本身
    	println("返回的结果为:${result}")
    }
    
  2. let内置函数

    特点: 入参默认含有it对象,返回最后一行的内容

    fun main(args: Array<String>) {
    	var name: String = "demo"
    
    	//let入参默认含有it对象
    	var result: Unit = name.let {
    		println("你的名字为:${it.capitalize()}")
    	}
    
    	//it返回代码块中最后一行内容
    	println("返回的结果为:${result}")
    }
    
  3. run 内置函数

    特点: 入参默认含有this对象,返回最后一行内容

    用法: 与apply和run相同.在链式调用时需要一个接一个

    fun main(args: Array<String>) {
    	var name: String = "demo"
    
    	//run入参默认含有this对象
    	var result: Unit = name.run {
    		println("你的名字为:${this.capitalize()}")
    	}
    
    	//run返回代码块中最后一行内容
    	println("返回的结果为:${result}")
    }
    
  4. with 内置函数

    特点: 入参默认含有this对象,返回最后一行内容

    用法: 与run不相同.在链式调用时,需要层层嵌套

    fun main(args: Array<String>) {
    	var name: String = "demo"
    
    	//run入参默认含有this对象
    	var result = with(name, {
    		println("你的名字为:${this}")
    	})
    
    	//run返回代码块中最后一行内容
    	println("返回的结果为:${result}")
    }
    
  5. also 内置函数

    特点: 入参默认含有it对象,返回对象本身

    fun main(args: Array<String>) {
    	var name: String = "demo"
    
    	//also入参默认含有it对象
    	var result = name.also {
    		println("你的名字为:${it.capitalize()}")
    	}
    
    	//also返回对象本身
    	println("返回的结果为:${result}")
    }
    
  6. takeif 内置函数

    特点: 如果takeif内的返回值为true则返回对象,否则返回nul

    fun main(args: Array<String>) {
    	var name: String? = "demo"
    
    	var result1 = name.takeIf { name?.let { true } ?: false }
    	println("初始值takeif结果为:${result1}")
    
    	name = null
    	var result2 = name.takeIf { name?.let { true } ?: false }
    	print("赋值为null后的结果为:${result2}")
    }
    
  7. takeunless 内置函数

    特点: 如果takeunless内的返回值为false则返回对象,否则返回null

    关联: 与takeif相反

    fun main(args: Array<String>) {
    	var name: String? = "demo"
    
    	var result1 = name.takeUnless { name?.let { false } ?: true }
    	println("初始值takeif结果为:${result1}")
    
    	name = null
    	var result2 = name.takeUnless { name?.let { false } ?: true }
    	print("赋值为null后的结果为:${result2}")
    }
    

2.26 List集合

  1. 长度不可变的List

    定义即初始化,该List可通过相应的方法增加、删除元素

    fun main(args: Array<String>) {
    	val strs: List<String> = listOf("list1", "list2", "list3")
    
    	//输出
    	println(strs)
    
    	//下标访问
    	println(strs.get(0))
    	println(strs[1])
    
    	//防止越界操作 getOrElse当越界后返回{}内的值
    	println(strs.getOrElse(3) { "越界" })
    
    	//防止越界操作 getOrNull当越界之后返回null值,一般配合空合并操作
    	println(strs.getOrNull(4) ?: "越界")
    
    	//添加元素 该方法为kotlin.collections
    	println(strs.plusElement("listNew1"))
    	//删除元素 该方法为kotlin.collections
    	println(strs.minusElement("listNew1"))
    }
    
  2. 长度可变的List

    定义可以初始化,该List可以直接增加、删除和修改元素

    fun main(args: Array<String>) {
    	val strs: MutableList<String> = mutableListOf("list1", "list2", "list3")
    
    	//增加操作 默认增加在最后
    	strs.add("listNew1")
    	println(strs)
    
    	//删除操作 如何删除的元素存在则删除,否则返回原数组内容
    	strs.remove("list1")
    	println(strs)
    
    	//将不可变list集合转化为可变list集合
    	val strs1: List<String> = listOf("new1", "new2", "new3")
    	val strs2: MutableList<String> = strs1.toMutableList()
    	println(strs2)
    }
    

    可变长度的List,在增加时可以通过 += 进行添加元素; 在删除时也可以通过 removeif 进行删除

    fun main(args: Array<String>) {
    	val strs: MutableList<String> = mutableListOf("list1", "list2", "list3")
    
    	//增加操作 默认增加在最后
    	strs += "listNew1"
    	println(strs)
    
    	//删除操作 对每一个元素判断是否包含字段值,包含则删除,不包含则保留
    	strs.removeIf {
    		it.contains("New")
    	}
    	println(strs)
    }
    
  3. 遍历List

    遍历不可变和可变长度的List集合

    fun main(args: Array<String>) {
    	val strs: List<String> = listOf("new1", "new2", "new3")
    	val strs1: MutableList<String> = strs.toMutableList()
    
    	//遍历 List-不可变 和 MutableList-可变 相同
    	print("for循环的结果为:")
    	for (item in strs1) {
    		print("${item} ")
    	}
    	println()
    
    	print("foreach循环的结果为:")
    	strs1.forEach({
    		print("${it} ")
    	})
    	println()
    
    	print("含有下标的forEachIndexed循环结果为:")
    	strs1.forEachIndexed({ index: Int, s: String ->
    		print("下标为 ${index} 的值为 ${s}   ;")
    	})
    	println()
    }
    

2.27 解构过滤

  • 通过对对象的解析,返回特定位置上的特定值

    注意: 当不需要某个位置的元素时,可以通过 _ 进行忽略

    fun main(args: Array<String>) {
    	val strs: List<String> = listOf("value1", "value2", "value3")
    
    	//对应位置的解构,不能过多的解析,否则就会报错
    	var (v1: String, _, v2: String?) = strs
    	println("解析结果为:${v1},${v2}")
    
    	// var (v1: String, _, _, v2: String?) = strs -- 报错,strs的list集合并没有第四个元素
    }
    

2.28 Set集合

  • 不可变的Set集合

    与长度不可变的List相似,但Set集合元素无重复

    fun main(args: Array<String>) {
    	//Set集合元素不重复
    	val strs: Set<String> = setOf("set1", "set2", "set3", "set1")
    	println(strs)
    
    	//访问 下标访问
    	println(strs.elementAt(1))
    
    	//访问 elementAtOrElse,当位置上没有值时返回{}内的内容
    	var result1: String = strs.elementAtOrElse(3, { "该位置没有值" })
    	println(result1)
    
    	//访问 elementAtOrNull,当位置上没有值时返回null 一般与空拼接结合使用
    	var result2: String = strs.elementAtOrNull(3) ?: "该位置没有值"
    	println(result2)
    
    	//增加元素
    	println(strs.plusElement("it"))
    	//删除元素
    	println(strs.minusElement("it"))
    }
    
  • 可变的Set集合

    与长度可变的List相似,但Set集合元素无重复

    fun main(args: Array<String>) {
    	val strs: MutableSet<String> = mutableSetOf("set1", "set2", "set3", "set1")
    	println(strs)
    
    	//增加元素
    	strs += "setNew"
    	println(strs)
    
    	strs.add("setNew1")
    	println(strs)
    
    	//删除元素
    	strs -= "setNew"
    	println(strs)
    
    	strs.remove("setNew1")
    	println(strs)
    }
    

2.29 List集合去重

  • 解决List集合中含有重复的元素

    fun main(args: Array<String>) {
    	val strs: List<String> = listOf("list1", "list2", "list3", "list1")
    	println("去重前的值:${strs}")
    
    	//去重方法1: 转化为Set集合
    	val strsSet: Set<String> = strs.toSet()
    	println("转化为Set集合去重后的结果:${strsSet}")
    
    	//去重方法2:转化为Set集合,在转化为List集合
    	val strsNew: List<String> = strs.toSet().toList()
    	println("先转化为Set集合,再转化为List集合去重后的结果:${strsNew}")
    
    	//去重方法3:通过distinct()方法去重
    	val strsDistinct: List<String> = strs.distinct()
    	println("通过Distinct()方法去重后的结果:${strsDistinct}")
    	//等价方法 strs.toMutableSet().toList()
    }
    

2.30 数组

  • 数组的类型

    数组类型赋值方法
    IntArrayintArrayOf
    DoubleArraydoubleArrayOf
    LongArraylongArrayOf
    ShortArrayshortArrayOf
    ByteArraybyteArrayOf
    FloatArrayfloatArrayOf
    BooleanArraybooleanArrayOf
    Arrayarrayof
  • 单一类型的一类值的集合

    fun main(args: Array<String>) {
    	val intArray: IntArray = intArrayOf(1, 2, 3, 4, 5, 7, 6)
    	println(intArray)
    
    	//访问元素
    	println(intArray[0])
    	println(intArray.get(1))
    
    	//访问 elementAtOrElse,当位置上没有值时返回{}内的内容
    	var result1: Int = intArray.getOrElse(10, { -1 })
    	println(result1)
    	//访问 elementAtOrNull,当位置上没有值时返回null 一般与空拼接结合使用
    	var result2: Int = intArray.getOrNull(10) ?: -1
    	println(result2)
    
    	//List集合转为数组,只有数据类型内含有的才可以转化,但除了Arrya之外
    	val strs: List<Char> = listOf('1', '2', '3', '4')
    	val strsToArray: CharArray = strs.toCharArray()
    	println(strsToArray)
    }
    

2.31 Map集合

  • 创建Map集合

    参数格式: 类型1 to 类型2 或者 Pair(类型1,类型2)

    fun main(args: Array<String>) {
    	var map1: Map<String, Any> = mapOf<String, Any>("code" to 200, "status" to "ok", "data" to listOf<String>("value1", "value2"))
    
    	var map2: Map<String, Any> = mapOf<String, Any>(Pair("code", 200), Pair("status", "ok"), Pair("data", listOf<String>("value1", "value2")))
    }
    
  • 访问Map集合

    fun main(args: Array<String>) {
    	var map1: Map<String, Any> =
    		mapOf<String, Any>("code" to 200, "status" to "ok", "data" to listOf<String>("value1", "value2"))
    
    	var map2: Map<String, Any> =
    		mapOf<String, Any>(Pair("code", 200), Pair("status", "ok"), Pair("data", listOf<String>("value1", "value2")))
    
    	//访问Map集合
    	println(map1["code"])
    	println(map1["status"])
    	println(map1.get("data"))
    
    	//访问字段 getOrDefault 当对象中没有该key值时就会返回后面的默认的value值,反之返回对象中的值
    	println(map1.getOrDefault("msg", "暂无此字段"))
    	//访问字段 getOrElse 当对象中没有该key值时就会返回后面的默认的value值,反之返回对象中的值
    	println(map1.getOrElse("msg", { "暂无此字段" }))
    }
    
  • 遍历Map集合

    fun main(args: Array<String>) {
    	var map1: Map<String, Any> =
    		mapOf<String, Any>("code" to 200, "status" to "ok", "data" to listOf<String>("value1", "value2"))
    
    	var map2: Map<String, Any> =
    		mapOf<String, Any>(Pair("code", 200), Pair("status", "ok"), Pair("data", listOf<String>("value1", "value2")))
    
    	map1.forEach { t, u ->
    		println("集合的key为:${t},value为:${u}")
    	}
    	println()
    
    	map1.forEach { (key: String, value: Any) ->
    		println("集合的key为:${key},value为:${value}")
    	}
    	println()
    
    	for (item: Map.Entry<String, Any> in map1) {
    		println("集合的key为:${item.key},value为:${item.value}")
    	}
    }
    
  • 可变Map集合操作

    fun main(args: Array<String>) {
    	var map: MutableMap<String, Any> =
    		mutableMapOf<String, Any>(Pair("code", 200),
    			Pair("status", "ok"),
    			Pair("data", listOf<String>("value1", "value2")))
    
    	//添加字段值
    	map += Pair<String, Any>("msg", "操作成功")
    	println(map)
    	map["field1"] = "value1"
    	println(map)
    
    	//获取或者存入值 getOrPut
    	val result = map.getOrPut("msg", { "暂无此字段的值" })
    	println(result)
    
    }
    

第三章 kotlin进阶篇

3.1 类: class

  1. 类与 filed 关键字

    注意: kotlin中的属性在经过转译之后,会将属性私有化,会提供对应的set或get方法.根据kotlin声明是var(读写属性)还是val(只读属性)进行具体提供

    //定义Person类,私有属性,会提供公有的set和get方法
    class Person {
    	var name: String? = null
    		get() = field
    		set(value) {
    			field = value
    		}
    
    	var age: Int? = 18
    
    }
    
    fun main(args: Array<String>) {
    
    	val person: Person = Person()
    
    	person.name = "demo"
    	println("创建的person对象,name赋值为:${person.name}")
    	person.age = 20
    	println("创建的person对象,age赋值为:${person.age}")
    }
    
  2. 类的计算属性和防范空的情况

    class Person2 {
    	var name: String? = null
    
    	//计算属性,针对于只读属性val进行操作
    	val randomNum: Int
    		get() = (1..100).shuffled().first()
    
    	//属性防范空的情况
    	public fun getNameInfo(): String {
    		return name?.let {
    			"成功赋值,值的内容是:${name}"
    		} ?: "没有赋值,当前为null"
    	}
    
    }
    
    fun main(args: Array<String>) {
    	var person: Person2 = Person2()
    
    	//计算属性的获取
    	println(person.randomNum)
    
    	//默认为空的输出情况
    	println(person.getNameInfo())
    	//重新赋值情况
    	person.name = "zhangsan"
    	println(person.getNameInfo())
    }
    
  3. 类的主构造

    作用: 主要是为了在声明时进行初始化

    注意: 主构造的变量默认为临时类型,在声明创建后不能获取该临时变量.若需要使用,则需要声明主构造中的变量属性或者赋值在类内部声明变量

    • 默认构造并且赋值到类的内部变量进行访问
    //默认主构造且采取赋值到类内部变量
    class Person(_name: String, _age: Int) {
    	var name: String = _name
    	var age: Int = _age
    }
    
    fun main(args: Array<String>) {
    	var person: Person = Person("zhangsan", 20)
    
    	// person._name -> 无法进行该访问
    	println("Person初始化内容信息为:name = ${person.name}; age = ${person.age}")
    }
    
    • 声明主构造变量的变量属性, val 或者 var
    class Person(var name: String, var age: Int) {
    }
    
    fun main(args: Array<String>) {
    	var person: Person = Person("zhangsan", 20)
    	
    	println("Person初始化内容信息为:name = ${person.name}; age = ${person.age}")
    }
    
  4. 次构造函数

    作用: 可初始化类中的部分属性

    注意: 可重载;需实现主构造,为主构造赋值,让主构造统一管理

    class Person(_name: String) {
    
    	var Cname: String = _name
    	var Cage: Int = 18
    	var Cinfo: String? = null
    
    	constructor(name: String, age: Int) : this(name) {
    		println("次构造函数中的属性为:name=${name};age=${age}")
    		this.Cname = name
    		this.Cage = age
    	}
    
    	constructor(name: String, age: Int, info: String?) : this(name) {
    		println("次构造函数中的属性为:name=${name};age=${age};info=${info}")
    		this.Cname = name
    		this.Cage = age
    		this.Cinfo = info
    	}
    
    }
    
    fun main(args: Array<String>) {
    
    	var person1: Person = Person("zhangsan")
    	println(person1.Cname)
    
    	var person2: Person = Person("zhangsan", 20)
    	println("Person初始化内容信息为:name = ${person2.Cname}; age = ${person2.Cage}")
    
    	var person3: Person = Person("zhangsan", 20, "个人信息")
    	println("Person初始化内容信息为:name = ${person3.Cname}; age = ${person3.Cage}; info = ${person3.Cinfo}")
    }
    
  5. 类参数的默认值和调用顺序

    优先调用主构造函数,其次再为次构造函数

    主构造是在init代码块中,次构造是在contructor中进行

3.2 init代码块

  • 相当于java中的代码块{} ,但不是静态代码块{}

    class Person(name: String, password: String) {
    	init {
    		println("主构造函数调用")
    		require(name.isNotBlank()) { "参数为空" }
    	}
    
    	constructor(name: String, password: String, info: String) : this(name, password) {
    		println("次构造函数参数为:name=${name};password:${password};info=${info}")
    	}
    }
    
    fun main(args: Array<String>) {
    	var person: Person = Person("zhangsan", "123456", "个人")
    }	 
    

3.3 懒加载: lateinit

  • 用法: 在属性上进行的操作,通过关键字lateinit实现变量的懒加载.通过 ::变量名.isInitialized 获取变量名是否已经初始化

    fun main() {
    	var b: Base = Base()
    	b.initInfo()
    	//需要先加载属性,才能进行使用
    	b.showInfo()
    }
    
    class Base {
    	//延迟初始化,用到的时候在进行加载数据
    	lateinit var info: String
    
    	fun initInfo() {
    		info = "成功"
    	}
    
    	fun showInfo() {
    		if (::info.isInitialized) {
    			println(info)
    		} else {
    			println("忘记加载内容")
    		}
    	}
    }
    

3.4 惰性加载: by lazy

  • 用法: 作用在变量名上,需要实现by lazy中的方法

    fun main() {
    
    	//var b: Base = Base()
    	//Thread.sleep(5000)
    	//println(b.database)
    
    	var b: Base = Base()
    	Thread.sleep(5000)
    	println(b.database2)
    }
    
    class Base {
    	//val database: String = readSqlDataBase()
    
    	val database2 by lazy { readSqlDataBase() }
    
    	fun readSqlDataBase(): String {
    		println(1)
    		println(2)
    		println(2)
    		println(2)
    		println(2)
    		println(2)
    		println(2)
    		println(2)
    		println(1)
    		return "Mysql"
    	}
    }
    

3.5 类的继承与重写

  • 继承: 通过 : 完成父到子的继承

  • 重写: 方法名相同,存在于继承之间

    fun main() {
    	var b: Base = Child("zhangsan")
    	b.basePrintln()
    }
    
    // kotlin所有的类和函数都是final属性的,如果需要可继承,则需要加入open关键字
    open class Base(private val name: String) {
    	private fun showName(): String {
    		return "父类:姓名是:${name}"
    	}
    
    	open fun basePrintln() = println(showName())
    }
    
    class Child(private val subname: String) : Base(subname) {
    
    	private fun showName(): String {
    		return "子类:姓名是:${subname}"
    	}
    
    	override fun basePrintln() = println(showName())
    }
    

3.6 类的类型转化

  • 存在父类和子类之间的转化,调用父类或者子类的方法

    import java.io.File
    
    fun main() {
    
    	var b: Base = Child("zhangsan")
    	b.basePrintln()
    
    	println(b is Base)
    	println(b is Child)
    	println(b is File)
    
    	//is+as进行转换
    
    	if (b is Child) {
    		(b as Child).basePrintln()
    	}
    
    	if (b is Base) {
    		println((b as Base).test())
    	}
    }
    
    // kotlin所有的类和函数都是final属性的,如果需要可继承,则需要加入open关键字
    open class Base(private val name: String) {
    	private fun showName(): String {
    		return "父类:姓名是:${name}"
    	}
    
    	open fun basePrintln() = println(showName())
    
    	fun test(): String {
    		return "父类:姓名是:${name}"
    	}
    }
    
    class Child(private val subname: String) : Base(subname) {
    
    	private fun showName(): String {
    		return "子类:姓名是:${subname}"
    	}
    
    	override fun basePrintln() = println(showName())
    }
    
  • 在调用的过程中,如果之前有进行as转化,那之后在使用时,就是as转化后的对象

    import java.io.File
    
    fun main() {
    
    	var b: Base = Child("zhangsan")
    	b.basePrintln()
    
    	//智能声明类型,已确定后续使用子类的方法
    	(b as Child).childPrintln()
    
    	b.childPrintln()
    
    }
    
    // kotlin所有的类和函数都是final属性的,如果需要可继承,则需要加入open关键字
    open class Base(private val name: String) {
    	private fun showName(): String {
    		return "父类:姓名是:${name}"
    	}
    
    	open fun basePrintln() = println(showName())
    
    }
    
    class Child(private val subname: String) : Base(subname) {
    
    	private fun showName(): String {
    		return "子类:姓名是:${subname}"
    	}
    
    	fun childPrintln() = println(showName())
    }
    

3.7 Any超类

  • 任何类的父类,提供了规范接口定义

    fun main() {
    	//Any类的toString只提供标准,不提供实现
    	println(obj().toString())
    }
    
    //每个类都默认继承了Any类
    class obj : Any() {
    
    }
    

3.8 类的单例对象: object

  • 作用: 在类上的声明,使得类成为为单例模式

    fun main() {
    	println(Base)
    	println(Base)
    	println(Base)
    	println(Base)
    	println(Base)
    
    	println(Base.show())
    }
    
    //单例的实例,也是类名,只有一个被创建
    object Base {
    	init {
    		print("Base create")
    	}
    
    	fun show(): Unit {
    		println("show函数")
    	}
    }
    

3.9 对象表达式

  • 在继承接口时,只能使用唯一的一种方式进行创建对象 object:类型{实现方法}

    fun main() {
    
    	var it: Base = object : Base() {
    		override fun add(info: String) {
    			//super.add(info)
    			println("匿名对象add:${info}")
    		}
    
    		override fun del(info: String) {
    			//super.del(info)
    			println("匿名对象del:${info}")
    		}
    	}
    
    	it.add("1234")
    	it.del("12345")
    
    	// 具名方式
    	var it2: Child = Child()
    	it2.add("1234")
    	it2.del("12345")
    
    	// java的Runable实现
    	var p3: Runnable = object : Runnable {
    		override fun run() {
    			//TODO("Not yet implemented")
    			println("Runable...")
    		}
    	}
    	p3.run()
    
    	var p4 = Runnable {
    		println("run..")
    	}
    	p4.run()
    
    	//KT接口只有一种对象表达式,没有简洁的写法,对象表达式object:类型{实现方法}
    	object : RunableKT {
    		override fun run() {
    			//TODO("Not yet implemented")
    			println("1111run")
    		}
    	}.run()
    }
    
    open class Base {
    	open fun add(info: String) = println("add: ${info}")
    	open fun del(info: String) = println("del: ${info}")
    }
    
    class Child : Base() {
    	override fun add(info: String) {
    		//super.add(info)
    		println("具名对象add:${info}")
    	}
    
    	override fun del(info: String) {
    		//super.del(info)
    		println("具名对象add:${info}")
    	}
    }
    
    interface RunableKT {
    	fun run()
    }
    

3.10 伴生对象: companion

  • 只会创建一次,类似于Java中的static静态块

    fun main() {
    	println(Base.info)
    	Base.showInfo()
    }
    
    //因为kotlin中没有java的那种static静态,所以产生了compannon伴生对象
    //无论创建多少次companion只创建一次
    class Base {
    	companion object {
    		const val info: String = "demo"
    		fun showInfo(): Unit = println("info: $info")
    	}
    }
    

3.11 内部类和嵌套类

  • 默认情况下是嵌套类,类的内部的类含有inner关键字才能内部类

  • 内部类可以访问外部的属性,嵌套类不能访问外部属性

    fun main() {
    
    	Body("isOk").Heart().run()
    	Body("isOk").Hand().Left().run()
    
    	Outer.Net().showInfo("info")
    }
    
    //外部和内部类
    class Body(_bodyInfo: String) {
    	val bodyInfo: String = _bodyInfo
    
    	fun show() {
    		Heart().run()
    	}
    
    	// inner 使得内部类可以访问外部类,外部类可以直接访问内部的类
    	inner class Heart {
    		fun run(): Unit = println("心跳运行:${bodyInfo}")
    	}
    
    	inner class Hand {
    		inner class Left {
    			fun run(): Unit = println("左手:${bodyInfo}")
    		}
    	}
    }
    
    //默认情况下就是嵌套类,除非是由外部类传递到内部类
    class Outer {
    	val info: String = "ok"
    
    	fun show() {
    		Net().showInfo(info)
    	}
    
    	class Net {
    		fun showInfo(info: String): Unit = println(info)
    	}
    }
    

3.12 普通类和数据类

  • 普通类: 具有get和set、构造函数

  • 数据类: 除了普通类具有的get、set和构造函数外,还提供了解构、克隆、toString、HashCode、equals方法

    fun main() {
    
    	println(ResponseBean(200, "ok", "成功"))
    
    	println(ResponsedataBean(200, "ok", "成功"))
    
    	//默认继承的Any父类equals时,是一种对象比较
    	println(ResponseBean(200, "ok", "成功") == ResponseBean(200, "ok", "成功"))
    	//数据类重写了equals,所以是在对值的比较
    	println(ResponsedataBean(200, "ok", "成功") == ResponsedataBean(200, "ok", "成功"))
    }
    
    //普通类:具有set和get、构造函数
    class ResponseBean(var code: Int, var msg: String, var data: Any) {
    
    }
    
    //数据类:除了set和get、构造函数外,还提供解构、克隆、toString、HashCode、equals方法
    //服务器相应,javaBean,实体可以使用,主要就是数据存储载入,便于打印
    //至少又一个参数的构造参数,且必须指明参数的类型 val 或 var
    //数据类不能使用 abstract,open,sealed,inner
    //比较,copy,toString,解构等
    data class ResponsedataBean(var code: Int, var msg: String, var data: Any) {
    
    }
    

3.13 类的复制函数: Copy

  • 类的复制函数,只复制了类的主构造方法,不管类的次构造方法

    fun main() {
    
    	var bo: BaseObject = BaseObject("zhangsan")
    	println(bo)
    
    	// copy、toString、hashCode只看主构造的参数信息,不管次构造的参数信息
    	var copybo: BaseObject = bo.copy(name = "wangwu")
    	println(copybo)
    }
    
    data class BaseObject(var name: String, var age: Int) {
    	var coreMsg: String = ""
    
    	init {
    		println("主构造被调用")
    	}
    
    	constructor(name: String) : this(name, 99) {
    		println("此构造被调用")
    		coreMsg = "核心信息"
    	}
    
    	override fun toString(): String {
    		//return super.toString()
    		return "toString: name: ${name};age: ${age};coreMsg: $coreMsg"
    	}
    }
    

3.14 数据类的解构

  • 在普通类中也可以实现解构造,需要运算符重载

    fun main() {
    	val (name, age, sex) = CommClass("zhangsan", 14, '男')
    	println("普通类:name: ${name};age:${age};sex:${sex}.")
    
    	val (name2, age2, sex2) = CommDataClass("zhangsan", 14, '男')
    	println("数据类:name: ${name2};age:${age2};sex:${sex2}.")
    
    	val (name3, _, sex3) = CommDataClass("zhangsan", 14, '男')
    	println("数据类:name: ${name3};sex:${sex3}.")
    }
    
    class CommClass(var name: String, var age: Int, var sex: Char) {
    	//解构需要运算符重载关键字 operator
    	operator fun component1() = name
    	operator fun component2() = age
    	operator fun component3() = sex
    }
    
    data class CommDataClass(var name: String, var age: Int, var sex: Char) {
    
    }
    

3.15 运算符重载: operator

  • 通过重写对应的方法,以实现对应所需要的功能

    fun main() {
    	println(Add(1, 2) + Add(2, 3))
    }
    
    class Add(var num1: Int, var num2: Int) {
    	operator fun plus(add: Add): Int {
    		return num1 + add.num1 + num2 + add.num2
    	}
    
    	//operator fun Add.   查看整个运算符重载的方式
    }
    

3.16 枚举类: enum

  • 简单声明使用

    fun main() {
    	println(Week.星期一)
    	println(Week.星期六)
    	//枚举的值等于枚举本身
    	println(Week.星期三 is Week)
    }
    
    // 枚举也是一个class
    enum class Week {
    	星期一,
    	星期二,
    	星期三,
    	星期四,
    	星期五,
    	星期六,
    	星期日
    }
    
  • 枚举类定义函数

    fun main() {
    
    	//调用显示
    	println(BodyPart.LEFT_HAND.show())
    	println(BodyPart.RIGHT_HAND.show())
    	println(BodyPart.LEFT_FOOT.show())
    	println(BodyPart.RIGHT_FOOT.show())
    
    	//更新数据
    	BodyPart.LEFT_HAND.update(BodyInfo("left_hand", 32))
    }
    
    //枚举的主构造参数必须和枚举的参数保持一致
    enum class BodyPart(private val bodyInfo: BodyInfo) {
    	LEFT_HAND(BodyInfo("LEFT_HAND", 12)),
    	RIGHT_HAND(BodyInfo("RIGHT_HAND", 12)),
    
    	LEFT_FOOT(BodyInfo("LEFT_FOOT", 12)),
    	RIGHT_FOOT(BodyInfo("RIGHT_FOOT", 12)),
    	//结束枚举的值
    	;
    
    	fun show(): String = "四肢的信息是:${bodyInfo.flag},长度为:${bodyInfo.length}"
    	fun update(newBodyInfo: BodyInfo): Unit {
    		println("更新前Emnu数据,${this.bodyInfo.show()}")
    		this.bodyInfo.flag = newBodyInfo.flag
    		this.bodyInfo.length = newBodyInfo.length
    		println("重新定义Emnu数据成功,${this.bodyInfo.show()}")
    	}
    }
    
    class BodyInfo(var flag: String, var length: Int) {
    	fun show(): String {
    		return "${flag}的长度为:${length}"
    	}
    }
    
  • 代数数据类型

    fun main() {
    	println(Teacher(Exam.GRAD4).show())
    }
    
    enum class Exam {
    	GRAD1,
    	GRAD2,
    	GRAD3,
    	GRAD4,
    	;
    }
    
    class Teacher(private val exam: Exam) {
    	fun show(): String =
    		//枚举属于代数数据类型,所以不需要else
    		when (exam) {
    			Exam.GRAD1 -> "分数低"
    			Exam.GRAD2 -> "分数中下"
    			Exam.GRAD3 -> "分数中上"
    			Exam.GRAD4 -> "分数高"
    		}
    }
    

3.17 密封类: sealed

  • 枚举类的一种特殊情况

    fun main() {
    
        println(Teacher(Exam.GRAD4("zhangsan")).show())
    
        //声明object是单例模式
        println(Exam.GRAD1 == Exam.GRAD1)
        //class不是单例模式的
        println(Exam.GRAD4("aaa") == Exam.GRAD4("aaa"))
    }
    
    sealed class Exam {
        object GRAD1 : Exam()
    
        object GRAD2 : Exam()
    
        object GRAD3 : Exam()
    
        //object GRAD4 : Exam()
    
        //var name: String? = null
    
        class GRAD4(val name: String) : Exam()
    }
    
    class Teacher(private val exam: Exam) {
        fun show(): String =
            //枚举属于代数数据类型,所以不需要else
            when (exam) {
                is Exam.GRAD1 -> "分数低"
                is Exam.GRAD2 -> "分数中下"
                is Exam.GRAD3 -> "分数中上"
                is Exam.GRAD4 -> "分数高,该学生的姓名是:${(this.exam as Exam.GRAD4).name}"
            }
    }
    

3.18 接口: interface

  • 接口本身不能含有主构造;继承的接口不仅需要重写接口函数,也需要重写接口的成员;实现接口的部分全部要加入override关键字

    fun main() {
    
    	val usb1: IUSB = Mouse()
    	println(usb1.insertUSB())
    
    	val usb2: IUSB = KeyBoard()
    	println(usb2.insertUSB())
    
    }
    
    //接口本身都是public open,接口不能含有主构造
    //接口不仅仅要重写接口的函数,也要重写接口的成员
    //接口实现的部分全部要加入override关键字
    interface IUSB {
    	var usbVersion: String
    	var usbInsertDriver: String
    
    	fun insertUSB(): String
    }
    
    class Mouse(override var usbVersion: String = "3.2", override var usbInsertDriver: String = "鼠标") : IUSB {
    	override fun insertUSB(): String {
    		//TODO("Not yet implemented")
    		return "设备为:${usbInsertDriver},设备版本为:${usbVersion}"
    	}
    }
    
    class KeyBoard : IUSB {
    	override var usbVersion: String = "3.2"
    		get() = field//TODO("Not yet implemented")
    		set(value) {
    			field = value ?: "该字段为空"
    		}
    	override var usbInsertDriver: String = "键盘"
    		get() = field//TODO("Not yet implemented")
    		set(value) {
    			field = value ?: "该字段为空"
    		}
    
    	override fun insertUSB(): String {
    		//TODO("Not yet implemented")
    		return "设备为:${usbInsertDriver},设备版本为:${usbVersion}"
    	}
    }
    
  • 接口默认实现

    fun main() {
    
    	val usb1: USB2 = Mouse2()
    	println(usb1.insertUSB())
    
    	val usb2: USB2 = KeyBoard2()
    	println(usb2.insertUSB())
    
    	val usb3: USB2 = Mouse3()
    	println(usb3.insertUSB())
    }
    
    //接口不能给成员赋值
    //任何类 接口等等 val代表只读,是没有在其后动态赋值
    interface USB2 {
    	val usbVersion: String
    		get() = (1..100).shuffled().last().toString()
    
    	val usbInsertDriver: String
    		get() = "usb设备接入"
    
    	fun insertUSB(): String
    }
    
    class Mouse3() : USB2 {
    	override val usbVersion: String
    		get() = super.usbVersion
    	override val usbInsertDriver: String
    		get() = super.usbInsertDriver
    
    	override fun insertUSB(): String {
    		//TODO("Not yet implemented")
    		return "设备为:${usbInsertDriver},设备版本为:${usbVersion}"
    	}
    }
    
    class Mouse2(override var usbVersion: String = "3.2", override var usbInsertDriver: String = "鼠标") : USB2 {
    	override fun insertUSB(): String {
    		//TODO("Not yet implemented")
    		return "设备为:${usbInsertDriver},设备版本为:${usbVersion}"
    	}
    }
    
    class KeyBoard2 : USB2 {
    	override var usbVersion: String = "3.2"
    		get() = field//TODO("Not yet implemented")
    		set(value) {
    			field = value ?: "该字段为空"
    		}
    	override var usbInsertDriver: String = "键盘"
    		get() = field//TODO("Not yet implemented")
    		set(value) {
    			field = value ?: "该字段为空"
    		}
    
    	override fun insertUSB(): String {
    		//TODO("Not yet implemented")
    		return "设备为:${usbInsertDriver},设备版本为:${usbVersion}"
    	}
    }
    

3.19 抽象类: abstract

  • 可以有一些抽象方法,也可以有一些具体实现

    fun main() {
    	MainActivity().show()
    }
    
    abstract class BaseActivity {
    	fun onCreate() {
    		setContentView(getLayoutID())
    		initView()
    		initData()
    		initOthers()
    	}
    
    	private fun setContentView(laoutID: Int) = println("加载${laoutID}")
    	abstract fun getLayoutID(): Int
    	abstract fun initView()
    	abstract fun initData()
    	abstract fun initOthers()
    }
    
    class MainActivity : BaseActivity() {
    	override fun getLayoutID(): Int {
    		//TODO("Not yet implemented")
    		return 562
    	}
    
    	override fun initView() {
    		//TODO("Not yet implemented")
    		println("View 初始化")
    	}
    
    	override fun initData() {
    		//TODO("Not yet implemented")
    		println("data 初始化")
    	}
    
    	override fun initOthers() {
    		//TODO("Not yet implemented")
    		println("Ohters 初始化")
    	}
    
    	fun show() {
    		super.onCreate()
    	}
    
    }
    

3.20 泛型

  • 普通泛型

    fun main() {
    	var s: Student = Student(name = "zhangsan", age = 19, sex = '男')
    	BaseF(s).show()
    
    	var t: Teacher = Teacher(name = "wangwu", age = 29, sex = '男')
    	BaseF(t).show()
    
    	BaseF(String(("留意").toByteArray()))
    }
    
    class BaseF<T>(private val obj: T) {
    	fun show() = println("输出对象:${obj}")
    }
    
    data class Student(val name: String, val age: Int, val sex: Char)
    data class Teacher(val name: String, val age: Int, val sex: Char)
    
  • 泛型函数

    fun main() {
    	var s: Student = Student(name = "zhangsan", age = 19, sex = '男')
    	println(BaseF(true, s).getObj())
    
    	var t: Teacher = Teacher(name = "wangwu", age = 29, sex = '男')
    	println(BaseF(true, t).getObj())
    
    	println(BaseF(false, t).getObj() ?: "返回了null呀")
    
    	BaseF(true, s).getObj()?.run {
    		println("对象为:${this}")
    	} ?: "返回了null呀"
    
    	var temp: Student? = BaseF(true, s).getObj()?.apply {
    		if (this != null) {
    			println("对象为:${this}")
    		} else {
    			println("返回了null呀")
    		}
    	}
    
    	show("String")
    
    	show2(null)
    }
    
    class BaseF<T>(private val isShow: Boolean = false, private val obj: T) {
    	fun getObj() = obj.takeIf { isShow }
    }
    
    data class Student(val name: String, val age: Int, val sex: Char)
    data class Teacher(val name: String, val age: Int, val sex: Char)
    
    
    fun <B> show(item: B) {
    	var result = item?.also {
    		println("打印:${item}")
    	} ?: println("返回了null呀")
    }
    
    fun <T> show2(item: T) {
    	var r = item?.also {
    		if (item == null) {
    			println("null")
    		} else {
    			println("打印:${item}")
    		}
    	} ?: "返回了null呀"
    }
    
  • 泛型变换

    fun main() {
    	var p1 = BaseF2(isMap = true, 321421)
    	var r = p1.map {
    		it.toString()
    	}
    	println(r is String?)
    	println(r)
    
    	var r1: String? = map(inputValue = 12345) {
    		it.toString()
    	}
    	println(r1)
    }
    
    class BaseF2<T>(private val isMap: Boolean = false, val inputType: T) {
    
    	fun <R> map(mapAction: (T) -> R): R? = mapAction(inputType).takeIf {
    		isMap
    	}
    }
    
    
    inline fun <I, O> map(isChange: Boolean = true, inputValue: I, mapAction: (I) -> O): O? {
    	return if (isChange) mapAction(inputValue) else null
    }
    
  • 泛型类型的约束

    fun main() {
    
    	val my = MyClass("1234")
    	val person = PersonClass("1234")
    	val student = StudentClass("1234")
    	val teacher = TeacherClass("1234")
    	val dog = DogClass("1234")
    
    	val r1 = PrintF(inputTypeValue = student).getObj();
    	println(r1)
    }
    
    open class MyClass(name: String)
    
    open class PersonClass(name: String) : MyClass(name)
    
    class StudentClass(name: String) : PersonClass(name)
    
    class TeacherClass(name: String) : PersonClass(name)
    
    class DogClass(name: String)
    
    // <T : 类型>,类型的以及类型的子类可以使用
    class PrintF<T : PersonClass>(private val isChange: Boolean = true, val inputTypeValue: T) {
    	fun getObj() = inputTypeValue.takeIf { isChange }
    }
    

3.21 动态关键字: vararg

  • 声明的该属性可接收多个值

    fun main() {
    
    	// 类型: Baseargs<{Comparable<*> & java.io.Serializable}>
    	var p: Baseargs<Any?> = Baseargs(ischange = true, true, "1234", 213.4)
    
    	println(p.showObject(0))
    
    	println(p.showObject(2).toString() is String)
    
    	var r: String = p.mapObj(1) {
    		it as String
    	}
    	println(r)
    }
    
    class Baseargs<T>(var ischange: Boolean, vararg objects: T) {
    	//out 指我们的T只能被读取,不能进行修改
    	val objectArray: Array<out T> = objects
    
    	fun showObject(): Array<out T> {
    		return objectArray
    	}
    
    	fun showObject(index: Int): T {
    		return objectArray[index]
    	}
    
    	fun <O> mapObj(index: Int, mapAction: (T?) -> O): O {
    		return mapAction(objectArray[index].takeIf { ischange })
    	}
    }
    

3.22 自定义操作符: []

  • 重写操作符: []

    fun main() {
    	inputObj("demo")
    	inputObj(null)
    
    	var i: BaseClss<String?> = BaseClss(isChange = true, "zhangsan", "lisi", "wangwu")
    	println(i.get(0))
    	println(i.get(2))
    }
    
    
    class BaseClss<INPUT>(val isChange: Boolean, vararg objects: INPUT) {
    	//out标识objectArray只能进行读取,不能进行修改
    	val objectArray: Array<out INPUT> = objects
    
    	fun getObj(): Array<out INPUT> = objectArray
    
    	fun getObj2(): Any = objectArray.takeIf { isChange } ?: "null值"
    
    	fun getObj3(): Any? = objectArray.takeIf { isChange } ?: "null值" ?: null
    
    	fun getObj4(index: Int): INPUT? = objectArray[index].takeIf { isChange } ?: null
    
    	fun getObj5(index: Int): Any? = objectArray[index].takeIf { isChange } ?: "AAA" ?: null
    
    	operator fun get(index: Int): INPUT? = objectArray[index].takeIf { isChange }
    }
    
    fun <INPUT> inputObj(item: INPUT) {
    	println((item as String?)?.length ?: "传递的是null")
    }
    

3.23 out协变

  • 父 -> 子

    fun main() {
    
    	var p1: Producer<Animal> = Produce1()
    	//类型也可以为Animal,因为有out关键字,泛型的子类对象也可以赋值给父类对象,默认情况下不可以
    	//相当于java中的 ? extends 例如:List<? extends CharSequence> list2=new ArrayList<String>();
    	var p2: Producer<Animal> = Produce2()
    	var p3: Producer<Animal> = Produce3()
    	var p4: Producer<Animal> = Produce4()
    	
    }
    
    //out T 协变
    interface Producer<out T> {
    	// 这里的T只能读取,不能修改,放在参数里,可能会产生修改
    	//fun consumer(item:T){}
    
    	fun Produce(): T
    }
    
    //in T 逆变
    interface Consumer<in T> {
    
    	fun Consume(item: T)
    
    	//不能进行读取,只能修改
    	//fun Produce():T
    }
    
    interface ProducerAndConsumer<T> {
    	fun Produce(): T
    
    	fun Consume(item: T)
    }
    
    
    open class Animal
    open class Humanity : Animal()
    open class Man : Humanity()
    open class Woman : Humanity()
    
    
    class Produce1 : Producer<Animal> {
    	override fun Produce(): Animal {
    		//TODO("Not yet implemented"
    		println("Animal Produce")
    		return Animal()
    	}
    }
    
    class Produce2 : Producer<Humanity> {
    	override fun Produce(): Humanity {
    		//TODO("Not yet implemented"
    		println("Humanity Produce")
    		return Humanity()
    	}
    }
    
    class Produce3 : Producer<Man> {
    	override fun Produce(): Man {
    		//TODO("Not yet implemented"
    		println("Man Produce")
    		return Man()
    	}
    }
    
    class Produce4 : Producer<Woman> {
    	override fun Produce(): Woman {
    		//TODO("Not yet implemented"
    		println("Woman Produce")
    		return Woman()
    	}
    }
    

3.24 in 逆变

  • 子 -> 父

    // out 协变:只读 父类 = 子类
    // in 逆变:只写 子类 = 父类
    fun main() {
    
    	var p1: Producer<Animal> = Produce1()
    	//类型也可以为Animal,因为有out关键字,泛型的子类对象也可以赋值给父类对象,默认情况下不可以
    	//相当于java中的 ? extends 例如:List<? extends CharSequence> list2=new ArrayList<String>();
    	var p2: Producer<Animal> = Produce2()
    	var p3: Producer<Animal> = Produce3()
    	var p4: Producer<Animal> = Produce4()
    
    	//因为有in关键字,泛型的子类对象也可以接收父类的对象,默认情况下是不可以
    	//相当于java中的 ? super 例如:List<? extends String> list2=new ArrayList<CharSequence>();
    	val c1: Consumer<Man> = Consume1()
    }
    
    //out T 协变
    interface Producer<out T> {
    	// 这里的T只能读取,不能修改,放在参数里,可能会产生修改
    	//fun consumer(item:T){}
    
    	fun Produce(): T
    }
    
    //in T 逆变
    interface Consumer<in T> {
    
    	fun Consume(item: T)
    
    	//不能进行读取,只能修改
    	//fun Produce():T
    }
    
    interface ProducerAndConsumer<T> {
    	fun Produce(): T
    
    	fun Consume(item: T)
    }
    
    
    open class Animal
    open class Humanity : Animal()
    open class Man : Humanity()
    open class Woman : Humanity()
    
    
    class Produce1 : Producer<Animal> {
    	override fun Produce(): Animal {
    		//TODO("Not yet implemented"
    		println("Animal Produce")
    		return Animal()
    	}
    }
    
    class Produce2 : Producer<Humanity> {
    	override fun Produce(): Humanity {
    		//TODO("Not yet implemented"
    		println("Humanity Produce")
    		return Humanity()
    	}
    }
    
    class Produce3 : Producer<Man> {
    	override fun Produce(): Man {
    		//TODO("Not yet implemented"
    		println("Man Produce")
    		return Man()
    	}
    }
    
    class Produce4 : Producer<Woman> {
    	override fun Produce(): Woman {
    		//TODO("Not yet implemented"
    		println("Woman Produce")
    		return Woman()
    	}
    }
    
    
    class Consume1 : Consumer<Animal> {
    	override fun Consume(item: Animal) {
    		//TODO("Not yet implemented")
    		println("Animal Consume")
    	}
    }
    
    class Consume2 : Consumer<Humanity> {
    	override fun Consume(item: Humanity) {
    		//TODO("Not yet implemented")
    		println("Humanity Consume")
    	}
    }
    
    class Consume3 : Consumer<Man> {
    	override fun Consume(item: Man) {
    		//TODO("Not yet implemented")
    		println("Man Consume")
    	}
    }
    
    class Consume4 : Consumer<Woman> {
    	override fun Consume(item: Woman) {
    		//TODO("Not yet implemented")
    		println("Woman Consume")
    	}
    }
    

3.25 out和in的用法

fun main() {
    val p1: SetClass<String> = SetClass<String>();
    p1.set1("1234213")

    val o1: GetClass<String> = GetClass<String>("param");
    println(o1.get1())
}

// in T 或者 out T 声明处泛型 ,java不支持
//所有的成员 泛型相关只能修改更改,不能读取
class SetClass<in T>() {

    fun set1(item: T) {
        println("设置的item为:${item}")
    }
}

//所有的成员 泛型相关只能读取,不能更改
class GetClass<out T>(_item: T) {

    val item: T = _item

    fun get1(): T? {
        return item
    }
}

3.26 reified关键字

fun main() {

    //匿名方式
    var r = AllFun().randomOrDefault<ObjectClass1> {
        ObjectClass1("wangwu", 20)
    }
    println(r)

    //具名方式
    var r1: ObjectClass1? = AllFun().randomOrDefault<ObjectClass1>(::defaultAction)
    println(r1)
}

data class ObjectClass1(val name: String, val age: Int)
data class ObjectClass2(val name: String, val age: Int)
data class ObjectClass3(val name: String, val age: Int)

fun <T> defaultAction(): T {
    return ObjectClass1("wangwu", 20) as T
}

class AllFun {

    inline fun <reified T> randomOrDefault(defaultLambdaAction: () -> T): T? {
        var objLists: List<Any> = listOf<Any>(
            ObjectClass1("wangwu", 12),
            ObjectClass2("zangsan", 12),
            ObjectClass3("lsii", 12)
        )

        val randomObj: Any? = objLists.shuffled().first()
        println("随机产生的对象为:${randomObj}")

        //return randomObj.takeIf { it is T } as T ?: null
        return randomObj.takeIf { it is T } as T? ?: defaultLambdaAction()
    }
}

3.27 扩展函数

  • 基本扩展

    fun main() {
    	val baseClass: BaseClass = BaseClass("zhangsan", 18, '男')
    	baseClass.show()
    
    	println("Demo".addExtAction(3))
    }
    
    class BaseClass(val name: String, val age: Int, val sex: Char)
    
    //每个扩展类函数中都含有一个this,this代表类的本身
    fun BaseClass.show() {
    	println("name:${this.name},age:${age},sex:${sex}")
    }
    
    fun BaseClass.getAge(): Int = this.age
    
    fun String.addExtAction(num: Int) = this + "@".repeat(num)
    
  • 超类扩展

    fun main() {
    	ResponseResult(200, "ok", "成功").showPrintlnContent()
    	"提示信息".showPrintlnContent()
    
    	"提示信息".showPrintlnContent2().showPrintlnContent2()
    }
    
    //扩展函数不允许重复定义
    fun Any.showPrintlnContent() = println("当前的对象是:${this}")
    
    //链式调用
    fun Any.showPrintlnContent2(): Any {
    	println("当前的对象为:${this}")
    	return this
    }
    
    data class ResponseResult(val code: Int, val status: String, val msg: String)
    
  • 泛型扩展

    fun main() {
    	//所有的类型都是泛型,所以所有的类均可以调用showContentInfo函数
    	123.showContentInfo()
    	"1234".showContentInfo()
    	contentFun().showContentInfo()
    }
    
    fun <T> T.showContentInfo() {
    	println("${if (this is String) "字符长度为:${this.length}" else "内容为:${this}"} ")
    }
    
    fun contentFun() {
    
    }
    
  • apply内置函数扩展

    fun main() {
    	"Demo".myLet {
    		true
    	}
    
    	"demo".let {
    		true
    	}
    }
    
    private inline fun <I, O> I.myLet(lambda: (I) -> O): O = lambda(this)
    
  • 扩展属性

    fun main() {
    	var str: String = "abc"
    	str.getInfo().getInfo()
    
    	str.myinfo.getInfo()
    }
    
    val String.myinfo: String
    	get() = "demo"
    
    fun String.getInfo(): String {
    	println("当前内容是:${this}")
    	return this
    }
    
  • 可用类型的应用

    fun main() {
    	var info: String? = null
    	info.outPutStringValueFun("默认值")
    }
    
    //String?可以接收可空数据,也可以接收有值数据
    fun String?.outPutStringValueFun(defaultValue: String): Unit {
    	println(this ?: defaultValue)
    }
    
    fun String?.outPutStringValueFun2(defaultValue: String): String {
    	return this ?: defaultValue
    }
    

3.28 中缀表达式

fun main() {
    mapOf("0".to(12))
    mapOf("1".to(23120))

    "demo".goto(1234)

    "demo" goto 12341
}

//中缀表达式 + 扩展函数
//条件:对一个对象需要进行函数扩展,另一个对象需要传递在参数内
private infix fun <C1, C2> C1.goto(c2: C2) {
    println("参数1:${this}")
    println("参数2:${c2}")
}

3.29 扩展文件

fun main() {
    val list: List<String> = listOf("12", "23124", "312412")
    val set: Set<Int> = setOf(1, 2, 3, 5, 9)

    println(list.shuffled().first())
    println(set.shuffled().first())

    println(list.randomItemValue())
    set.randomItemValuePrintln()
}

//扩展文件一般都是public,重写父类主要是为了子类可以使用
fun <E> Iterable<E>.randomItemValue(): E {
    return this.shuffled().first()
}

fun <T> Iterable<T>.randomItemValuePrintln() = println(this.shuffled().first())

3.30 重命名 as

主要用法:import 方法名 as 别名

3.31 apply解析扩展

  • 一般扩展

    fun main() {
    	"str".mApply {
    		println(this.length)
    	}.mApply {
    		println(this is String)
    	}
    }
    
    //private 私有化
    //inline 函数属于高阶函数,使用内联对lambda进行优化处理提高新能
    //fun<INPUT> 函数中声明一个泛型
    //INPUT.mApply 让所有类型都可以进行调用,泛型扩展
    // INPUT.()->Unit 让我们的匿名函数中持有this,在lambda里面返回类型为空
    // 调用lambda(this) 默认就含有this
    //返回this的目的主要是用链式调用
    private inline fun <INPUT> INPUT.mApply(lambda: INPUT.() -> Unit): INPUT {
    	lambda()
    	return this
    }
    
  • let和apply总结

    //1. let 返回类型是根据匿名函数的变化而变化(lambda的返回类型变化而变化)
    //2。 匿名函数李曼持有的是 it对象
    inline fun <I, O> I.mLet(lambda: (I) -> O): O = lambda(this)
    
    //1. apply返回类型永远都是I,lambda的返回类型与apply返回类型并无关联
    //2. 匿名函数里面持有的是 this对象
    inline fun <I> I.mApply(lambda: I.() -> Unit): I {
    	lambda()
    	return this
    }
    

3.32 DSL

//DSL(Domain Specified Language),领域专用语言
//定义输入和输出规则;
//定义使用的对象
fun main() {
    val context: Context = Context().apply1 {
        toast("success")
        toast(it)
    }
    println(context)
}

class Context {
    val info = "demo"

    fun toast(str: String): Unit {
        println("Toast: $str")
    }
}

fun Context.apply1(lambda: Context.(String) -> Unit): Context {
    lambda(this.info)
    return this
}

3.33 函数变换

  • map的函数变换

    fun main() {
    	val list: List<String> = listOf("123", "1234", "12", "1")
    
    	//通过匿名函数的最后一行返回值加入新的集合,并返回新的集合
    	val list1: List<String> = list.map {
    		println(it)
    		"{$it}"
    	}
    	println(list1)
    
    	list.map {
    		"字符串是:$it"
    	}.map {
    		"$it,文字的长度是:${it.length}"
    	}.map {
    		"[$it]"
    	}.map {
    		println(it)
    	}
    }
    
  • flatmap的函数变换

    fun main() {
    	val list: List<String> = listOf("zhangsan", "lisi", "wangwu")
    
    	//map 返回每一个元素的加入到新的集合 List<String>
    	//flatmap 返回每一个集合加入到新的集合 List<List<String>>
    	val newlist: List<String> = list.map {
    		"你的姓名是:$it"
    	}.map {
    		"$it,文字的长度是:${it.length}"
    	}.flatMap {
    		listOf("$it 在1", "$it 在2")
    	}
    
    	println(newlist)
    
    	val list2: List<String> = list.flatMap {
    		listOf("$it 在1", "$it 在2")
    	}
    	println(list2)
    }
    

3.34 filter函数过滤

fun main() {
    val names: List<List<String>> = listOf(
        listOf("zhangsan", "wangwu", "zhaoliu"),
        listOf("lisi", "wanger", "wuli")
    )

    names.map {
        println(it)
    }

    names.flatMap {
        println(it)
        listOf("")
    }

    //返回的对象为String
    names.flatMap { it ->
        //filter:如果为true 加入到新的集合中进行组装;否则不加入
        it.filter {
            println("$it,1")
            false
        }
    }.map {
        println(it)
    }

    // 返回的类型为List<String>
    names.map { it ->
        //filter:如果为true 加入到新的集合中进行组装;否则不加入
        it.filter {
            //println("$it,1")
            true
        }
    }.map {
        println(it)
    }


    names.flatMap { it ->
        it.filter {
            it.contains("zhao")
        }
    }.map {
        print("$it   ")
    }
}

3.35 zip合并函数

fun main() {
    val names: List<String> = listOf("zhangsan", "lisi", "wangwu")
    val ages: List<Int> = listOf(19, 29, 31)

    //zip 第一个集合和第二个集合进行合并后,创建新的集合
    var new: List<Pair<String, Int>> = names.zip(ages)
    println(new)
    println(new.toMap())
    println(new.toMutableSet())
    println(new.toMutableList())

    //遍历
    new.forEach() {
        println("第一个:${it.first},第二个:${it.second}")
    }

    //map普通方式
    new.toMap().forEach() { key: String, value: Int ->
        println("第一个:${key},第二个:${value}")
    }
    //map的解构方式
    new.toMap().forEach() { (key: String, value: Int) ->
        println("第一个:${key},第二个:${value}")
    }
}

3.36 函数式编程

3.37. java与kotlin交互

public class DemoCon {
    public String getInfo() {
        return "Demo";
    }

    public String getInfo2() {
        return null;
    }
}
fun main() {

    //交互时不能直接使用,可能会出现异常错误提示
    //println(DemoCon().info.length)
    //println(DemoCon().info2.length)

    //java与kotlin交互式类型都是 :类型!
    val info: String? = DemoCon().info
    val info1: String? = DemoCon().info2
    println(info?.length)
    println(info1?.length)
}

3.38 单例模式的四种方式

// kotlin的饿汉模式加载
object Singleton

//kotlin的懒汉式加载
class Singleton2 {
    companion object {
        private var instance: Singleton2? = null
            get() {
                if (field == null) {
                    field = Singleton2()
                }
                return field
            }
        //fun getInstanceAction(): Singleton2 = instance!!

        //懒汉式处理+安全处理
        @Synchronized
        fun getInstanceAction(): Singleton2 = instance!!
    }

    fun show() {
        println("show")
    }
}


//懒汉式处理+双重安全处理
class Singleton3 {
    companion object {
        val instance: Singleton3 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Singleton3()
        }
    }

    fun show() {
        println("show")
    }
}


fun main() {
    //Singleton2.getInstanceAction().show()
    Singleton3.instance.show()
}

3.39 kotlin 注解

  1. JvmName

    public class JvmNameJava {
        public static void main(String[] args) {
            //JvmNameAndkotlinKt.getJvmNameJavaInfo("1234");
            JNAK.getJvmNameJavaInfo("1234");
        }
    }
    
    //编译环节修改类名称,使得其他进行调用时更简洁,必须要写在包名外
    @file:JvmName("JNAK")
    
    fun main() {
    
    }
    
    fun getJvmNameJavaInfo(str: String) = println(str)
    
  2. JvmField

    public class JvmFieldAndKotlin {
        public static void main(String[] args) {
            Text test = new Text();
    //        for (String item : test.getName()) {
    //            System.out.println(item);
    //        }
            for (String item : test.name) {
                System.out.println(item);
            }
        }
    }
    
    class Text {
        //将成员的私有化方法去掉,属性变为公开可访问的
        @JvmField
        val name: List<String> = listOf("zhangsan", "lisi")
    }
    
  3. JvmOverloads

    public class JvmOverloadsJava {
        public static void main(String[] args) {
            JvmOverloadsAndKotlinKt.show("1234");
        }
    }
    
    fun main() {
        show(name = "123")
    }
    
    //编译阶段会有一个重载函数供其调用
    @JvmOverloads
    fun show(name: String, age: Int = 20) {
        println("name:${name},age:${age}")
    }
    
  4. JvmStatic

    public class JvmStaticJava {
        public static void main(String[] args) {
            //Test.Companion.getAddress();
            //Test.Companion.show();
    
            System.out.println(Test.address);
            Test.show();
    
        }
    }
    
    class Test {
        companion object {
            @JvmField
            val address = "北京"
    
            @JvmStatic
            fun show() = println("当前的地址为:${address}")
        }
    }
    
    fun main() {
        Test.address
    
        Test.show()
    }
    

3.40 自定义变换操作符

fun main() {
    //create 匿名表达式 只关心用户的输入 输出源是最后一行内容
    //map 输入源就是create输出源 输出源为最后一行内容
    //observer 输入源就是map存储的输出源
    create {
        "demo"
    }.map {
        "你的值是:$this"
    }.map {
        "{{${this}}}"
    }.observer {
        println(this)
    }
}

class RxJavaCoreObjectClass<T>(val value: T) {
}

inline fun <I, O> RxJavaCoreObjectClass<I>.map(mapAction: I.() -> O): RxJavaCoreObjectClass<O> {
    return RxJavaCoreObjectClass(mapAction(value))
}

inline fun <OUTPUT> create(action: () -> OUTPUT): RxJavaCoreObjectClass<OUTPUT> {
    return RxJavaCoreObjectClass<OUTPUT>((action()))
}

inline fun <INPUT> RxJavaCoreObjectClass<INPUT>.observer(observerAction: INPUT.() -> Unit): Unit {
    observerAction(value)
}
0

评论区