2.1 Kotlin基础语法
Kotlin 文件以 .kt 为后缀。
包声明
代码文件的开头一般为包的声明:
|
|
kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。
以上例中 test() 的全名是 com.shijc.main.test、Shijiacheng 的全名是 com.shijc.main.Shijiacheng。
如果没有指定包,默认为 default 包。
默认导入
有多个包会默认导入到每个 Kotlin 文件中:
- kotlin.*
- kotlin.annotation.*
- kotlin.collections.*
- kotlin.comparisons.*
- kotlin.io.*
- kotlin.ranges.*
- kotlin.sequences.*
- kotlin.text.*
函数定义
函数定义使用关键字 fun,参数格式为:参数 : 类型
|
|
表达式作为函数体,返回类型自动推断:
|
|
无返回值的函数(类似Java中的void):
|
|
可变长参数函数
函数的变长参数可以用 vararg 关键字进行标识:
|
|
lambda(匿名函数)
lambda表达式使用实例:
|
|
定义常量与变量
可变变量定义:var 关键字
|
|
不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)
|
|
常量与变量都可以没有初始化值,但是在引用前必须初始化
编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。
|
|
注释
Kotlin 支持单行和多行注释,实例如下:
|
|
与 Java 不同, Kotlin 中的块注释允许嵌套。
字符串模板
$ 表示一个变量名或者变量值
$varName 表示变量值
${varName.fun()} 表示变量的方法返回值:
|
|
NULL检查机制
Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理
|
|
当一个引用可能为 null 值时, 对应的类型声明必须明确地标记为可为 null。
当 str 中的字符串内容不是一个整数时, 返回 null:
|
|
以下实例演示如何使用一个返回值可为 null 的函数:
|
|
类型检测及自动类型转换
我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字)。
|
|
或者
|
|
甚至还可以
|
|
区间
区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。
区间是为任何可比较类型定义的,但对于整型原生类型,它有一个优化的实现。以下是使用区间的一些示例:
|
|
实例测试
|
|
输出结果:
|
|
2.2 Kotlin 基本数据类型
Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等。不同于Java的是,字符不属于数值类型,是一个独立的数据类型。
类型 | 位宽度 |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
字面常量
下面是所有类型的字面常量:
- 十进制:123
- 长整型以大写的 L 结尾:123L
- 16 进制以 0x 开头:0x0F
- 2 进制以 0b 开头:0b00001011
- 注意:8进制不支持
Kotlin 同时也支持传统符号表示的浮点数值:
- Doubles 默认写法:
123.5
,123.5e10
- Floats 使用 f 或者 F 后缀:
123.5f
你可以使用下划线使数字常量更易读:
|
|
比较两个数字
Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。数字类型也一样,所有在比较两个数字的时候,就有比较数据大小和比较两个对象是否相同的区别了。
在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。
|
|
类型转换
由于不同的表示方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型。 这意味着在不进行显式转换的情况下我们不能把 Byte 型值赋给一个 Int 变量。
|
|
我们可以代用其toInt()方法。
|
|
每种数据类型都有下面的这些方法,可以转化为其它的类型:
|
|
有些情况下也是可以使用自动类型转化的,前提是可以根据上下文环境推断出正确的数据类型而且数学操作符会做相应的重载。例如下面是正确的:
|
|
位操作符
对于Int和Long类型,还有一系列的位操作符可以使用,分别是:
|
|
字符
和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号 ‘ 包含起来的。比如普通字符 ‘0’,’a’。
|
|
字符字面值用单引号括起来: ‘1’。 特殊字符可以用反斜杠转义。 支持这几个转义序列:\t、 \b、\n、\r、\’、\”、\ 和 \$。 编码其他字符要用 Unicode 转义序列语法:’\uFF00’。
我们可以显式把字符转换为 Int 数字:
|
|
当需要可空引用时,像数字、字符会被装箱。装箱操作不会保留同一性。
布尔
布尔用 Boolean 类型表示,它有两个值:true 和 false。
若需要可空引用布尔会被装箱。
内置的布尔运算有:
|
|
数组
数组用类 Array 实现,并且还有一个 size 属性及 get 和 set 方法,由于使用 [] 重载了 get 和 set 方法,所以我们可以通过下标很方便的获取或者设置数组对应位置的值。
数组的创建两种方式:一种是使用函数arrayOf();另外一种是使用工厂函数。如下所示,我们分别是两种方式创建了两个数组:
|
|
如上所述,[] 运算符代表调用成员函数 get() 和 set()。
注意: 与 Java 不同的是,Kotlin 中数组是不型变的(invariant)。
除了类Array,还有ByteArray, ShortArray, IntArray,用来表示各个类型的数组,省去了装箱操作,因此效率更高,其用法同Array一样:
|
|
字符串
和 Java 一样,String 是可不变的。方括号 [] 语法可以很方便的获取字符串中的某个字符,也可以通过 for 循环来遍历:
|
|
Kotlin 支持三个引号 “”” 扩起来的字符串,支持多行字符串,比如:
|
|
String 可以通过 trimMargin() 方法来删除多余的空白。
2.3 Kotlin 条件控制
IF 表达式
一个 if 语句包含一个布尔表达式和一条或多条语句。
|
|
我们也可以把 IF 表达式的结果赋值给一个变量。
|
|
这也说明我也不需要像Java那种有一个三元操作符,因为我们可以使用它来简单实现:
|
|
实例
|
|
输出结果为:
|
|
使用区间
使用 in 运算符来检测某个数字是否在指定区间内,区间格式为 x..y :
实例
|
|
输出结果为:
|
|
When 表达式
when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。
when 既可以被当做表达式使用也可以被当做语句使用。如果它被当做表达式,符合条件的分支的值就是整个表达式的值,如果当做语句使用, 则忽略个别分支的值。
when 类似其他语言的 switch 操作符。其最简单的形式如下:
|
|
在 when 中,else 同 switch 的 default。如果其他分支都不满足条件将会求值 else 分支。
如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:
|
|
我们也可以检测一个值在(in)或者不在(!in)一个区间或者集合中:
|
|
另一种可能性是检测一个值是(is)或者不是(!is)一个特定类型的值。注意: 由于智能转换,你可以访问该类型的方法和属性而无需 任何额外的检测。
|
|
when 也可以用来取代 if-else if链。 如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:
|
|
实例
|
|
输出结果:
|
|
when 中使用 in 运算符来判断集合内是否包含某实例:
|
|
输出结果:
|
|
2.4 Kotlin 循环控制
For 循环
for 循环可以对任何提供迭代器(iterator)的对象进行遍历,语法如下:
|
|
循环体可以是一个代码块:
|
|
如上所述,for 可以循环遍历任何提供了迭代器的对象。
如果你想要通过索引遍历一个数组或者一个 list,你可以这么做:
|
|
注意这种”在区间上遍历”会编译成优化的实现而不会创建额外对象。
或者你可以用库函数 withIndex:
|
|
实例
对集合进行迭代:
|
|
输出结果:
|
|
while 与 do…while 循环
while是最基本的循环,它的结构为:
|
|
do…while 循环 对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
|
|
实例
|
|
输出结果:
|
|
返回和跳转
Kotlin 有三种结构化跳转表达式:
- return。默认从最直接包围它的函数或者匿名函数返回。
- break。终止最直接包围它的循环。
- continue。继续下一次最直接包围它的循环。
在循环中 Kotlin 支持传统的 break 和 continue 操作符。
|
|
输出结果:
|
|
Break 和 Continue 标签
在 Kotlin 中任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟 @ 符号,例如:abc@、fooBar@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。
|
|
现在,我们可以用标签限制 break 或者continue:
|
|
标签限制的 break 跳转到刚好位于该标签指定的循环后面的执行点。 continue 继续标签指定的循环的下一次迭代。
标签处返回
Kotlin 有函数字面量、局部函数和对象表达式。因此 Kotlin 的函数可以被嵌套。 标签限制的 return 允许我们从外层函数返回。 最重要的一个用途就是从 lambda 表达式中返回。回想一下我们这么写的时候:
|
|
这个 return 表达式从最直接包围它的函数即 foo 中返回。 (注意,这种非局部的返回只支持传给内联函数的 lambda 表达式。) 如果我们需要从 lambda 表达式中返回,我们必须给它加标签并用以限制 return。
|
|
现在,它只会从 lambda 表达式中返回。通常情况下使用隐式标签更方便。 该标签与接受该 lambda 的函数同名。
|
|
或者,我们用一个匿名函数替代 lambda 表达式。 匿名函数内部的 return 语句将从该匿名函数自身返回
|
|
当要返一个回值的时候,解析器优先选用标签限制的 return,即
|
|
意为”从标签 @a 返回 1”,而不是”返回一个标签标注的表达式 (@a 1)”。