参考链接
Kotlin官方文档
https://kotlinlang.org/docs/home.html
中文网站
https://www.kotlincn.net/docs/reference/properties.html
本系列为参考Kotlin中文文档
https://download.csdn.net/download/u011109881/21418027
整理的笔记
pdf也可以在这里下载
https://www.kotlincn.net/docs/kotlin-docs.pdf
大部分示例来自bilibili Kotlin语言深入解析 张龙老师的视频
1 解构声明
知识点
1 解构声明在数据类中的应用
2 一个函数返回多个结果
3 解构声明在集合中的应用
4 解构声明的类型
笔记
/**
* 解构声明
* 可以理解为批量赋值 常用于数据类和Map等拥有多个属性的类型
* 目的是方便我们声明和获取其中的属性
*/
fun main() {
// 1 解构声明在数据类中的应用
// 普通Java类的获取方式
val myPerson = generatePerson()
println(myPerson.name)
println(myPerson.age)
println(myPerson.address)
// 使用解构声明
// 批量声明与赋值
val (myName, myAge, myAddress) = generatePerson()
println(myName)
println(myAge)
println(myAddress)
println("======= 1 end ========")
// 2 一个函数返回多个结果
// --使用Pair或Triple
val triple = generatePerson2()
println(triple.first)
println(triple.second)
println(triple.third)
// 想要一个return里面返回多个数据 一个是利用解构声明 一个是利用Pair或Triple
// 但是两者区别还是挺大的 Pair或Triple只是存储了多个结果 但是并没有解构声明容易理解 因为Pair或Triple并没有固定的数据类型
// 而结构声明返回的数据类型 是我们创建map或者数据类时就制定好了类型的
// 所以更推荐解构声明
println("======= 2 end ========")
// 3 解构声明在集合中的应用
// map 初始化 to关键字本身是一个中缀表达式 返回一个pair
// 3.1 利用解构声明遍历map
val map = mapOf("a" to "aa", "b" to "bb", "c" to "cc") // 类型可以推断出来 所以可以省略
val map2 = mapOf<String, String>("a" to "aa", "b" to "bb", "c" to "cc")
for ((myKey, myValue) in map) {
println("key:$myKey value:$myValue")
}
println("----------------------")
// 3.2 利用mapValues方法修改map的value
// mapValues:map以<K,V>的类型输入 以<K,R>的形式输出
// mapValues接受一个函数作为参数 该函数参数为Map.Entry<K,V> 返回R类型的数据
// mapKeys和mapValues方法差不过 差异在于mapKeys修改的是key而不是value
map.mapValues { entry ->
"...value changed to:${entry.key} ${entry.value}"
}.forEach { println(it) }
println("----------------------")
// 3.3 mapValues+结构声明 修改value同时遍历map
map.mapValues { (_, value) ->
"$value haha"// 给value加上haha
}.forEach { println(it) }
println("======= 3 end ========")
// 4 解构声明的类型
// kotlin 允许我们我们为解构声明的整体指定类型 也允许我们给每个元素指定类型
// 给每个元素指定类型
map.mapValues { (key: String, value: String) -> "$value haha" }.forEach { println(it) }
// 给整体指定类型
map.mapValues { (key, value): Map.Entry<String, String> -> "$value hihi" }.forEach { println(it) }
// 也可以省略
map.mapValues { (key, value) -> "$value enen" }.forEach { println(it) }
}
// 2 一个函数返回多个结果
fun generatePerson2(): Triple<String, Int, String> {
return Triple("zhangsan", 25, "shanghai")
}
// 1 解构声明在数据类中的应用
data class Person(val name: String, val age: Int, val address: String)
fun generatePerson(): Person {
return Person("zhangsan", 25, "shanghai")
}
class D0501DestructuringDeclaration {
}
2 集合
知识点
1 只读视图demo
2 set的创建与遍历
3 只读列表是协变的(out)
4 快照 snapshot
笔记
/**
* 可变集合与不可变集合
*
* kotlin 严格区分可变集合和不可变集合
* 重点是区分真正的不可变集合与可变集合的只读视图
* 在kotlin中 mutable修饰的集合是可变的 没有mutable修饰的则是不可变的
* 例如 MutableList创建的是可变集合 List创建的是不可变集合
*
* List继承自Collection Collection又继承自Iterable 因此它只有访问的方法
* MutableList除了继承自 List 还继承自MutableCollection MutableCollection则提供了一系列add remove等修改list内容的方法
* 只读视图虽然本身无法修改内容 但是如果它的原引用内容变化 视图里面的内容也发生变化
*/
fun main() {
// 1 只读视图demo
// 创建一个可变集合
val stringList: MutableList<String> = mutableListOf("hello", "world", "hello world")
// 创建一个可变集合的只读视图
val readOnlyView: List<String> = stringList
println(stringList)
stringList.add("welcome")
println(stringList)
// 因为readOnlyView是stringList的只读视图 因此stringList发生了变化 readOnlyView内容自然变化
// 但是readOnlyView自身无法调用修改内容的接口
println(readOnlyView)
// readOnlyView.clear//报错 无法调用修改的接口
println("=========== 1 end ===============")
// 2 set的创建与遍历
val mySet: HashSet<String> = hashSetOf("a", "b", "c", "c")
mySet.forEach { println(it) }
println("=========== 2 end ===============")
// 3 只读列表是协变的(out)
// 原因是 它只用于从集合中取出数据 是生产者 而不会消费数据(更改内容)
val myString: List<String> = listOf("a", "b")
val s2: List<Any> = myString // List<String> 好像赋值给了 List<Any> 子类型赋值给父类型---协变
println("=========== 3 end ===============")
// 4 快照 snapshot
val origin = mutableListOf("a", "b", "c")
val snapshot = origin.toList()// toList 是一个Iterable的扩展方法 只是赋值集合中的元素 返回的是一个不可变的list
origin.add("d")
println(origin)
println(snapshot)
// snapshot.clear()// 报错
println("=========== 4 end ===============")
}
class D0502Collection {
}
3 集合的便利方法
知识点
1 List的便利方法
2 map demo
笔记
// 集合的便利方法
fun main() {
// 1 List的便利方法
val item = listOf(1, 2, 3, 4)
// 取出列表第一个元素
println(item.first())
// 取出列表最后一个元素
println(item.last())
// Returns the first element, or null if the list is empty.
println(item.firstOrNull())
println(item.lastOrNull())
// 传入lambda表达式过滤列表
item.filter { it % 2 == 0 }.forEach { println(it) }
println("--------------")
val myList = mutableListOf(1, 2, 3)
// none方法传入一个lambda表达式 如果表达式成立 none返回true 否则返回false
if (myList.none { it > 10 }) {
println("没有大于十的元素")
} else {
println("存在>10的元素")
}
// requireNoNulls 如果myList中没有null 返回List 否则抛出IllegalArgumentException异常
println(myList.requireNoNulls())
println("======== 1 end ========")
// 2 map demo
val myMap = hashMapOf("hello" to 1, "word" to 2)
// 通过下标访问Map
println(myMap["hello"])
val myMap2: Map<String, Int> = HashMap(myMap) // myMap2是myMap元素的拷贝 且无法修改
println(myMap2)
// 通过下标增加map的元素
myMap["hi"] = 3
println(myMap)
println(myMap2)
// myMap2["hi"] = 3 // myMap2是只读的
}
class D0503CollectionConvenientMethod {
}
4 range
笔记
// range
fun main() {
// 1 输出4
val i = 4
if (i in 1..5) {
println(i)
}
println("---------------")
// 输出1-4
for (a in 1..4) {
println(a)
}
println("---------------")
// 什么输出都没有
for (a in 4..1) {
println(a)
}
println("---------------")
// 降序输出
for (a in 4 downTo 1) {
println(a)
}
println("---------------")
for (a in 1..6 step 2) {
println(a)
}
println("---------------")
// 输出1-4 [1,4)
for (a in 1 until 4) {
println(a)
}
println("---------------")
}
class D0504Range {
}
5 异常
笔记
import java.lang.NumberFormatException
import javax.xml.bind.DatatypeConverter.parseInt
// 异常
// Kotlin 中的异常是一个表达式
// Kotlin 中所有的异常都是运行时异常 没有checked exception
fun main() {
val s = "a"
// 如下所示
// res的值可能是try中的最后一句表达式的值 或者 catch中的最后一句表达式的值
val res: Int? = try {
parseInt(s)
} catch (ex: NumberFormatException) {
null
} finally {
println("finally invoked")
}
println(res)
}
class D0505Exception {
}
6 throw
知识点
1 Elvis 表达式
2 throw表达式
3 各种item赋值为null 类型推断
笔记
import java.lang.IllegalArgumentException
/**
* throw
* throw在Kotlin中是一个表达式
* throw表达式的类型是一种特殊的类型:Nothing
* 在自己的代码中 可以使用Nothing来代表永远不会返回的函数
*/
fun main() {
// 1 Elvis 表达式
// Elvis是 ?: 它的含义是 如果该表达式的前半部分不为空 则该表达式的值为前半部分 否则为后半部分
val str: String? = "aa" // null
val str2 = str ?: throw IllegalArgumentException("不能传入空")
println(str2)
println("=========1 end ==========")
// 2 throw表达式 返回Nothing类型
val str3: String? = "bb" // null
val str4 = str3 ?: myMethod("")
println(str4)
// 3 各种item赋值为null 类型推断
// 赋值为null
// 类型推断为Nothing?
val myNull = null
println(myNull is Nothing?)
// list元素赋值为null
// list类型推断为List<Nothing?>
val s2 = listOf(null)
println(s2 is List<Nothing?>)
}
fun myMethod(message: String): Nothing {
throw IllegalArgumentException(message)
}
class D0506Throw {
}