Kotlin 笔记 2 :基础,数据类型和基本语法

数据类型

Kotlin 的基本数据类型和 Java 差不多,但是没有 Java 那种类型自动转换的功能(譬如 int 可以自动转换为 long)

用它们来表示数字:

  • Double
  • Float
  • Long
  • Int
  • Short
  • Byte

对于浮点数,默认是 Double 类型的,Float 类型使用 Ff 标识,这点倒是和 Java 一样。

更加方便一点的是,Kotlin 中可以使用下划线来使得数据更加易读:

val oneMillion = 1_000_000
不用一位一位的数了,这点还挺方便的。
  • 用它来标识字符:Char
    和 Java 不同的是,Kotlin 中的字符不能转化为数字,在 Java 中是可以这样做的:

    char i = 25106;
    System.out.println(i);

而在 Kotlin 中却不可以。

如果我们要使用数字字面来作为字符,需要使用单引号`'` 将其括起来,例如 `'0'`,可以使用 `'0'.toInt()` 方法将其转为 Int 值。
  • 用它来标识布尔值:Boolean

    和 Java 一样,Kotlin 内置了短路与 &&短路或 ||逻辑非 ! 布尔运算。

  • 用它来标识数组:Array
    创建数组的方式有以下几种:

    • 使用 arrayOf() 函数

      var arr = arrayOf('x','y','z')
      对应 Java 的 char[] arr = new char[] {'x','y','z'};
    • 使用 Array 的构造函数

      val arr = Array(3) { i -> (i * 2) }
      这个方法是创建一个有三个元素的数组,第 i 个元素的值为 i*2
    • 使用函数 arrayOfNulls() 来创建指定大小的元素为空的数组

      //创建一个大小为10 用来存储 Int 类型,但此时数据为空的数组
      val arrayOfNulls = arrayOfNulls<Int>(10)
    • Kotlin 同样也提供了一系列的专门用来表示原声类型数组的类:ByteArrayShortArrayIntArray,他们和 Array 并不是继承关系。
  • 用它来标识字符串:String
    和 Java 一样,Kotlin 中的字符串也是不可变的。Java 中使用 charAt 函数来获取字符串中的字符,在 Kotlin 中可以直接通过 [下标] 的方法来完成这个操作:

        var name:String = "lixyz"
        println(name[2])//输出结果为x

对于拼接字符串,Kotlin 和 Java 不同的是,使用 + 来拼接字符串,表达式的开始必须是字符串才可以:

 var str:String = "lixyz" + 100   //正确的
 var str:String = 100 + "lixyz" //错误的
就跟 Java 一样,Kotlin 推荐使用原始字符串,如果需要拼接的话,最好使用 `模板` 来进行拼接,我估摸着原因跟 Java 推荐使用 StringBuilder 和 StringBuffer 一样,模板表达式以 `&` 开头,后面跟对象名称,例如:
val name:String = "lixyz"
println("name = $name") // name = lixyz

或者用花括号括起来的任意表达式:
println("age = ${10+10}") // 输出 age = 20

如果你需要在原始字符串中表示字面值 `$` 字符(它不支持反斜杠转义),你可以用下列语法:
val price = """
${'$'}9.99
"""

至于其他的,和 Java 语言差不多了,同样也支持转义符。

包和导包

Kotlin 源文件不需要相匹配的目录和包,源文件可以放在任意目录下。在 Java 语言当中,我们的 .java 文件必须放在其 package 表示的目录下,否则会出错,而 Kotlin 则没有这个限制。

如果没有指定包名,那默认为 default 包。

系统会默认导入一下包到 Kotlin 文件中:

  • kotlin.*
  • kotlin.annotation.*
  • kotlin.collections.*
  • kotlin.comparisons.*
  • kotlin.io.*
  • kotlin.ranges.*
  • kotlin.sequences.*
  • kotlin.text.*

和 Java 语言不通的是,Kotlin 不单单可以导入一个类,还可以单独导入一个方法:

import com.lixyz.kotlin.monthTest

fun main() {
    monthTest("哈哈")
}

控制流

if...else

在 Kotlin 中,if 不单单是一个关键字,它还是一个表达式,它可以作为返回值:

fun main() {
    print(max(10, 20))
}

fun max(a: Int, b: Int): Int {
    val result = if (a > b) a else b
    return result
}

有点儿类似于 Java 中的三目运算符。

when

when 的用法有点儿类似于 Java 中的 switch,它的参数依次和所有的分支做比较,直到其中一个分支满足条件,当所有分支都不满足,则执行 else 分支(类似于 Java 中的 default 分支),但是它的功能又要比 Java 中的 switch 强大,写法也略有不同:

//普通用法
    var flag = 1
    when (flag) {
        1 -> println("Flag is 1")
        2 -> println("Flag is 2")
        3 -> println("Flag is 3")
        4 -> println("Flag is 4")
        else -> println("error")
    }
//分支合并
    var name = "西瓜"
    when (name) {
        "西瓜", "橘子" -> println("是水果")
        "小麦", "稻子" -> println("是粮食")
        else -> println("既不是水果,又不是粮食")
    }
//使用表达式做分支(-=注意,这里的 when 没有参数=-)
    fun main() {
        var number = 10
        when {
            isOdd(number) -> print("基数")
            isEven(number) -> print("偶数")
        }
    }
    
    fun isOdd(number: Int): Boolean {
        return number % 2 != 0
    }
    
    fun isEven(number: Int): Boolean {
        return number % 2 == 0
    }
//检测是否在区间内,或者是否在集合内
    fun main() {
        var validNumbers = Array(3) { i -> (i * 2) }
        var x = 2
        when (x) {
            in validNumbers -> print("x is valid")
            in 1..10 -> print("x is in the range")
            !in 10..20 -> print("x is outside the range")
            else -> print("none of the above")
        }
    }

for 循环

Kotlin 中的 for 循环和 Java 中的 foreach 挺像:

    //正常遍历
    var validNumbers = Array(3) { i -> (i * 2) }
    for (i in validNumbers) {
        println(i)
    }
    //遍历区间,输出 :1   2   3   
    for (i in 1..3) {
        print("$i   ")
    }
    //降序遍历,跳过 2 个,输出:6   4   2   0   
    for (i in 6 downTo 0 step 2) {
        print("$i   ")
    }    
    //通过下标遍历一个数组,输出:024
    var number = Array(3) { i -> (i * 2) }
    for (i in number.indices) {
        print(number[i])
    }    

while 和 do...while

和 Java 基本没啥区别,不赘述。

返回和跳转

和 Java 一样,Kotlin 中也有三种转跳表达式:

  • return。默认从最直接包围它的函数或者匿名函数返回。
  • break。终止最直接包围它的循环。
  • continue。继续下一次最直接包围它的循环。

其常规用法也和 Java 一样。

在 Kotlin 中,任何表达式都可以为其添加一个标签,格式为标识符后跟 @,要为一个表达式添加标签,只需要在表达式前面添加 标签名@即可。

有了标签,在 Kotlin 中 break 和 continue 就可以使用标签来限制跳转了:

    test@for (j in 1..5) {
        for (i in 1..5) {
            if (i == 3) {
                break@test
            }
            println("$j               $i")
        }
    }
    
//输出结果为:
1               1
1               2

在 Java 当中,当我们在一个方法内执行了 return,会直接从这个方法中返回,在 Kotlin 里,配合标签,可以让 return 更加的灵活,单独读起来可能有些难以理解,配合代码来看,平时我们会这样写:

    var arr = listOf(1, 2, 3, 4, 5)
    arr.forEach() {
        if (it == 3) {
            return
        }
        print(it)
    }
    //输出结果为 12

但是我们加上一个标签

    var arr = listOf(1, 2, 3, 4, 5)
    arr.forEach() test@{
        if (it == 3) {
            return@test
        }
        print(it)
    }
    //输出结果为  1245

通过上面的例子可以看出,从标签处 return,只会返回到 foreach 表达式中返回,事实上,在 Kotlin 中每个方法的方法名都是一个标签,所以我们可以将声明标签的动作省略:

    var arr = listOf(1, 2, 3, 4, 5)
    arr.forEach() {
        if (it == 3) {
            return@forEach
        }
        print(it)
    }
    //输出结果为  1245

上面两个例子的作用是相同的,可以看到,它只是返回到了 lambda 表达式处,然后继续执行 it == 4 之后的循环