Kotlin笔记2—进阶

文章目录

  • 1 lateinit
  • 2 OnClickListener回调函数简化(SAM转换)
  • 3 伴生对象companion
  • 4 属性委托 by
  • 5 !! 与?与?:
  • 6 Map与FlatMap
  • 7 函数类型
  • 8 高阶函数
  • 9 匿名函数
  • 10 Lambda表达式
  • 11 Kotlin中,理解T.()->Unit 、 ()->Unit与(T) -> Unit

1 lateinit

lateinit 推迟属性初始化

// 在 Kotlin 中,必须在声明对象时初始化对象
val languageName: String? = null

// 使用lateinit后便可不必在声明时初始化了
lateinit val languageName: String

2 OnClickListener回调函数简化(SAM转换)

loginButton.setOnClickListener {
// 当用户点击 loginButton 时,系统会执行下面的代码,
// 相当于在onClick()方法中执行的
   
}

3 伴生对象companion

相当于static

class LoginFragment : Fragment() {

    ...

    companion object {
        private const val TAG = "LoginFragment"
    }
}

4 属性委托 by

private val viewModel: LoginViewModel by viewModels()
  • 只能用于常量val
  • 相当于单例模式(如果为空,则初始化,否则直接得到值)。
  • 只有在第一次调用的时才执行 by 后的表达式,对变量赋值,
  • 后面再调用就直接获取到变量的值了,不会再次执行by 后的表达式了。

举例子:

val tes : String by lazy {
    println("compute")
    "hello"
}
fun main(args: Array<String>) {
	println(tes)
	println(tes)
}

输出:
compute
hello
hello

5 !! 与?与?:

!! 表示确信变量一定不为空,如果为空的话抛出异常,这就跟java一样了

val account = Account("name", "type")
val accountName = account.name!!.trim()

?表示变量可为空,为空了也不抛出异常,将空传递下去,在我这是管不了了,爱咋咋滴

val account = Account("name", "type")

// account.name为空的话,调用trim()不抛异常,而是返回null
val accountName = account.name?.trim() 

?:为?做个兜底保障,都不管了我得管。它后面会跟一个默认值,表示为空的话,就取它后面的默认值

val account = Account("name", "type")
val accountName = account.name?.trim() ?: "Default name"

6 Map与FlatMap

map:遍历每一个元素
flatMap:遍历每一个元素,并铺平元素

var list =listOf(listOf(10,20),listOf(30,40),listOf(50,60))

var mapList = list.map{element->element.toString()}

var flatMapList = list.flatMap{element->element.asIterable()}

flatMap中的函数一定要返回一个Iterable,不然报错
结果:
[[10, 20], [30, 40], [50, 60]]

[10, 20, 30, 40, 50, 60]

7 函数类型

函数类型必须要具有函数的 参数 和 返回值类型
所有函数类型都有一个圆括号括起来的参数类型列表,以及一个返回类型:(A, B) -> C ,参数列表与返回值类型之间通过 -> 符号连接。(A, B) -> C表示接收类型分别为 A 与 B 两个参数并返回一个 C 类型值的函数类型。
eg:

val f: (Int) -> String
() -> String
(Int) -> Unit // Unit表示无返回值

赋值eg:

val block: (Int, Int) -> Int = ::sum

fun sum(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber + secondNumber
}

函数类型的变量需要接收函数类型的对象,那怎么才能得到函数类型的对象呢?Kotlin为我们提供了双冒号(::)来创建函数类型对象的引用。

调用:

val block: (Int, Int) -> Int = ::sum

// 以下调用都是有返回值的,因为(Int, Int) -> Int这个函数类型是有返回值的
block(1, 2)
// 等价于
block.invoke(1, 2)
// 等价于
(::sum)(1, 2)
// 等价于
(::sum).invoke(1, 2)

函数类型的对象后面可以加括号调用,等价于调用原函数。其实这是Kotlin为我们提供的一个语法糖,它本质上还是会去调用该对象的invoke函数

8 高阶函数

一个函数的参数列表中存在函数类型的参数或是函数的返回值类型函数类型,那么这个函数就叫做高阶函数

9 匿名函数

没有名字的函数,无法直接调用。可以赋值给一个变量,或者当作实参直接传递给一个函数类型的形参。

匿名函数能够赋值给变量:

val filterWeightFunPredicate =
            fun(appleBean: AppleBean): Boolean = appleBean.weight

一旦我们将一个匿名函数赋值给一个变量,那个这个变量其实就是一个函数类型的对象,函数类型为:(AppleBean) -> Boolean

我们也可以直接将匿名函数传入另一个函数

filterApple(appleList, fun(appleBean: AppleBean): Boolean
 = appleBean.weight > 6)

实际上你传递的是一个对象,一个函数类型的对象。因为匿名函数它本来就不是函数,而是一个函数类型的对象。

10 Lambda表达式

Lambda表达式的本质是匿名函数,而匿名函数的本质是函数类型的对象。因此,Lambda表达式、匿名函数、双冒号+函数名这三个东西,都是函数类型的对象,他们都能够赋值给变量以及当作函数的参数传递!

Lambda表达式被大括号包围着
Lambda表达式的参数在->的左边,如果没有参数,则只保留函数体
Lambda表达式的函数体在->的后面
Lambda表达式的返回类型值总为函数体最后一行代码的返回值类型

彻底搞懂Kotlin的高阶函数、匿名函数、Lambda表达式: https://www.jianshu.com/p/8eb0623f08c6

11 Kotlin中,理解T.()->Unit 、 ()->Unit与(T) -> Unit

https://www.jianshu.com/p/f3ca07b582e5

你可能感兴趣的:(Kotlin,kotlin,java,开发语言)