kotlin笔记

2021-04-21  本文已影响0人  紫鹰

kotlin优势
简洁(data class自带get set equals hashCode toString copy
安全(区别可空和不可空,避免各类空指针)
与java互操作性

基础特性及用法

显式

Kotlin 通过细致的显式声明和约束,使代码的逻辑和结构都更加清晰,并减少错误。

集合
集合也可以根据是否允许容纳 null进行区分(List<Int?> / List<Int> )。
可以使用 filterNotNull()从可为空类型的集合中过滤非空类型。

open:用于继承的类要显示的声明open

inner:内部类,默认内部类不能访问外部类
使用inner标记的类会携带外部类引用,可以访问外部类成员

数据类解构声明
data class User(val name: String = "", val age: Int = 0)
数据类自动对每个属性生成对应的componentN()函数,用于解构声明: val jane = User("Jane", 35)
val (name, age) = jane

    fun MutableList<Int>.swap(index1: Int, index2: Int) {
     val tmp =    this[index1] // this 对应列表本身 this[index1] = this[index2]
     this[index2] = tmp
    }

同时声明以下两个函数回导致冲突:

fun String?.toDecimal(): BigDecimal {...}
fun toDecimal(value: String?): BigDecimal {...}  

扩展函数是静态解析的,其调用取决于声明类型而不是运行时的实际类型

open class C class D: C()
fun C.foo() = "c" fun D.foo() = "d"
fun printFoo(c: C) {
println(c.foo())
}
printFoo(D()) // c

// todo

进阶特性及用法

kotlin中函数的地位

kotlin中函数是头等的。可以存储在变量与数据结构中、可以作为参数传递给高阶函数、也可以从高阶函数返回。

高阶函数

高阶函数是将函数用作参数或返回值的函数。

fun <T> lock(lock: Lock, body: () ‐> T): T {
    lock.lock()
    try {
     return body()
    }
    finally {
     lock.unlock()
   }
}

上述代码中,body就是函数类型,该函数没有输入参数,输出类型为T。 它被 lock 保护,在 try 块中调用,其结果由 lock() 函数返回。 lock() 的调用方法如下。

fun toBeSynchronized() = sharedResource.operation()
val result1 = lock(myLock, ::toBeSynchronized)
val result2 = lock(myLock, { sharedResource.operation() })

函数类型

Kotlin 使用类似 (Int) -> String 的一系列函数类型来处理函数的声明: val onClick: () -> Unit = ……。

这些类型具有与函数签名对应的特殊标示法,即他们的参数和返回值:

还可以通过类型别名给函数类型起一个别称:

 typealias ClickHandler = (Button,ClickEvent) ->Unit

函数类型实例调用

函数类型的值可以通过invoke(...)调用:f.invoke(x)或者直接f(x)

如果该值具有接收者类型,那么应该将接收者作为第一个参数传递。调用接收者的函数值类型的另一个方式是在其前面加上接收者对象,就好比该值是一个扩展函数:

val stringPlus: (String, String) -> String = String::plus
val intPlus: Int.(Int) -> Int = Int::plus

println(stringPlus.invoke("<-", "->"))
println(stringPlus("Hello, ", "world!")) 

println(intPlus.invoke(1, 1))
println(intPlus(1, 2))
println(2.intPlus(3)) // 类扩展调用
    val sum1: (Int, Int) ‐> Int = { x, y ‐> x + y }
    val sum2 = { x: Int, y: Int ‐> x + y }
    sum1(1, 2)
    sum2(1, 2)

如果函数的最后一个参数为表达式,且你传递的是Lamda表达式,那么kotlin的惯例是把Lamda表达式写在括号外面:

lock(myLock, { sharedResource.operation() })
// 等效于
lock (myLock) {
 sharedResource.operation()
}

Lambda表达式和匿名函数可以访问其闭包,也就是外部作用域声明的变量。不同的是,java可以修改从闭包中获取的变量。

使用

    val values = listOf(1, 2, 3, 4, 5)
    val filtered = filter(values, isOdd)

如果Lambda只有一个参数,且编译器可以推断其类型,则可以省略参数,此时该参数会被隐式的声明为it

val isOdd: (Int) -> Boolean = { value -> value % 2 == 1 } val isOdd: (Int) -> Boolean = { it % 2 == 1 }
val isOdd: (Int) -> Boolean = { it % 2 == 1 }

如果省略回影响编译器的类型推断,则不可省略

val isOdd = { value: Int -> value % 2 == 1 }

如果函数只返回一个表达式,则可以省略函数体的大括号(和返回类型),使用 = 连接函数体

fun double(x: Int): Int { return x * 2 } 
fun double(x: Int): Int = x * 2
fun double(x: Int) = x * 2

默认参数调用

reformat(str)

指定参数调用

reformat(str, true, true, false, '_')

使用命名参数,提高代码可读性

reformat(str,normalizeCase = true,upperCaseFirstLetter = true,divideByCamelHumps = false,wordSeparator = '_')

使用如下形式声明委托属性

class Example {
  var p: String by Delegate() 
}

实现委托

 class Delegate {
     operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!" }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
     }
  }

使用

val e = Example()
e.p = "HelloWorld" // HelloWorld has been assigned to 'p' in    Example@17f052a3. println(e.p) // Example@17f052a3, thank you for delegating 'p' to me!

输出

 Running in main
 computed!
 Hello
 Hello

输出

  <no name> -> first
  first -> second
    inline fun <T> lock(lock: Lock, body: () -> T): T { lock.lock()
        try {
           return body()
        } finally {
           lock.unlock()
        }
    }

    foo()
    lock(l) { foo() }
    bar()

相当于

    foo()
    l.lock() 
    try {
       foo()
    } finally {
       l.unlock() 
    }
    bar()

在内联函数中使用 reified 将范型标记为具体化类型参数,在内联函数中,可以像访问参数一样访问具体化类型参数。

  inline fun <reified T: Any> fromJson(json: String): T =
  gson.fromJson(json, T::class.java) 
  val user = fromJson<User>(json)
  val user: User = fromJson(json)
    class Person {
          var age: Int = 10
              get() {
                  return field 
              }
              set(value) {
                  field = value
              }
    }

这里的isAdult相当于java的

  public boolean isAdult() {
        return age >= 18; 
  }

  val person = Person("John", 17) 
  println(person.isAdult) \\ false 
  person.age++ 
  println(person.isAdult) \\ true
上一篇 下一篇

猜你喜欢

热点阅读