Kotlin学习
基本数据类型以及操作示例
整型:Byte、Short、Int、Long
浮点型:Float、Double
字符型:Char
布尔型:Boolean
其中,Byte、Short、Int、Long 是整型,分别表示 8、16、32、64 位有符号整数;Float、Double 是浮点型,分别表示 32、64 位浮点数;Char 表示一个字符,使用单引号括起来;Boolean 表示布尔值,只有 true 和 false 两个取值。
-
Kotlin 复杂数据类型包括:
数组:可以存储同一类型的多个元素,使用 Array 类型表示,可以使用 arrayOf() 函数创建。
列表:可以存储不同类型的多个元素,使用 List 类型表示,可以使用 listOf() 函数创建。
集合:可以存储不同类型的多个元素,使用 Set 类型表示,可以使用 setOf() 函数创建。
映射:可以存储键值对,使用 Map 类型表示,可以使用 mapOf() 函数创建。
类:可以封装数据和行为,使用 class 关键字定义,可以创建对象实例。
接口:可以定义一组方法,使用 interface 关键字定义,可以被类实现。
枚举:可以定义一组常量,使用 enum 关键字定义,可以使用 when 表达式进行匹配。
泛型:可以定义一种通用的类型,使用 <T> 表示,可以在类、函数、接口中使用。
var 和 val的区别
var 定义的为可变类型变量
val 定义不可变类型变量
continue break return
contiune 跳过本次循环
break 跳出循环
return 结束
数组使用
方式一
var arr1 = arrayOf(1,2,3)
方式二
var arr2 = IntArray(10)
多行字符串
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n54" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var s2 = """
这是一个
多行的
字符串
""".trimIndent()
println(s2)
println(s2[5])</pre>List的使用
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n56" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var list1 = listOf<String>("a","b","c")
for (l in list1){
println(l)
}</pre><pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n57" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var list2 = mutableListOf<String>("1","2","3")
list2.add("4")
list2.add("5")
list2.add("6")
for (l in list2){
println(l)
}</pre>Map的使用
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n59" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var map = mapOf<String, String>("xing" to "133")
println(map["xing"])var map2 = mutableMapOf<String,String>()
map2.put("ck","1")
map2.put("ba","2")
println("ck")</pre>元祖的使用
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n61" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var pair = Pair<String, Int>("zhang",90)
println(pair.first)
println(pair.second)var triple = Triple("li", 90, 80)
println(triple.first)
println(triple.second)
println(triple.third)val a = 1
var res = if (1 == a) {
"bala"
} else {
"bili"
}</pre>when 使用
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n63" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var wang = 110
var res2 = when (wang) {
90 -> {
"不及格"
}100 -> {
"及格"
}110 -> {
"满分"
}else -> {
"缺考"
}
}
println(res2)</pre>foreach使用
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n65" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var list = listOf(1, 2, 3)
list.forEach {
println(it)
}</pre>while 使用
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="kotlin" cid="n67" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> var count = 0;
var sum = 0;
while (count <= 200) {
sum += count;
count++;
}
println(sum)</pre>函数的使用
在 Kotlin 中,函数的定义使用关键字 fun,后面跟着函数名和参数列表。函数体可以是一个表达式或者一个代码块。下面是一个简单的函数定义的例子:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n70" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">fun add(a: Int, b: Int): Int {
return a + b
}
//调用
val result = add(1, 2)</pre>函数的参数
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n72" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//Kotlin 中的函数参数可以有默认值,也可以使用命名参数。下面是一个使用默认值和命名参数的函数定义的例子:
fun greet(name: String = "World", message: String = "Hello") {
println("name!")
}greet() // 输出 "Hello, World!"
greet("Kotlin") // 输出 "Hello, Kotlin!"
greet(message = "Hi", name = "Java") // 输出 "Hi, Java!"
</pre>函数的返回值
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n74" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//Kotlin 中的函数可以有返回值,也可以没有返回值。如果函数没有返回值,可以使用 Unit 类型来表示。下面是一个没有返回值的函数定义的例子:
fun printMessage(message: String): Unit {
println(message)
}</pre>函数的高阶用法:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n76" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//Kotlin 中的函数可以作为参数传递给其他函数,也可以作为返回值返回。这种函数作为参数或返回值的用法称为高阶函数。下面是一个使用高阶函数的例子:
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}val result = calculate(1, 2) { a, b -> a + b }</pre>
类与对象的使用
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n78" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">open class Person(val name: String, var age: Int) {
fun sayHello() {
println("hello ,my name is $name")
}
}
var person = Person("zhang",20)
person.sayHello()//类的继承
class Student(name: String, age: Int, var grade: Int) : Person(name, age) {
fun study() {
println("grade ")
}
}
var student = Student("li",18,10)
student.sayHello()
student.study()//类的实现
interface Shape {
fun area(): Double
}class Rectangle(val width: Double, val height: Double) : Shape {
override fun area(): Double {
return width * height
}
}var rectangle = Rectangle(22.1, 33.3) println(rectangle.area())
//关于构造函数 主构造函数 和次构造函数
class Rectangle(val width: Double, val height: Double) {
constructor(side: Double) : this(side, side)
fun area(): Double {
return width * height
}
}
val rectangle = Rectangle(5.0, 10.0)val square = Rectangle(3.0)
println("Rectangle area: {square.area()}")//在这个例子中,我们定义了一个名为Rectangle的类,它有两个属性:width和height。
//我们还定义了一个主构造函数,它接受两个参数,并使用val关键字来定义属性并在构造函数中初始化它们。
//我们还定义了一个次构造函数,它接受一个参数,并调用主构造函数来创建一个正方形
//最后,我们定义了一个名为area的方法,它可以计算矩形的面积。</pre>数据类,伴生类,枚举类
-
数据类:数据类是 Kotlin 中的一种特殊类,它主要用于存储数据。数据类会自动生成一些通用的方法,如 equals()、hashCode()、toString() 等,这些方法可以让我们更方便地操作数据类对象
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n83" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//数据类
data class User(val name: String, val age: Int) {
}val user = User("Tom", 18)
</pre> -
伴生类:它是与类对象相关联的类,而不是与类的实例相关联的类。我们可以使用伴生类来定义一些静态方法或静态属性。自己的理解:伴随着类的创建而创建的静态方法 或者 静态属性,可以直接通过类名 .出来
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n86" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">class MyClass {
companion object{
val name = "MyClass"
fun sayHello(){
println("hello")
}
}
}//调用伴生类的属性和方法
println(MyClass.name)
println(MyClass.sayHello())</pre> -
枚举类:它用于表示一组有限的值。枚举类中的每个值都是一个对象,我们可以使用枚举类来定义一些常量或状态
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n89" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">enum class Color(var rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}//调用
println(Color.BLUE.rgb)</pre> -
密封类:它们可以看作是枚举类的扩展,因为它们也具有固定数量的子类。但是,密封类的子类可以包含状态信息,而枚举类的每个常量只是一个对象
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n92" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//密封类的子类必须在同一个文件中声明,并且必须是密封类的直接子类
sealed class Result
class Success(val message: String) : Result()
class Error(val error: Throwable) : Result()//使用
fun handleResult(result: Result) {
when (result) {
is Success -> println(result.message)
is Error -> println(result.error.message)
}
}</pre>
对象表达式
对象表达式是 一种创建匿名对象的方式 类似Java中的匿名内部类
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n95" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> //使用对象表达式
var obj= object : Runnable {
override fun run() {
println("hello world")
}
}
obj.run()</pre>单例
使用
object
关键字创建的对象是线程安全的,且只会被初始化一次<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n98" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">object Single {
fun sayHello() {
println("hello")
}
}//调用
Single.sayHello()</pre>委托和延迟委托
Kotlin 的属性委托是一种强大的语言特性,它允许我们将一个属性的访问和修改委托给另一个对象。这种机制使得我们可以更加灵活地管理属性的行为,并且可以避免重复的代码。
属性委托的用法如下:
- 创建一个委托类
首先,我们需要创建一个委托类,这个委托类需要实现 getValue() 和 setValue() 方法。这两个方法分别用于获取属性值和设置属性值。
例如,我们可以创建一个名为 LazyProperty 的委托类,实现了 getValue() 和 setValue() 方法,用于实现属性的延迟初始化:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n107" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">class LazyProperty<T>(private val initializer: () -> T) {
private var value: T? = null
operator fun getValue(thisRef: Any?, property: KProperty<>): T {
if (value == null) {
value = initializer()
}
return value!!
}
operator fun setValue(thisRef: Any?, property: KProperty<>, value: T) {
this.value = value
}
}</pre>在上面的代码中,我们定义了一个泛型的委托类 LazyProperty,它接收一个 lambda 表达式作为构造函数参数。在 getValue() 方法中,如果属性值没有被初始化,则调用 lambda 表达式进行初始化,并返回属性值;在 setValue() 方法中,直接将属性值设置为指定的值。
- 使用委托类
接下来,我们可以在类中定义一个属性,并使用委托类进行属性的访问和修改。
例如,我们可以在类中定义一个名为 lazyValue 的属性,使用 LazyProperty 委托类进行延迟初始化:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n114" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">class MyClass {
val lazyValue: String by LazyProperty { "Hello" }
}</pre>在上面的代码中,我们定义了一个名为 lazyValue 的属性,使用 by 关键字将其委托给 LazyProperty 委托类。由于 LazyProperty 实现了 getValue() 方法,因此可以在属性首次被访问时进行延迟初始化,并返回初始化后的值。
除了延迟初始化外,属性委托还可以用于实现属性的缓存、属性的验证等。Kotlin 标准库中已经提供了一些常用的属性委托,例如 lazy、observable 等,可以直接使用。
标准库中lazy 的使用
在 Kotlin 中,lazy 是一种属性委托,用于实现延迟初始化。它可以让我们在第一次使用属性时才进行初始化,而不是在对象创建时就立即初始化。这样可以避免不必要的初始化,提高代码的性能和效率。
lazy 的用法如下:
- 创建一个 lambda 表达式
首先,我们需要创建一个 lambda 表达式,用于实现属性的初始化。例如,我们可以创建一个 lambda 表达式,用于初始化一个字符串:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n124" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">val lazyValue: String by lazy {
println("Initializing...")
"Hello"
}</pre>在上面的代码中,我们定义了一个名为 lazyValue 的属性,使用 by 关键字将其委托给 lazy。在 lazy 的后面,我们定义了一个 lambda 表达式,用于实现属性的初始化。在这个 lambda 表达式中,我们输出了一条日志,用于表示属性的初始化过程,并返回了一个字符串 "Hello"。
- 使用属性
接下来,我们可以在类中使用这个属性。由于 lazy 属性是延迟初始化的,因此在第一次使用属性时才会进行初始化。例如:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n130" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">fun main() {
val obj = MyClass()
println(obj.lazyValue)
println(obj.lazyValue)
}</pre>在上面的代码中,我们创建了一个 MyClass 的对象,并分别两次访问了 lazyValue 属性。由于 lazyValue 是延迟初始化的,因此第一次访问时会执行属性的初始化,并输出 "Initializing..." 的日志。在第二次访问时,由于属性已经被初始化,因此不会再次执行初始化过程,直接返回属性的值 "Hello"。
综上所述,lazy 是一种属性委托,用于实现延迟初始化。它可以让我们在第一次使用属性时才进行初始化,避免不必要的初始化,提高代码的性能和效率。
IO操作
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n136" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> //创建文件 写在了项目文件夹根目录下
val file = File("example.txt")
file.createNewFile()//写入文件 var fileWriter = FileWriter(file) fileWriter.write("hello world!") fileWriter.close() //读取文件 var fileReader = FileReader(file) var bufferedReader = BufferedReader(fileReader) val content = bufferedReader.readText() fileReader.close() println(content) //复制文件 var file1 = File("example_copy.txt") file.copyTo(file1) //删除文件 file1.delete()</pre>
协程
Kotlin中的协程是一种轻量级的并发机制,可以让开发者以同步的方式编写异步代码。协程可以在不阻塞线程的情况下暂停和恢复执行,从而提高应用程序的性能和响应能力。
在Kotlin中,协程是通过协程构建器来创建的。协程构建器包括launch、async和runBlocking等。其中,launch用于启动一个新的协程,async用于启动一个新的协程并返回一个Deferred对象,runBlocking用于启动一个新的协程并阻塞当前线程直到协程执行完成。
协程可以使用挂起函数来暂停执行。挂起函数是一种特殊的函数,它可以在不阻塞线程的情况下暂停执行,并在某个条件满足时恢复执行。Kotlin中的挂起函数包括delay、withContext和suspendCoroutine等。
协程还可以使用协程作用域来管理协程的生命周期。协程作用域是一种特殊的对象,它可以用来启动和取消协程。Kotlin中的协程作用域包括GlobalScope、CoroutineScope和SupervisorJob等。
总之,Kotlin中的协程是一种非常强大的并发机制,可以让开发者以同步的方式编写异步代码,从而提高应用程序的性能和响应能力。
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n143" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//首先需要在build.gradle 添加依赖
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1");import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
// 在后台异步执行耗时操作
val result = withContext(Dispatchers.IO) {
delay(1000L)
"World!"
}
// 在主线程中更新 UI
println("Hello, $result")
}
println("Waiting...")
job.join()
println("Done!")
}//在这个示例中,我们使用了 runBlocking 函数来创建一个协程作用域,并且使用 launch 函数来创建一个新的协程。在 launch 函数中,我们使用了 withContext 函数来在后台异步执行耗时操作,然后在主线程中更新 UI。在主函数中,我们输出 “Waiting…”,然后等待协程执行完毕后再输出 “Done!”。
</pre>扩展函数
扩展函数是一种特殊的函数,可以在不修改原始类的情况下,为该类添加新的函数。
扩展函数的语法格式为:fun ClassName.functionName(parameters){...},其中ClassName表示要扩展的类名,functionName表示要添加的函数名,parameters表示函数的参数列表。扩展函数可以在任何地方被调用,就像原始类的成员函数一样。扩展函数的一个重要特点是,它们不能访问原始类的私有成员变量和方法,只能访问公共成员变量和方法。扩展函数的另一个重要特点是,它们不能被覆盖,因为它们不是原始类的成员函数。扩展函数可以为任何类添加新的函数,包括系统类和自定义类。扩展函数的使用可以简化代码,提高代码的可读性和可维护性。
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n149" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//例如,假设我们想为String类添加一个新的函数,用于将字符串中的所有空格替换为下划线。我们可以使用扩展函数来实现这个功能,代码如下:
fun String.replaceSpacesWithUnderscores(): String {
return this.replace(" ", "_")
}//在上述代码中,我们定义了一个名为replaceSpacesWithUnderscores()的扩展函数,它可以被任何String对象调用。该函数使用String类的replace()方法将字符串中的所有空格替换为下划线,并返回替换后的字符串。使用该函数的示例代码如下:
val str = "Hello World"
val newStr = str.replaceSpacesWithUnderscores()
Log.d(TAG, newStr) // 输出:Hello_World//在上述代码中,我们首先定义了一个字符串变量str,然后调用replaceSpacesWithUnderscores()函数将字符串中的空格替换为下划线,并将结果保存到newStr变量中。最后,我们使用Log.d()函数将替换后的字符串打印到控制台中。</pre>
其他一些奇怪的语法
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n153" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;"> serviceIntent = Intent(this@MainActivity, FloatingClickService::class.java)
startService(serviceIntent)
//在Kotlin中,使用双冒号运算符(::)可以获取一个类的引用。在这里,FloatingClickService::class表示FloatingClickService类的引用,
//FloatingClickService::class.java则表示该类的Java类对象。这个Java类对象可以用作Intent构造函数的第二个参数,以指定要启动的服务的类</pre>this 关健字的写法
java MainActivity.this
kotlin this@MainActivity
class关键字
java MainActivity.class
kotlin MainActivity::class.java
Kotlin 的类和方法默认是不能被继承和重写的,如果想要被继承或者重写必须要使用 open 关键字进行修饰
类型比较
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="java" cid="n163" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">if ("1" instanceof String) {
}
if (!("2" instanceof String)) {
}
//kotlin
if ("1" is String) {}
if ("2" !is String) {
}</pre>
比较对象
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="java" cid="n165" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//java
// 比较两个对象内容是否一样
if (object1.equals(object2)) {}
if (!object3.equals(object4)) {}
// 比较两个对象是否是同一个
if (object5 == object6) {}
if (object7 != object8) {
}
//kotlin
// 比较两个对象内容是否一样
if (object1 == object2) {}
if (object3 != object4) {}
// 比较两个对象是否是同一个
if (object5 === object6) {}
if (object7 !== object8) {
}
//总结:Kotlin 中 == 和 Java 中的 equals 效果是一样的,而 Kotlin 中 === 和 Java 中 == 的效果是一样的</pre>对于空安全
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n168" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">fun getText() : String? {
return null
}
// 返回的值可能为null 那么在使用的时候
var text = getText()
1. print(text!!.length)
2. print(text?.length)</pre>遇到的一些注解 记录
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n170" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">@Suppress("SetJavaScriptEnabled") //抑制</pre>
这段代码是一个Kotlin注解,
@Suppress
用于忽略指定的编译器警告或错误。在这个例子中,
"SetJavaScriptEnabled"
是一个字符串参数,表示忽略设置JavaScript启用时的警告。通常情况下,当我们在使用WebView控件时,如果启用了JavaScript,编译器会发出警告,因为这可能会带来安全风险。通过在该代码上添加
@Suppress("SetJavaScriptEnabled")
注解,我们可以告诉编译器忽略这个警告。@jvmOverloads 是一个kotlin注解,用于在java代码中生成多个重载函数,这样就可以使用不同数量的参数来调用kotlin函数,写法上更加灵活
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n175" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">class BrowserView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null,
defStyleAttr: Int = android.R.attr.webViewStyle, defStyleRes: Int = 0)</pre>@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
是一个Kotlin注解,用于指定注解的保留策略。具体而言,AnnotationRetention.RUNTIME
表示该注解在运行时保留,并且可以通过反射机制获取。保留策略是指注解的生命周期,即注解在编译期、类加载期还是运行期保留。Kotlin中有三种保留策略:
AnnotationRetention.SOURCE
:表示该注解仅在源代码中保留,编译后不会包含在字节码中。AnnotationRetention.BINARY
:表示该注解在编译期和类加载期保留,但是在运行期不会保留。AnnotationRetention.RUNTIME
:表示该注解在运行期保留,并且可以通过反射机制获取。
在上面的例子中,
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
注解被应用于自定义注解(例如@CheckNet
)上,表示该注解在运行期保留,并且可以通过反射机制获取。这对于需要在运行期动态处理注解的情况非常有用。
泛型
https://www.jianshu.com/p/be6cfc411dec
apply用法
apply
是 Kotlin 标准库中的一个作用域函数,它的主要作用是在对象上执行一系列操作,并返回对象本身。
apply
函数接受一个 lambda 表达式作为参数,在 lambda 表达式中可以对对象进行属性或方法的调用、赋值等操作。在 lambda 表达式内部,可以使用 this
来引用当前对象。
apply
函数的返回值是当前对象本身,因此可以在调用完 apply
后继续链式调用该对象的其他方法。
下面是一个示例代码,演示了 apply
的用法:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="kotlin" cid="n195" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; caret-color: rgb(184, 191, 198); color: rgb(184, 191, 198); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: initial initial; background-repeat: initial initial;">data class Person(var name: String, var age: Int)
val person = Person("Alice", 25).apply {
// 在 apply 的 lambda 表达式内部,对 person 对象进行操作
name = "Bob"
age += 5
}
println(person) // 输出:Person(name=Bob, age=30)</pre>
在上面的例子中,首先创建了一个 Person
对象并传入初始值。然后使用 apply
函数对这个对象进行操作,在 apply
的 lambda 表达式内部将 name
修改为 "Bob",将 age
增加 5。最后,将修改后的 person
打印出来。
通过使用 apply
函数,我们可以方便地对对象进行多个属性或方法的连续操作,并且不需要额外创建临时变量来存储中间结果。这样可以使代码更加简洁、可读性更高。在实际开发中,apply
函数常用于对象的初始化或配置过程。