基础语法

定义变量/常量

可变变量定义:var
var <标识符> :<类型> = <初始值>
不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)
val <标识符> : <类型> = <初始化值>
变量和常量都可以没有初始化值,但是在使用前必须进行初始化
声明变量的时候支持类型自动推导

  1. val a: Int = 1
  2. val b = 1 // 系统自动推断变量类型为Int
  3. val c: Int // 如果不在声明时初始化则必须提供变量类型
  4. c = 1 // 明确赋值
  5. var x = 5 // 系统自动推断变量类型为Int
  6. x += 1 // 变量可修改

字符串模板

可以在字符串中使用$来表示一个变量名或者变量值

  1. fun test2() {
  2. var name = "ssssheep"
  3. println("Hello,$name")
  4. // 字符串模板中可以写任意表达式
  5. println("${name.uppercase()}")
  6. }
  7. fun main(args : Array<String>) {
  8. test2()
  9. }

NULL检查机制

Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null 或配合 ?:做空判断处理

  1. //类型后面加?表示可为空
  2. var age: String? = "23"
  3. //抛出空指针异常
  4. val ages = age!!.toInt()
  5. //不做处理返回 null
  6. val ages1 = age?.toInt()
  7. //age为空返回-1
  8. val ages2 = age?.toInt() ?: -1

如果一个引用可能是null值的时候,需要其声明的时候就明确的标记为可为null

类型检测和自动类型转换

类似于Java中的instance of,可以使用 is 运算符来检测一个表达式是否为某类型的一个实例

  1. fun test3(data :Any) :Int {
  2. /*
  3. if (data is String) {
  4. return data.length
  5. }
  6. return null?:-1
  7. */
  8. return if (data !is String) {
  9. // 如果不是String类型,就抛出空指针异常
  10. null!!
  11. }else {
  12. data.length
  13. }
  14. }
  15. fun main(args : Array<String>) {
  16. // test1()
  17. // test2()
  18. println(test3(1))
  19. }

或者

  1. fun getStringLength(obj: Any): Int? {
  2. // 在 `&&` 运算符的右侧, `obj` 的类型会被自动转换为 `String`
  3. if (obj is String && obj.length > 0)
  4. return obj.length
  5. return null
  6. }

区间

区间表达式由操作符形式..rangeTo函数和 in 以及 !in形成

  1. fun test4() {
  2. for (i in 1..4) {
  3. println(i)
  4. }
  5. println("*************************")
  6. for (i in 1..10 step 2){
  7. println(i)
  8. }
  9. println("*************************")
  10. for (i in 10 downTo 1 step 2) {
  11. println(i)
  12. }
  13. println("*************************")
  14. for (i in 1 until 10) {
  15. println(i)
  16. }
  17. }
  18. fun test5(data :Int) {
  19. for (i in 1 .. data) {
  20. print("$i ")
  21. }
  22. }
  23. fun main(args : Array<String>) {
  24. // test1()
  25. // test2()
  26. // println(test3(1))
  27. // test4()
  28. test5(5)
  29. }

字符串

和Java一样,String也是不可变的
并且支持三个引号”””包裹起来的字符串,支持多行字符串

  1. fun main(args: Array<String>) {
  2. val text = """
  3. 多行字符串
  4. 多行字符串
  5. """
  6. println(text) // 输出有一些前置空格
  7. }

image.png
但是会有缩进边距
使用trimMargintrimIndent进行删除
image.png

条件控制

if表达式

  1. // 传统用法
  2. var max = a
  3. if (a < b) max = b
  4. // 使用 else
  5. var max: Int
  6. if (a > b) {
  7. max = a
  8. } else {
  9. max = b
  10. }
  11. // 作为表达式
  12. val max = if (a > b) a else b

在Kotlin中,没有三元表达式,但是可以将IF表达式的结果赋值给某一个变量

  1. val max = if (a > b) {
  2. print("Choose a")
  3. a
  4. } else {
  5. print("Choose b")
  6. b
  7. }

可以使用其来实现三元表达式的功能

  1. val c = if (condition) a else b

when表达式

when可以将它的参数和所有的分支条件进行顺序比较,直到某个分支满足条件
类似于其他语言中的switch

  1. when (x) {
  2. 1 -> print("x == 1")
  3. 2 -> print("x == 2")
  4. else -> { // 注意这个块
  5. print("x 不是 1 ,也不是 2")
  6. }
  7. }

在 when 中,else 同 switch 的 default。如果其他分支都不满足条件将会求值 else 分支。
如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:

  1. when (x) {
  2. 0, 1 -> print("x == 0 or x == 1")
  3. else -> print("otherwise")
  4. }

when 也可以结合区间使用

  1. when (x) {
  2. in 1..10 -> print("x is in the range")
  3. in validNumbers -> print("x is valid")
  4. !in 10..20 -> print("x is outside the range")
  5. else -> print("none of the above")
  6. }

用来检测数据的类型

  1. fun test7(data :Any) = when(data) {
  2. is String -> println("data is String")
  3. else -> println("data is not String")
  4. }

循环控制

for循环

for 循环可以对任何提供迭代器(iterator)的对象进行遍历,语法如下:

  1. for (item in collection) print(item)

如上所述,for 可以循环遍历任何提供了迭代器的对象。
如果你想要通过索引遍历一个数组或者一个 list,你可以这么做:

  1. fun test8() {
  2. var arr :Array<Int> = arrayOf(1,2,3,4,5)
  3. for (i in arr.indices) {
  4. print("${arr[i]} ")
  5. }
  6. }

或者使用库函数withIndex

  1. fun test8() {
  2. var arr :Array<Int> = arrayOf(1,2,3,4,5)
  3. for ((index,value) in arr.withIndex()) {
  4. println("index:$index value:$value")
  5. }
  6. }

while和do…while循环

和其他的语言没有什么不同。不赘述了

标签

在 Kotlin 中任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟 @ 符号,例如:abc@、fooBar@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。

  1. loop@ for (i in 1..100) {
  2. // ……
  3. }

从标签处返回

Kotlin 有函数字面量、局部函数和对象表达式。因此 Kotlin 的函数可以被嵌套。 标签限制的 return 允许我们从外层函数返回。 最重要的一个用途就是从 lambda 表达式中返回。回想一下我们这么写的时候:

  1. fun test9() {
  2. var arr :Array<Int> = arrayOf(1,2,3,4,5)
  3. arr.forEach {
  4. if(it == 1) return
  5. print("$it ")
  6. }
  7. println("test")
  8. }

实际执行的时候,forEach内部的return会直接退出test9这个函数
但是如果我们想要的是让他从表达式内部返回,那么就可以使用标签进行约束

  1. fun test9() {
  2. var arr :Array<Int> = arrayOf(1,2,3,4,5)
  3. arr.forEach test@{
  4. if(it == 1) return@test
  5. print("$it ")
  6. }
  7. println("test")
  8. }

这样就会从lambda表达式内部返回
image.png
也可以直接使用一个匿名函数来代替lambda表达式,匿名函数内部的return将从匿名函数中返回

  1. fun test9() {
  2. var arr :Array<Int> = arrayOf(1,2,3,4,5)
  3. arr.forEach(fun(item :Int) {
  4. if(item == 1) return
  5. print("$item ")
  6. })
  7. println("test")
  8. }