第五章 kotlin表达式

193 阅读2分钟

5.1、只读变量和变量和常量

变量表达

var 来表示变量

只读变量

val表示只读变量

只读变量VS常量

常量的意思是:永远不变。

但是请看下面的例子,Test中的b,它会随着Math的值不一样,获取到的b的值是不一样的,它的值是变化的,所以称为只读变量

class Test {
    val b: Int
        get() {
            return (Math.random() * 1000).toInt()
        }
}

常量要求和表示

1、只能修饰基本类型

2、只能定义在全局范围

3、必须立即用字面量初始化

   val b = 3

5.2、分支表达式

if - else表达式

        var a: Int = 4
        var c = if (a == 3) 4 else 5
        Log.e("cdx", "c:$c")

when 表达式写法

注意其中的 -> 箭头。类似于Java中的switch - case

when表达式 - 条件转移到分支、简写写法

        val a: Any = 4
        val c: Any
        when {
            a is String -> c = a.length
            a == 3 -> c = 3
            else -> c = 5
        }

简化写法

        val a: Any = 4
        val c = when {
            a is String -> a.length
            a == 3 -> 3
            else -> 5
        }

try - catch 表达式

Java不同的地方:try - catch表达式可以有返回值

        var a = 1
        var b = 0
        val c = try {
            a / b
        } catch (e: Exception) {
            0
        }

5.3、运算符与中缀表达式

运算符网站

https://kotlinlang.org/docs/operator-overloading.html

== 运算符 VS equal

        val str1 = "Hello"
        val str2 = "World"
        // 下面的两种方式是完全等价的
        val result1 = (str1 == str2)
        var result2 = str1.equals(str2)

+ 运算符 VS plus

        val str1 = "a"
        val str2 = "b"
        // 下面的两种方式是完全等价的
        val result1 = (str1 + str2)
        var result2 = str1.plus(str2)

        Log.e("cdx", result1.toString())
        Log.e("cdx", result2.toString())

in 运算符 VS contains

in 运算符 和contains 方法完全一样

        var list = listOf(1, 2, 3, 4)
        var result = 2 in list
        Log.e("cdx", result.toString())
        Log.e("cdx", list.contains(2).toString())

[] 运算符 VS get

        val map = mapOf("name" to "张三", "age" to 20)
        // [] 和 get 的方式完全一样,编译器推荐使用第二种方式
        Log.e("cdx", map.get("name").toString())
        Log.e("cdx", map["name"].toString())

> VS compareTo

        var result1 = 2 > 3
        var result2 = 2.compareTo(3) > 0
        Log.e("cdx", result1.toString())
        Log.e("cdx", result2.toString())

() 与 invoke

表示 执行

        // 定义匿名函数,用变量去接受这个函数
        var func = fun() {
            Log.e("cdx", "方法执行了")
        }

        // 第一种调用函数方法
        func()

        // 第二种调用函数方法
        func.invoke()

自定义运算符

第一步:定义运算符,相当于给Complex这个哥么增加了2个标签(比如幽默),比如 + 这个标签,那么两个Complex哥么通过标签就可以相互的认识。

package com.example.kotlindemo

class Complex(var real: Double, var image: Double) {
    override fun toString(): String {
        return "$real + $image"
    }
}

// 自定义操作符
// 相当于给Complex增加了plus操作符的功能,相当于增加了 + 的功能
operator fun Complex.plus(other: Complex): Complex {
    return Complex(this.real + other.real, this.image + other.image)
}

// 自定义减的运算符
// 给Complex增加了减的运算符,增加了 - 的功能
operator fun Complex.minus(other: Complex): Complex {
    return Complex(this.real - other.real, this.image - other.image)
}

第二步:然后在页面里面去调用

class MainActivity2 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        var c1 = Complex(1.0, 2.0)
        var c2 = Complex(3.0, 2.0)

		// 
        var result1 = c1 + c2
        Log.e("cdx", result1.toString())
        var result2 = c1 - c2
        Log.e("cdx", result2.toString())

    }
}

中缀表达式-infix的介绍

Kotlin允许在不使用括号点号的情况下调用函数,那么这种函数被称为 infix函数。

中缀表达式要求和使用

1、只有一个参数。

2、增加infix参数,表示可以省略括号和点号。

class MainActivity2 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        2.to(3)
        2 to 3

    }

    // infix:中缀表达式的的标识
    // A,B 都是泛型
    infix fun <A, B> A.to(b: B): Pair<A, B> {
        return Pair(this, b)
    }
}

5.4、Lambda表达式

匿名函数的传递

        // func:是变量名
        // 匿名函数赋值给了一个变量
        var func = fun() {
            Log.e("cdx", "test")
        }

匿名函数的调用

        // func:是变量名
        // 匿名函数赋值给了一个变量
        var func = fun() {
            Log.e("cdx", "test")
        }

        // 通过()运算符去执行
        func()
        // 通过invoke()去执行
        func.invoke()

Lambda表达式的类型

Lambda表达式就是匿名函数的简化

        // 没有参数的Lambda表达式
        // 注意func1的类型 () -> Int
        var func1: () -> Int = {
            Log.e("cdx", "test")
        }

        // 有参数的Lambda表达式
        // 注意func2的类型 (Int, Int) -> Int
        var func2: (Int, Int) -> Int = { p1: Int, p2: Int ->
            Log.e("cdx", "test,$p1 $p2")
        }

Lambda表达式返回值

是由Lambda中的最后一行的语句决定。

5.5、为Person实现equals 和hashCode

package com.example.kotlindemo

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

class MainActivity2 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        val hashSet = HashSet<Person>()
        hashSet.add(Person("张三", 15))
        hashSet.add(Person("张三", 15))

        Log.e("cdx", hashSet.size.toString())

    }
}

class Person(var name: String, var age: Int) {

    override fun equals(other: Any?): Boolean {
        Log.e("cdx", "equals")
        val person = (other as? Person) ?: return false
        return person.name == name && person.age == age
    }

    override fun hashCode(): Int {
        Log.e("cdx", "hashCode")
        return name.hashCode() * 7 + age * 5;
    }
}

5.6、为String实现四则运算

需要实现下面的效果,实现字符串的加减乘除

分析:

1、没有办法修改String的源码,所以我们需要使用扩展方法。

2、借助于自定义运算符。

package com.example.kotlindemo

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import java.lang.StringBuilder

class MainActivity2 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        val str: String = "HelloWorld"
        val result = str - "World"
        Log.e("cdx", result)

        val result2 = str * 5
        Log.e("cdx", result2)

        val result3 = str / "l"
        Log.e("cdx", result3.toString())
    }
}

operator fun String.minus(other: Any): String {
    return this.replaceFirst(other.toString(), "")
}

operator fun String.times(time: Int): String {
    var sb = StringBuilder()
    for (i in 0 until time) {
        sb.append(this)
    }
    return sb.toString()
}

operator fun String.div(str: String): Int {
    // 这个东西很好玩
    // String字符串上一点一点的划,划的长度是str.lenght,
然后间隔是1,表示一个一个的划
    // 然后获取到划到的集合
    return this.windowed(str.length, 1) {
        it == str
    }
        // 然后数一数里面欧多少个满足条件的,it为true的就筛选出来
        .count {
            it
        }
}