- 目录与包的结构无需匹配:源代码可以在文件系统的任意位置
- 一切都是对象(即,任何变量都是根据引用类型来使用的)
- 变量分为var(可变的)和val(不可变的)。首选使用val不变值的好处:可预测的行为和线程安全
- 具有变量类型推断功能,例如可以这么写:
var x = 5 //自动推断出‘Int’类型
var y: Int = 1 //显式指定‘Int’类型
- is运算符检测一个表达式是否为某类型的一个实例
- 原始字符串由三重引号分隔。原始字符串可包括换行符和任何其他字符
- 字符串可以包含模板表达式,模板表达式由$符号开始
- if语句是一个表达式,即它会返回一个值,例如:
val max = if (a > b) a else b
- if的分支也可以是代码块,最后的表达式作为该快的值,例如:
val max = if (a > b) {
print("max is a")
a
} else {
print("max is b")
b
}
- kotlin没有三元表达式,别if else替代了。例如:
if(true) 1 else 0
- 如果表达式只有一个分支,或分支的结果是Unit,它的值就是Unit
- when表达式替代了switch case表达式,且更灵活强大。例如:
fun cases(obj:Any){
when(obj){
1,"one" -> print("第一项")
in 2..10 -> println("在区间[2,10]中")
!in validNumbers -> println("不在集合validNumbers中")
"hello" -> print("这个字符串是hello")
is Long -> print("这是一个Long类型的数据")
!is String -> print("这不是一个String类型的数据")
else -> print("else类似于Java中的default")
}
}
- 与if一样,when的每一个分支也可以是一个代码块,它的值是块中最后的表达式的值
- 使用for循环遍历数组或list的三种方式:
for(arg in args){
println(arg)
}
for(i in array.indices){
println(args[i])
}
for((index, value) in array.withIndex()){
println(the element at $index is $value)
}
- 函数的返回值可以不需要显示地用return来指定,但用return的编码风格更易于阅读
- kotlin中可以直接使用=符号来直接返回一个函数的值:
fun sum(a: Int, b: Int) = a + b
fun max(a: Int, b: Int) = if (a > b) a else b
val sum = fun (a: Int, b: Int) = a + b
sum(1,1) // 2
val sumf = fun (a: Int, b: Int) = {a + b}
sumf(1,1).invoke() // 2
- return语句会从最近的函数或匿名函数中返回,但是在lambda表达式中遇到return,则直接返回最近的外层函数
fun returnDemo_1(){
println("START " + ::returnDemo_1.name)
val intArray = intArrayOf(1,2,3,4,5)
intArray.forEach{
if(it == 3) return
println(it)
}
}
//1
//2
fun returnDemo_2(){
println("START " + ::returnDemo_2.name)
val intArray = intArrayOf(1,2,3,4,5)
intArray.forEach{
fun (a: Int){
if(a == 3) return
println(a)
}
}
}
//1
//2
//4
//5
- 在kotlin中任何表达式都可以用标签来标记。标签的格式为标识符后跟@符号,例如abc@、jarOfLove@都是有效的标签。可以用标签来控制return、break或continue的跳转行为。Kotlin的函数是可以被嵌套的。它有函数字面量、局部函数等。有了标签限制的return,就可以从外层函数返回了。例如从lambda表达式中返回,returnDemo_3()我们可以显示制定lambda表达式的return地址是其入口处:
fun returnDemo_3() {
val intArray = intArrayOf(1,2,3,4,5)
intArray.forEach here@ {
if( it == 3 ) return@here //指令跳转到lambda表达式标签here@处,继续下一个it=4的遍历循环
println(it)
}
}
//1
//2
//4
//5
- 上面的demo在lambda表达式开头处添加了标签here@,可以这么理解:该标签相当于是记录了lambda表达式的指令执行入口地址,然后在表达式内部就可以使用return@here来跳转至lambda表达式该地址处
- 另外,也可以使用更加方便的隐式标签,该标签与接收该lambda的函数同名,例如:
fun returnDemo_4() {
val intArray = intArrayOf(1,2,3,4,5)
intArray.forEach {
if (it == 3) return@forEach
println(it)
}
}
- 当在多层嵌套循环体中使用break时,会跳出最近外层的循环(也可用标签来显式地指出循环体的跳转地址来提高代码可读性:inner@、break@inner)。当想让break直接跳转到外层for循环,就可以使用标签了。例如:
fun breakDemo_2() {
outer@ for (outer in 1..5) {
for (inner in 1..10) {
println("inner=" + inner)
println("outer=" + outer)
if (inner % 2 == 0){
break@outer
}
}
}
}
//inner=1
//outer=1
//inner=2
//outer=1
- kotlin中throw是表达式,它的类型是特殊类型Nothing。该类型没有值,跟C、Java中的void意思一样。在代码中用Nothing来标记无返回的函数:
fun fail(msg:String):Nothing { throw IllegalArgumentException(msg) }
// 如果把一个throw表达式的值赋值给一个变量,需要显式声明类型为Nothing
// 另外,因为ex变量是Nothing类型,没有任何值,所以无法当做参数传给函数
val ex:Nothing = throw Exception("YYY")
- kotlin的块注释可嵌套
END
参考资料:《Kotlin极简教程》
网友评论