Kotlin常用语法记录

1. 定义函数

具有返回Int类型的两个Int参数的函数:

fun sum(a: Int, b: Int): Int复制代码

函数与表达主体和推断返回值的类型:

fun sum(a: Int, b: Int) = a + b复制代码

函数返回无意义值:(Unit返回类型可以省略:)

fun printSum(a: Int, b: Int): Unit复制代码

2. 定义局部变量

分配一次(只读)局部变量:

val a: Int = 1 
val b = 2复制代码

可变变量:

var x = 5复制代码

3. 使用字符串模板

模板表达式以美元符号($)开头以及简单名称组成:

var a = 1
println("a is $a")复制代码

或大括号中的任意表达式

val s = "abc"
val str = "$s.length is ${s.length}"

fun maxOf(a: Int, b: Int): Int
println("max of 0 and 42 is ${maxOf(0, 42)}")复制代码

4. 使用条件表达式

使用if表达式:

fun maxOf(a: Int, b: Int) = if (a > b) a else b复制代码

if分支可以是块,并且最后一个表达式是块的值:

val max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}复制代码

5. 使用可空值来检查null值

当可能为null值时,引用必须被明确地标记为可空(null)

如果str不包含整数,则返回null

fun parseInt(str: String): Int? {
    // ...
}复制代码

在 Kotlin 中,类型系统区分一个引用可以容纳 null (可空引用)还是不能容纳(非空引用)。

例如,String 类型的常规变量不能容纳 null

var a: String = "abc"
a = null // 编译错误复制代码

如果要允许为空,我们可以声明一个变量为可空字符串,写作 String?

var b: String? = "abc"
b = null // ok复制代码

现在,如果你调用 a 的方法或者访问它的属性,它保证不会导致 NPE,这样你就可以放心地使用:

val l = a.length复制代码

但是如果你想访问 b 的同一个属性,那么这是不安全的,并且编译器会报告一个错误:

val l = b.length // 错误:变量“b”可能为空复制代码

但是我们还是需要访问该属性,对吧?有几种方式可以做到

  • 在条件中判空

    val l = if (b != null) b.length else -1复制代码
  • 安全的调用操作符

    如果任意一个属性(环节)为空,这个链式调用就会返回 nul

    b?.length
    bob?.department?.head?.name复制代码

    如果要只对非空值执行某个操作,安全调用操作符可以与 let 一起使用:

    b?.length?.let { println(it) } / 输出 A 并忽略 null复制代码

Elvis 操作符

当我们有一个可空的引用 r 时,我们可以说“如果 r 非空,我使用它;否则使用某个非空的值 x

val l: Int = if (b != null) b.length else -1复制代码

这还可以通过 Elvis 操作符表达,写作 ?:

val l = b?.length ?: -1复制代码

!! 操作符

第三种选择是为 NPE 爱好者准备的。我们可以写 b!! ,这会返回一个非空的 b
(例如:在我们例子中的 String)或者如果 b 为空,就会抛出一个 NPE 异常:

val l = b!!.length复制代码

安全的类型转换as?

如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException
另一个选择是使用安全的类型转换,如果尝试转换不成功则返回 null

val aInt: Int? = a as? Int复制代码

可空类型的集合

如果你有一个可空类型元素的集合,并且想要过滤非空元素,你可以使用 filterNotNull 来实现。

val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()复制代码

6. 使用类型检查和自动转换

is运算符检查表达式是否是类型的实例。

obj is String复制代码

7. 使用for循环

for循环提供迭代器用来遍历任何东西。 语法如下:

for (item in collection) print(item)复制代码

主体可以是一个块,如下 -

for (item: Int in ints) {
    // ...
}复制代码

for循环数组被编译为一个基于索引的循环,它不会创建一个迭代器对象。如果要遍历具有索引的数组或列表,可以这样做:

for (i in array.indices) {
    print(array[i])
}复制代码

或者,可以使用withIndex库函数:

for ((index, value) in array.withIndex()) {
    println("the element at $index is $value")
}复制代码

8. 使用 while 循环

whiledo..while 用法和java语言中一样,如下 -

while (x > 0) {
    x--
}

do {
    val y = retrieveData()
} while (y != null) // y is visible here!复制代码

9. 使用 when 表达式

如果许多情况应该以同样的方式处理,分支条件可使用逗号组合:

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}复制代码

可以使用任意表达式(不仅仅是常量)作为分支条件

when (x) {
    parseInt(s) -> print("s encodes x")
    else -> print("s does not encode x")
}复制代码

还可以检查值是否在或不在(in/!in)范围内或集合中

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}复制代码

另一个可能性是检查一个值是否(is/!is)为指定类型的值。请注意,由于智能转换,可以访问类型的方法和属性,而无需任何额外的检查。

fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}复制代码

10. 使用范围

使用in操作符检查数字是否在指定范围内:

fun main(args: Array<String>) {
    val x = 10
    val y = 9
    if (x in 1..y+1) {
        println("fits in range")
    }
}复制代码

检查一个数字是否超出指定范围:!in

fun main(args: Array<String>) {
    val list = listOf("a", "b", "c")

    if (-1 !in 0..list.lastIndex) {
        println("-1 is out of range")
    }
    if (list.size !in list.indices) {
        println("list size is out of valid list indices range too")
    }
}复制代码

迭代范围:step

fun main(args: Array<String>) {
    for (x in 1..10 step 2) {
        println(x)
    }
    println("===============================")
    for (x in 9 downTo 0 step 3) {
        println(x)
    }
}复制代码

上面代码,执行结果如下 -

1
3
5
7
9
===============================
9
6
3
0复制代码

检查集合是否包含一个对象,使用in运算符:

fun main(args: Array<String>) {
    val items = setOf("apple", "banana", "kiwi")
    when {
        "orange" in items -> println("juicy")
        "apple" in items -> println("apple is fine too")
    }
}复制代码

11. 高阶函数

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

这种函数的一个很好的例子是 lock(),它接受一个锁对象和一个函数,获取锁,运行函数并释放锁

fun  lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
        return body()
    }
    finally {
        lock.unlock()
    }
}复制代码

让我们来检查上面的代码:body 拥有函数类型:() -> T
所以它应该是一个不带参数并且返回 T 类型值的函数。
它在 try{: .keyword }-代码块内部调用、被 lock 保护,其结果由lock()函数返回。

如果我们想调用 lock() 函数,我们可以把另一个函数传给它作为参数(参见函数引用):

fun toBeSynchronized() = sharedResource.operation()

val result = lock(lock, ::toBeSynchronized)复制代码

通常会更方便的另一种方式是传一个 lambda 表达式:

val result = lock(lock, { sharedResource.operation() })复制代码
  1. Lambda 表达式

    • lambda 表达式总是被大括号括着,
    • 其参数(如果有的话)在 -> 之前声明(参数类型可以省略),
    • 函数体(如果存在的话)在 -> 后面。

    在 Kotlin 中有一个约定,如果函数的最后一个参数是一个函数,并且你传递一个 lambda 表达式作为相应的参数,你可以在圆括号之外指定它:

    lock (lock) {
        sharedResource.operation()
    }复制代码

    高阶函数的另一个例子是 map()

    fun  List.map(transform: (T) -> R): List {
        val result = arrayListOf()
        for (item in this)
            result.add(transform(item))
        return result
    }复制代码

    该函数可以如下调用:(请注意,如果 lambda 是该调用的唯一参数,则调用中的圆括号可以完全省略。)

    val doubled = ints.map { value -> value * 2 }复制代码
  2. it:单个参数的隐式名称

    一个有用的约定是,如果函数字面值只有一个参数,
    那么它的声明可以省略(连同 ->),其名称是 it

    ints.map { it * 2 }复制代码

Kotlin惯用语法

1. 创建DTO(POJO/POCO)

我们经常创建一个类,只能持有数据。 在这样一个类中,一些标准功能通常是从数据中机械推导出来的。 在Kotlin中,这被称为数据类,并被标记为数据:

data class Customer(val name: String, val email: String)复制代码

编译器自动从主构造函数中声明的所有属性导出以下成员:

  • equals()/hashCode()函数对
  • toString()函数,它由”User(name=John, age=42)“构成
  • componentN()函数对应于属性的声明顺序

如果这些函数中的任何一个在类体中显式定义或继承自其基类型,则不会生成该函数。

为了确保生成的代码的一致性和有意义的行为,数据类必须满足以下要求:

  • 主构造函数需要至少有一个参数;
  • 主构造函数的所有参数需要标记为 valvar
  • 数据类不能是抽象、开放、密封或者内部的;
  • 数据类只能实现接口(在1.1之前)。

复制

在很多情况下,我们需要复制一个对象改变它的一些属性,但其余部分保持不变。 copy() 函数就是为此而生成。对于上文的 User 类,其实现会类似下面这样:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)复制代码
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)复制代码

数据类和解构声明

为数据类生成的 Component 函数 使它们可在解构声明中使用:

val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // 输出 "Jane, 35 years of age"复制代码

2. 函数参数的默认值

fun foo(a: Int = 0, b: String = "") { ... }复制代码

3. 过滤列表

val positives = list.filter { it > 0 }复制代码

4. 字符串插值

println("Name $name")复制代码

5. 实例检查

when (x) {
    is Foo -> ...
    is Bar -> ...
    else   -> ...
}复制代码

6. 遍历映射/列表对

for ((k, v) in map) {
    println("$k -> $v")
}复制代码

7. 使用范围

for (i in 1..100) { ... }  // closed range: includes 100
for (i in 1 until 100) { ... } // half-open range: does not include 100
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }复制代码

8. 只读列表

val list = listOf("a", "b", "c")复制代码

9. 只读映射

val map = mapOf("a" to 1, "b" to 2, "c" to 3)复制代码

10. 访问映射

println(map["key"]) // 打印值
map["key"] = value // 设置值复制代码

11. 懒属性

val p: String by lazy {
    // compute the string
}复制代码

12. 扩展函数

un String.spaceToCamelCase() { ... }

"Convert this to camelcase".spaceToCamelCase()复制代码

13. 创建单例

object Resource {
    val name = "Name"
}复制代码

14. 如果不为null的速记

val files = File("Test").listFiles()

println(files?.size)复制代码

15. 如果不为nullelse的速记

val files = File("Test").listFiles()

println(files?.size ?: "empty")复制代码

16. 如果为null,执行语句

val data = ...
val email = data["email"] ?: throw IllegalStateException("Email is missing!")复制代码

17. 如果不为null,执行语句

val data = ...

data?.let {
    ... // execute this block if not null
}复制代码

18. 在 when 语句上返回

fun transform(color: String): Int {
    return when (color) {
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("Invalid color param value")
    }
}复制代码

19. try/catch 表达式

fun test() {
    val result = try {
        count()
    } catch (e: ArithmeticException) {
        throw IllegalStateException(e)
    }

    // Working with result
}复制代码

20. if表达式

fun foo(param: Int) {
    val result = if (param == 1) {
        "one"
    } else if (param == 2) {
        "two"
    } else {
        "three"
    }
}复制代码

21. 单表达式函数

fun theAnswer() = 42复制代码

这相当于

fun theAnswer(): Int {
    return 42
}复制代码

这可以与其他惯用语法有效结合,从而代码更短。 例如,与when-expression结合:

fun transform(color: String): Int = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}复制代码

22. 在对象实例上调用多个方法(‘with’)

class Turtle {
    fun penDown()
    fun penUp()
    fun turn(degrees: Double)
    fun forward(pixels: Double)
}

val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
    penDown()
    for(i in 1..4) {
        forward(100.0)
        turn(90.0)
    }
    penUp()
}复制代码

23. 使用可空的布尔值

val b: Boolean? = ...
if (b == true) {
    ...
} else {
    // `b` is false or null
}复制代码

你可能感兴趣的:(移动开发,java)