Kotlin语法梳理(二)
目录
声明变量
声明变量使用 var、val关键字,如下:
var | val 变量名 [:类型] [= 初始值]
var n : Int = 0
var s : String = "变量的定义" // var声明的是变量,val声明的是常量
和 Java 的不同之处是,变量类型写在变量名后面了,和 go 语言类似。在Kotlin中每条语句的最后不用加分号。
数据类型
与Java基本类型相对应,Kotlin也有8中基本数据类型:
- 整数类型:Byte、Short、Int和Long,Int是默认类型。
- 浮点类型:Float和Double,Double是默认类型。
- 字符类型:Char。
- 布尔类型:Boolean。
Kotlin的8个基本数据类型没有对应的包装类,Kotlin编译器会根据不同的场景将其编译成为Java中的基本类型数据还是包装类对象。例如,Kotlin的Int用来声明变量、常量、属性、函数参数类型和函数返回类型等情况时,被编译为Java的int类型;当作为集合泛型类似参数时,则被编译为Java的java.lang.Integer,这是因为Java集合中只能保存对象
数据类型之间的转换
Kotlin中要想实现这种赋值转换,需要使用转换函数显式转换。Kotlin中不能像Java中那样的自动类型转换,必须显示转换;Kotlin的6种数值类型(Byte、Short、Int、Long、Float和Double),以及Char类型都有如下7个转换函数: toByte(), toShort(): , toInt(),toLong(),toFloat(), toDouble(), toChar() 通过上述7个转换函数可以实现7种类型(Byte、Short、Int、Long、Float、Double和Char)之间的任意转换。
var n1 :Int = 10 //或者 var n1 = 10,整数默认为Int
var n2 :Double = n1.toDouble() //必须显示转换
非空安全
Kotlin默认是非空的,在非空类型后面加上问号“?”表示可空类型。
var str : String = null //错误的代码,默认非空
var str : String? = null //标识可空
可空类型在具体使用时会有一些限制: 不能直接调用可空类型对象的函数或属性。 不能把可空类型数据赋值给非空类型变量。 不能把可空类型数据传递给非空类型参数的函数。
var str : String? = null
........
str.length //错误代码,可空类型不能直接调用可空类型对象的函数或属性
为了“突破”这些限制,Kotlin提供了如下运算符: 安全调用运算符:?. Elvis运算符:?: 非空断言:!!
可空类型变量使用安全调用运算符?. 可以调用非空类型的函数或属性。安全调用运算符?. 会判断可空类型变量是否为空,如果是则不会调用函数或属性,直接返回空值;否则返回调用结果。
var str : String ? = null
var length = str!!.length //非空断言,一旦str为空,抛出空指针异常
var str : String? = null
var length = str?.length //如果str不为空直接调用,如果为空直接返回null,而不会抛出空指针异常
如果为空时不想返回null,通过?:可以执行为空时的返回值
var length = str?.length?:0 //str为空时返回0 A ?: B,如果A不为空值则结果为A,否则为B
常量
在Kotlin声明常量是在标识符的前面加上val或const val关键字,它们的区别如下:
- val声明的是运行期常量,常量是在运行时初始化的。
- const val 声明的是编译期常量,常量是在编译时初始化,只能用于顶层常量声明或声明对象中的常量声明,而且只能是String或基本数据类型(整数、浮点等)。
给Java程序员的提示 编译期常量(const val)相当于Java中public final static所修饰的常量。而运行期常量(val)相当于Java中final所修饰的常量。
运算符
Kotlin的==运算符和equals函数等同于Java的equals函数。Kotlin中的===运算符等同于Java的==运算符。
定义方法
fun [方法名] ( [参数名] : [参数类型] ) : [返回类型]{
...
return [返回值]
}
fun add(m:Int, n:Int):Int {
return m + n
}
//也可以写成表达式的方式:
fun add(m : Int, n : Int) : Int = m + n
流程控制语句
Kotlin 中流程控制语句的结果可以直接赋值给一个变量
//java传统写法
if (a > b) {
max = a
} else {
max = b
}
// kotlin写法
val max = if (a > b) a else b
when语句
when 取代了类 java中的 switch 操作符。其最简单的形式如下:
when (i) {
1 -> {
//操作。。。。
}
2 -> {
//操作。。。。
}
else -> {
//操作。。。。
}
}
此外,还可以使用in或者!in表达式结果是否在一个范围或集合中;可以用is或者!is表达式结果是否是某一类型的对象
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid") //validNumbers 为一个集合
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
when (view) {
is TextView -> toast(view.text)
is RecyclerView -> toast("Item count = ${view.adapter.itemCount}")
is SearchView -> toast("Current query: ${view.query}")
else -> toast("View type not supported")
}
when语句还可以省略表达式,此时分支条件表达式默认为Boolean型,在分支为true时会执行分支
when {
a is String -> print("传入的值是String类型")
a is Int -> print("传入的值是Int类型")
a is Long -> print("传入的值是Long类型")
a is ExampleUnitTest -> print("传入的值是ExampleUnitTest类型")
}
for循环
for (item in stringArrays){
println(item)
}
在for语句遍历集合时,一般不需要循环变量,但是如果需要使用循环变量,可以使用集合indices属性
for (i in stringArrays.indices) {
println(stringArrays[i]) //i为索引
}
还可以指定一个范围
for (i in 0..10 step 1) { // step 1 指定步长(i每次加几)可以省略,默认为1
println(stringArrays[i])
}
forEach 使用
stringArrays.forEach { //stringArrays为一个集合
println(it);
}
还可以在遍历的时候获取索引
mlist.forEachIndexed { index, value -> //index为索引,value为索引对应的值
println("第${index}个值为:$value")
}
return,break和continue
Kotlin 和java一样,有三种结构化跳转表达式:
return :从包围它的函数或匿名函数返回
break : 终止循环
continue: 跳出本次循环,继续下一次循环
和Java不同的是,这些表达式都可作为更大表达式的一部分:
val s = person.name ?: return
break和continue语句都有两种方式:带有标签和不带标签
loop@ for (i in 1..100) { //" loop@ "定义的标签 格式为:名字@
for (j in 1..100) {
if (……) break@loop // 终止loop标记的循环
if (……) continue@loop // 跳出loop标记的循环,继续下一次loop标记的循环
}
}
**return ** 也支持 @标签标签,只是标签定义的地方不同
mList.forEach lit@ {
if (it == 0) return@lit // 标记从forEach{}返回
print(it)
}
//用隐式标签(与接收lambda的函数同名)从lambda表达式中返回:
mList.forEach {
if (it == 0) return@forEach // 隐式标签forEach,从forEach{}返回
print(it)
}
需要注意的是:当return返回值时,表示的含义是不一样的
return@a 1 // 从@a标记的函数返回1,不是返回标记的表达式(@a 1)”。
不带标签的用法与Java中的一样。
总结
上述只是一些简单的语法,跟java中的用法差不多,只是功能更强大一些,使用起来确实很方便;重点是在类相关语法那块与Java中有很大的不同,内容也比较多。下一篇主要来梳理类相关的语法以及注意点。