【Kotlin回顾】2.基础语法

语言: CN / TW / HK

theme: cyanosis


开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

1.变量

/* 关键字 变量类型 ↓ ↓ */ var price: Int = 100; /* ↑ ↑ 变量名 变量值 */

变量的关键字有valvar,前者是不可变变量相当于Java中的final变量,后者是可变变量对应Java的普通变量,大多数情况下应该尽可能的使用val,这样就遵守了Kotlin的【不可变特性】

在Kotlin中【;】可以不用写,同时Kotlin还支持【类型推导】例如

``` val num = 1

val str = "Hello World"

val isAudlt = false ```

上面的代码在后面并没有声明变量类型,这就是因为Kotlin的【类型推导】

2.基础类型

在Kotlin中一切都是对象,在Java中有原始类型(int)和包装类型(Integer),其中原始类型不是对象,只有包装类型才是,而在Kotlin中就规避了这个问题,类型是完全的面向对象的,它的类型如下表所示

| Type | Bit width | 备注 | | ------- | --------- | ------------------- | | Double | 64 | Kotlin没有double | | Float | 32 | Kotlin没有float | | Long | 64 | Kotlin没有long | | Int | 32 | Kotlin没有int/Integer | | Short | 16 | Kotlin没有short | | Char | 16 | Kotlin没有char | | Byte | 8 | Kotlin没有byte | | Boolean | 8 | Kotlin没有boolean |

Kotlin这么做的好处是可以从下面这段代码得知

val i:Double = 1.toDouble()

可以直接进行类型转换,在Java中因为原始类型不是一个对象因此无法实现这样便捷的操作

  • 空安全

Kotlin中既然一切都为对象那么就可以定义空的变量了,在Java中可以直接在变量后赋值【null】即可定义空变量,但是在Kotlin中不可以这么做,Kotlin中想定义一个空变量需要用如下方法:

``` val x : String = "" //不可为空的变量

val y : String? = null //可以为空的变量 ```

同时还需要注意的是不能把y的值赋给x,因为x是不可为空的

  • 数字类型

Kotlin中的数字类型与Java中的数字类型一致

val int = 1 //整数默认会被推导为“Int”类型; val long = 1234567L //Long类型,我们则需要使用“L”后缀; val double = 13.14 //小数默认会被推导为“Double”,我们不需要使用“D”后缀; val float = 13.14F //Float类型,我们需要使用“F”后缀; val hexadecimal = 0xAF //使用“0x”,来代表十六进制字面量; val binary = 0b01010101 //使用“0b”,来代表二进制字面量。

但是,对于数字类型的转换,Kotlin 与 Java 的转换行为是不一样的。Java 可以隐式转换数字类型,而 Kotlin 更推崇显式转换。 在Kotlin中数字类型的转换如下所示:

val i : Int = 0 val j : Long = i.toLong()

类似的函数还有 toByte()、toShort()、toInt()、toLong()、toFloat()、toDouble()、toChar() 等等

  • 布尔类型

布尔类型与Java是一样的,只有true和false两个值,定义如下:

val x = false val y = true

  • 字符:Char

字符的定义跟Java类似只能代表单个字符,都是用【' '】定义的

val x = 'A'

  • 字符串:String

Kotlin的字符串定义用【" "】和【""" """】 ,前者就是普通的字符串定义,后者是在定义时是什么样打印出的日志就是什么样

``` val x = "Hello Kotlin” //输出日志:Hello Kotlin

val y = """ Hello World 今天是2022年 """ //输出日志: //Hello World //今天是2022年
```

  • 数组

在Kotlin中数组的定义使用arrayOf(),在括号中可以添加数组的元素,同时因为Kotlin具有类型推导的特性,因此定义数组的时候是不需要添加数组类型的,代码如下:

val arrayInt = arrayOf(1, 2, 3) val arrayString = arrayOf("apple", "pear")

在Java中我们常常需要操作数组,例如获取数组的长度需要length()方法,取出数组的元素需要arrayInt[index]跟集合是不一样的,但是在Kotlin中操作数组和操作集合的方法基本是一样的:

val size = arrayInt.size //获取数组长度 val item = arrayInt[0] //获取arrayInt的第【0】个元素

以上就是Kotlin的基础类型的内容,这里还要提一个Kotlin的特性——字符串拼接 ,代码如下:

``` val a = "Hello" println("$a Kotlin") //输出日志:Hello Kotlin

val arrayString = arrayOf("apple", "pear") println("arrayString数组的第【0】个元素的值是:${arrayString[0]}") //输出日志:arrayString数组的第【0】个元素的值是:apple ```

可以看到这个比Java真的是方便不少,具体用法就是如果只是单纯的拼接只需要加上【$】后面再跟上变量名或者字符串即可,如果需要从某个数组或者集合或者对象中取值就需要在加上【$】后再加上【{}】,在花括号中写入取值代码即可。

3.函数

  • 函数声明

Kotlin声明一个函数的代码如下:

/* 关键字 函数名 参数类型 返回值类型 ↓ ↓ ↓ ↓ */ fun helloFunction(name: String): String { return "Hello $name !" }/* ↑ 花括号内为:函数体 */

    • 使用了 fun 关键字来定义函数;
    • 函数名称,使用的是驼峰命名法(特殊函数除外);
    • 函数参数,是以 (name: String) 这样的形式传递的,这代表了参数类型为 String 类型;
    • 返回值类型,紧跟在参数的后面;
    • 最后是花括号内的函数体,它代表了整个函数的逻辑。

上面的代码中函数体只有一行代码因此可以这么写

fun helloFunction(name: String): String = "Hello $name !"

这样就省去了return和花括号,同时因为Kotlin具有类型推导的特性还可进一步优化代码:

fun helloFunction(name: String) = "Hello $name !"

这种方式的写法被称单一表达式函数

  • 函数调用

函数调用的调用跟Java类似,也是helloFunction("Kotlin")的方法,但是如果存在多个参数的情况下就会出现如下情况

``` fun createStudent( name: String, age: Int, gradle: String, teacher: String, subjects: String, score: Int, ranking: Int ) { //.. }

createStudent("张三", 12, "六年级", "李四", "数学", 100, 1) ```

调用传参的时候不知道参数具体代表的是哪个字段,这个在新版的IDE上会有提示,但是该记录咱还是要记录一下的

kotlin的特性其实可以这么写:

fun main() { createStudent( name = "张三", age = 12, gradle = "六年级", teacher = "李四", subjects = "数学", score = 100, ranking = 1 ) }

Kotlin的函数调用还有一个特性就是默认参数,代码如下

``` fun createStudent( name: String, age: Int, gradle: String = "六年级", teacher: String = "李四", subjects: String = "数学", score: Int, ranking: Int ) { //.. }

fun main() { createStudent( name = "张三", age = 12, score = 100, ranking = 1 ) } ```

在函数中定义的参数有了默认值那么我们在调用这个函数时就可以不传。

4.流程控制

Kotlin当中的流程控制主要有ifwhenwhile和for

  • if

在Java中使用if一般都这么写

``` val i = 1 if (i > 0) { print("Big") } else { print("Small") }

输出结果: Big ```

在Kotlin中也可以这么写(这是一句废话),但是它可以作为表达式来使用时就可以这么写,输出结果是一致的

val i = 1 val message = if (i > 0) "Big" else "Small"

另外,Kotlin中有【可空类型】和【不可空类型】,一般情况下我们都会遇到可空的变量,这就需要判断是否为空,那么我们就可以这么写

``` fun getLength(text: String?): Int { return if (text != null) text.length else 0 }

//优化后 fun getLength(text: String?): Int { return text?.length ?: 0 } ```

这种简化的写法叫做 Elvis 表达式。

  • when

通常情况下当if/else大于两个分支的时候就要用到when了,它与switch case的用法类似,但是它更好用因为when还可以作为表达式使用给变量赋值

``` val i: Int = 1

when(i) { 1 -> print("男") 2 -> print("女") else -> print("未知") }

//输出结果:男

val i: Int = 1

val i = 1 val gender = when (i) { 1 -> "男" 2 -> "女" else -> "未知" } print(gender)

//输出结果:男 ```

switch case的区别是when的结尾必须要有else否则就会报错。

  • 循环迭代:while

Kotlin的while的用法与Java类似没什么太大区别

``` var i = 0 while (i <= 2) { println(i) i++ }

var j = 0 do { println(j) j++ } while (j <= 2)

输出结果: 0 1 2 0 1 2 ```

  • 迭代循环: for

for循环就跟Java有很大的区别了

首先我们先遍历一个数组

``` val arrayInt = (1, 2, 3) for(i in arratInt){ println(i) }

//依次输出:1、2、3 ```

遍历一个区间

``` val oneTwoThree = 1..3 //代表[1, 3]

for(i in oneTwoThree){ println(i) } //依次输出:1、2、3 ```

逆序迭代一个区间

``` for (i in 6 downTo 0 step 2) { println(i) }

输出结果: 6 4 2 0 ```

上面这行代码的意思是逆序从6到0每隔两个数迭代

这里要注意的是逆序不能用区间【6..0】来定义,这样是不被Kotlin允许的。

5.思考题

虽然 Kotlin 在语法层面摒弃了“原始类型”,但有时候为了性能考虑,我们确实需要用“原始类型”。这时候我们应该怎么办?

  • 如果这个变量在定义的时候存在可能为空的情况就会被编译成Java的包装类型,如果这个变量不可能为空那它被编译后就是Java的原始类型。