概述:
语言学习,以实用为主,少扯淡,开门见山
概述详见:https://www.kotlincn.net/docs/reference/server-overview.html
一、定义与概念:
1、程序入口点:
kotlin 应用程序的入口点事main
函数:
1 | fun main() { |
2、变量:
2.1、不可变变量:
关键字:val
只能为其赋值一次,相当于Java 中的 final
1 | val a: Int = 1 // 立即赋值 |
2.1、可变变量:
关键字:var
可重新赋值。
1 | var x = 5 // 自动推断出 `Int` 类型 |
3、注释:
与大多数现代语言一样,Kotlin 支持单行(或行末)与多行(块)注释。
1 | // 这是一个行注释 |
4、字符串模板:
通过在字符串中使用$
符号来引用变量。
1 | var a = 1 |
二、基本类型:
1、数字
1.1、整型
tip:所有以未超出Int
最大值的整型值初始化的变量都会推断为Int
类型。如果初始值超过了其最大值,那么推断为Long
,若显示指定Long
型值,则请在该值后追加l
或 L
。
1.2、浮点型
tip:对于以小数初始化的变量,编译器会推断为Double
类型,如需将一个值显示指定为Float
类型,需添加 f
或 F
后缀。若这样的值包含多于6 ~7 位十进制数,那么会将其舍入。
注:
- 根据 IEEE 754 标准, 两种浮点类型的十进制位数(即可以存储多少位十进制数)不同。
Float
反映了 IEEE 754 单精度,而Double
提供了双精度。 - kotlin中的数字没有隐式拓宽转换(可使用显示转换),例:
1
2
3
4
5
6
7val i = 1
val d = 1.1
val f = 1.1f
printDouble(d)
// printDouble(i) // 错误:类型不匹配
// printDouble(f) // 错误:类型不匹配
1.3、显示转换:
1 | val b: Byte = 1 |
每个数字类型支持如下的转换:
toByte()
: BytettoShort()
: ShortttoInt()
: IntttoLong()
: LongttoFloat()
: FloatttoDouble()
: DoublettoChar()
: Char
运算转换:
1 | val l = 1L + 3 // Long + Int => Long |
1.4、字面常量:
整数:
- 十进制:
123
。Long类型:123L
- 十六进制:
0x0F
- 二进制:
0b00001011
- 八进制:不支持
浮点数:
- 默认double:
123.5
、123.5e10
- Float用
f
或F
标记:123.5f
2、字符 Char
表示:
- 字符字面值用单引号括起来,
'1'
- 转义字符::
\t
、\b
、\n
、\r
、\'
、\"
、\\
与\$
- 编码其他字符要用 Unicode 转义序列语法:
'\uFF00'
3、布尔 Boolean
4、数组 Array
4.1、创建数组:
1 | val testArr = arrayOf(1, 2, 3, 4, 5) //[1, 2, 3, 4, 5] |
4.2、原生类型数组:
如:ByteArray
、ShortArray
、IntArray
注: 与Array
没有继承关系。
1 | val x: IntArray = intArrayOf(1, 2, 3) //[1, 2, 3] |
4.3、属性函数
1 | fun main(args: Array<String>) { |
5、字符串 String
5.1、表示:
- 用String 类型表示,不可变
- 使用
+
操作符连接字符串 - 原始字符串:用三个双引号表示:
"""
1
2
3
4""" text =
for (c in "foo")
print(c)
"""
- 去除前导空格:
默认|
用作边界前缀,但你可以选择其他字符并作为参数传入,比如trimMargin(">")
。1
2
3
4
5
6""" text =
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
5.2、字符串模板:
- 表示:
$
1
2
3
4
5
6
7//变量
val i = 10
println("i = $i") // 输出“i = 10”
//表达式
val s = "abc"
println("$s.length is ${s.length}") // 输出“abc.length is 3”
原始字符串与转义字符串内部都支持模板。 如果你需要在原始字符串中表示字面值 $ 字符(它不支持反斜杠转义)
1 | """ price = |
5.3、属性:
1 | fun foo() { |
5.4、函数:
三、运算符
- 算术运算符
- 关系运算符
- 赋值运算符
- 一元运算符
- 按位运算
- 逻辑运算符
1、算术运算符
2、关系运算符
3、赋值运算符
4、一元运算符
5、逻辑运算符
6、按位运算
1 | fun main(args: Array<String>){ |
四、包与导入
- 包:
package
- 导入:
import
详见:https://www.kotlincn.net/docs/reference/packages.html
五、控制流程
1、if
在 Kotlin 中,if是一个表达式,即它会返回一个值。 因此就不需要三元运算符(条件 ? 然后 : 否则),因为普通的 if 就能胜任这个角色。
1 | // 传统用法 |
2、when
when 取代了类 C 语言的 switch 操作符。
when 既可以被当做表达式使用,也可以被当做语句使用
- 作为表达式:符合条件的分支的值,就是整个表达式的值。必须有
else
分支。(枚举enum类和密封sealed类子类型 可不用) - 作为语句:忽略个别分支的值。
2.1、示例
变量赋值:
1
2
3
4
5
6
7
8
9
10val x = 10;
val s = "5"
val a =
when(x) {
parseInt(s) -> print("s encodes x")
0, 1 -> print("x == 0 or x == 1")
in 6..8 -> print("x is in the range")
else -> print("otherwise")
}函数表达式:
1
2
3
4fun hasPrefix(x: Any) = when(x) {
is String -> x.startsWith("prefix")
else -> false
}取代
if-else if
链
如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:1
2
3
4
5when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
3、for
for 循环可以对任何提供迭代器(iterator)的对象进行遍历,这相当于像 C# 这样的语言中的 foreach
循环。
for 可以循环遍历任何提供了迭代器的对象。即:
- 有一个成员函数或者扩展函数 iterator(),它的返回类型
- 有一个成员函数或者扩展函数 next(),并且
- 有一个成员函数或者扩展函数 hasNext() 返回 Boolean。
这三个函数都需要标记为 operator。
示例:
对区间或者数组的 for 循环会被编译为并不创建迭代器的基于索引的循环。
1
2
3
4
5
6for (i in 1..3) {
println(i)
}
for (i in 6 downTo 0 step 2) {
println(i)
}通过索引遍历一个数组或者一个 list
1
2
3for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
4、while
while
与 do..while
照常使用
1 | while (x > 0) { |
5、返回、跳跃
Kotlin中有三个跳跃表达式。 这些跳转表达式用于控制程序执行的流程。 这些跳跃语句是:
- break:终止最直接包围它的循环。
- continue:继续下一次最直接包围它的循环。
- return:默认从最直接包围它的函数或者匿名函数返回。
1 | val s = person.name ?: return |
5.1、标签
break、continue
在 Kotlin 中任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟@
符号,例如:abc@
、fooBar@
都是有效的标签(参见语法)。 要为一个表达式加标签,我们只要在其前加标签即可。1
2
3
4
5
6
7
8
9loop@ for (i in 1..100) {
for (j in 1..100) {
if (j==50) {
break@loop
} else if(j==60) {
continue@loop
}
}
}return
没有标签则结束(foo)函数
通常情况下使用隐式标签更方便。 该标签与接受该 lambda 的函数同名。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // 局部返回到该 lambda 表达式的调用者,即 forEach 循环
print(it)
}
print(" done with explicit label")
}
//匿名标签,同函数名
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // 局部返回到该 lambda 表达式的调用者,即 forEach 循环
print(it)
}
print(" done with implicit label")
}
当要返一个回值的时候,解析器优先选用标签限制的 return,即return@a 1
,
意为“从标签 @a 返回 1”,而不是“返回一个标签标注的表达式 (@a 1)”。
如下:
1 | fun foo(ints: List<Int>): List<String> { |