概述:
语言学习,以实用为主,少扯淡,开门见山
概述详见: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(): Byte
- ttoShort(): Short
- ttoInt(): Int
- ttoLong(): Long
- ttoFloat(): Float
- ttoDouble(): Double
- ttoChar(): 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
 4text = """ 
 for (c in "foo")
 print(c)
 """
- 去除前导空格:
 默认|用作边界前缀,但你可以选择其他字符并作为参数传入,比如trimMargin(">")。1 
 2
 3
 4
 5
 6text = """ 
 |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
 10- val 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
 4- fun hasPrefix(x: Any) = when(x) { 
 is String -> x.startsWith("prefix")
 else -> false
 }
- 取代 - if-else if链
 如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:- 1 
 2
 3
 4
 5- when { 
 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
 6- for (i in 1..3) { 
 println(i)
 }
 for (i in 6 downTo 0 step 2) {
 println(i)
 }
- 通过索引遍历一个数组或者一个 list - 1 
 2
 3- for ((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
 9- loop@ 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
 16- fun 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> { |