kotlin 学习

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("message,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("name is study ingrade ")
    }
    }
    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: {rectangle.area()}") println("Square 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 的属性委托是一种强大的语言特性,它允许我们将一个属性的访问和修改委托给另一个对象。这种机制使得我们可以更加灵活地管理属性的行为,并且可以避免重复的代码。

    属性委托的用法如下:

    1. 创建一个委托类

    首先,我们需要创建一个委托类,这个委托类需要实现 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() 方法中,直接将属性值设置为指定的值。

    1. 使用委托类

    接下来,我们可以在类中定义一个属性,并使用委托类进行属性的访问和修改。

    例如,我们可以在类中定义一个名为 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 的用法如下:

    1. 创建一个 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"。

    1. 使用属性

    接下来,我们可以在类中使用这个属性。由于 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 函数常用于对象的初始化或配置过程。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容