本笔记是基于李刚的《Kotlin讲义》整理出来的,若有错误欢迎指出。
一、基础语法
1、概述
1.1 注释
单行注释: //
多行注释:/*...*/
文档注释:/**...*/
1.2 变量
可以使用val|var variableName[: type] [= initData]
声明变量,其中val声明的变量是值不可变的。==必须指定变量类型或初始值==。
var a = 11 //指定初始值
var b: Int //指定变量类型
var c: Int = 1;//指定初始值和变量类型
val name = 'yaohuix' //指定常量,值不可变
Kotlin并不要求语句以分号结尾
2、类型
2.1 整型
支持Byte、Short、Int、Long四种整型。与Java不同的是,Kotlin的整型不是基本类型,而是引用类型(类似Java的包装类),继承自Number类。另外,Kotlin是null安全的语言,所以Byte、Short、Int、Long型变量都不能接受null值,要存储null值,应该使用Byte?、Short?、Int?、Long?类型。
普通类型的整型变量会被映射成Java的基本类型,带"?"的整型变量会被映射成基本类型的包装类
Kotlin允许已有的类型后添加"?"来支持赋予null值
var p1: Int = 11
var p2: Int = 11
println(p1 === p2) //基本类型的比较,输出true
var p3: Int? = 11
var p4: Int? = 11
println(p3 === p4) //引用类型的比较,输出false
支持的字面值有3种:
- 二进制:0b或0B开头
- 十进制:最普通的整数值
- 十六进制:0x或0X开头
val p1 = 1_000_000 //允许增加下划线作为分隔符
var p2 = 0010000 //允许前面添加额外的零
Kotlin不支持八进制
2.2 浮点数
支持Float和Double两种类型。Kotlin还额外提供了3个特殊的浮点型数值:正无穷大、负无穷大和非数。正数除以0.0得到正无穷大,负数除以0.0得到负无穷大,0.0除以0.0或负数开方得到非数。
2.3 字符型
有三种表示形式:
- 'A'
- '\n'
- '\uXXXX'
Kotlin的Char型只是字符型,不能直接当整型使用
2.4 字符串
与java不同的是,Kotlin允许s[i]来访问索引处的字符,也支持三引号表示的原始字符串,允许使用${}
在字符串中嵌入变量或者表达式
var str = "Hello World"
println(str[1]) //e
//原始字符串可以包含换行和任意文本
//使用竖线(|)作为边界符,竖线之前的内容将全部去掉
var text = """
|人间清暑殿
|天上广寒宫
"""
//字符串模板
var price = 12
var bookPrice = "书本的价格是${price*5}元"
3、null安全
可空类型:比如 Int?
非空类型:比如 Int
Kotlin对可空类型做了限制,若不加任何处理,==可空类型不允许直接调用方法,访问属性==。
var aStr: String = "Hello"
var bStr: String? = "Hello"
aStr = null //错误
bStr = null //正确
println(aStr.length) //编译通过
println(bStr.length) //编译失败
如何调用可空类型?有以下两种方式:
//先判断后使用
var b: String? = "yao"
var len = if (b != null) b.length else -1
//安全调用
println(b?.length)
需要注意的是,对于可空的Boolean类型而言,它可接受3个值:true、false或null。因此对Boolean?进行判断时,要显示的与true、false值进行比较
var b: Boolean? = null
//以下语句将报错
if(b){}
//正确的做法
if(b == true){}
安全调用
?.
var b: String? = "Hello"
println(b?.length)
Elvis运算
?:
其实就是if else的简化写法,它的含义是左边的表达式不为null,返回左边的表达式,否则返回右边的表达式
var b: String = "Hello"
var len = b?.length ?: -1
强制调用
!!.
可能引发空指针
var b: String = "Hello"
var len = b!!.length
4、类型别名
类似C语言的typedef功能,可以为已有的类型指定另一个可读性更强的名字。语法格式为:typealias 类型别名 = 已有类型
typealias NodeSet = Set //指定别名
var set: NodeSet //声明变量
很多时候,我们可以定义别名来为内部类取一个更短的名字
class A{
inner class Inner
}
typealias AInner = A.Inner
var a: AInner
5、运算符
5.1 支持的运算符
Kotlin的运算符都是以方法的形式来实现的,也就是说只要我们为某类型实现了特定的方法,就可以对该类型对象用运算符进行"运算"。Kotlin不支持Java的三目运算符,使用了if else进行代替。
单目前缀运算符
+、-、!
运算符 | 对应方法 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
自加、自减运算符
++、--
运算符 | 对应方法 |
---|---|
a++ | a.inc() |
a-- | a.dec() |
双目算术运算符
+、-、*、/、%、..
运算符 | 对应方法 |
---|---|
a+b | a.plus(b) |
a-b | a.minus(b) |
a*b | a.times(b) |
a/b | a.div(b) |
a%b | a.rem(b) |
a..b | a.rangeTo(b) |
in和!in运算符
String类型就实现了contains()方法
var str = "hello world"
println("hello" in str)
运算符 | 对应方法 |
---|---|
a in b | b.contains(a) |
a !in b | !b.minus(a) |
索引访问运算符
运算符 | 对应方法 |
---|---|
a[i] | a.get(i) |
a[i,j] | a.get(i,j) |
a[i]=b | a.set(i,b) |
a[i,j]=b | a.set(i,j,b) |
调用运算符
运算符 | 对应方法 |
---|---|
a() | a.invoke() |
a(b) | a.invoke(b) |
广义赋值运算符
运算符 | 对应方法 |
---|---|
a+=b | a.plusAssgin(b) |
a-=b | a.minusAssign(b) |
a*=b | a.timesAssign(b) |
a/=b | a.divAssign(b) |
a%=b | a.remAssign(b) |
这种广义运算符有点特殊,比如a+=b,实际上相当于a=a+b,因此在程序中进行a+=b运算时,并不需要一定有plusAssign方法。
编译器会先判断是否存在plusAssign方法,如果存在,则必须plus方法不存在且plusAssign方法没有返回值,否则编译报错。然后执行plusAssign方法。否则执行a=a+b。
相等与不等运算符
== 、!=
运算符 | 对应方法 |
---|---|
a==b | a?.equals(b)?:(b===null) |
a!=b | !(a?.equals(b)?:(b===null)) |
Java中的"=="和"!="则由Kotlin中的"==="和"!=="代替
比较运算符
运算符 | 对应方法 |
---|---|
a>b | a.compareTo(b)>0 |
a | a.compareTo(b)<0 |
a>=b | a.compareTo(b)>=0 |
a<=b | a.compareTo(b)<=0 |
5.2 区间运算符 重要
可以理解为List
含义 | 运算符 |
---|---|
闭区间 | 2..5 |
半开区间 | 2 until 4 (不包括4) |
反向区间 | 5 downTo 2 |
区间步长 | 5 downTo 2 step 2 |
var range1 = 2..6 //定义了一个范围对象
var range2 = 6 downTo 2
var range3 = 2 until 5
var range4 = 7 downTo 1 step 3
6、流程控制
6.1 分支结构
if分支
Kotlin的if分支既可以做为语句使用,也可以作为表达式使用。当作为表达式时,最后一条语句将作为表达式的值。
var age = 18
var str = if(age>20){
"age大于20"
}else if(age<20){
"age小于20"
}else{
"age等于20"
}
when分支
when分支取代了Java中的switch语句
var score = 'A'
when (score) {
'A' -> println("优秀")
'B','C' -> println("良好")
else -> println("差")
}
when分支的改进:
- 可以匹配多个值
- 分支的值不要求是常量,可以是任意的表达式
- 对条件表达式的类型没有要求,只要条件表达式与某个分支的值通过"=="比较返回true。
与if分支相同,when分支也可以作为表达式。
使用in,!in运算符,检查是否位于指定的区间或集合。
var str = when(age){
in 10..25 -> "少年"
else -> "其他"
}
使用is,!is运算符,检查表达式是否为指定类型
fun realPrice(inputPrice: Any) = when(inputPrice){
is String ->inputPrice.toDouble()
is Int ->inputPrice.toDouble
else -> 0.0
}
取代if..else if链
var age = 5
when{//不再需要条件表达式
age==5 -> print("五岁")
age==10 -> print("十岁")
else -> print("错误")
}
6.2 循环结构
Kotlin也支持while,do..while的循环结构,此外还支持for-in循环
for-in循环
专门用于遍历范围、List、Map和String。可遍历任何可迭代对象。可迭代对象是指该对象包含一个iterator()方法,且该方法的返回对象具有next()和hasNext()方法。
注意,此时不允许对被迭代对象进行数据变更
for(i in 2 until 10){
}
基础语法就先到这里,下一篇将介绍Kotlin中的数组和集合