由于公司之前的项目一直都是使用java进行开发,并未只用到kotlin,加之刚开始的时候使用kotlin进行实际项目开发的人也不多,所以一直是持观望的态度。但随着google对Kotlin的逐渐推广,越来越多人将kotlin用作Android的首选开发语言,也有很多比较知名的开源项目使用Kotlin进行重构或者在新版本上使用kotlin,可以预见Kotlin将会在这几年内取代java成为android的普适性开发语言,所以很有必要学习一波。
最近郭霖大神出版了《第一行代码》第三版,里面就有专门针对Kotlin的讲解,果断支持一波,入手了一本,本笔记是针对学习过程的一个简要记录。
1. 变量和函数
1. 1 变量
Kotin中定义变量的方式和java区别很大。在Kotlin中定义一个变量只允许在变量前声明两种关键字:val和var。
- val 用来声明一个不可变的变量,相当于java中的final变量
- var 用来声明一个可变的变量,相当于java中非final变量
下面我们来看一下这两个关键字的简单实用:
fun main(){
val a=2
var b=3
print("a=$a,b=$b")
}
注意:Kotlin中的每一行代码结尾是不用加分号的。
在上述代码中变量a和b并未指定数据类型,但并不会语法报错,因为Kotlin具有出色的类型推导机制,它可以根据你所赋值的类型去自动推导当前变量是什么类型,但这只限于即时赋值的情况,如果对一个变量进行延迟赋值,则kotlin无法进行类型自动推导,这时候就需要显示地声明变量类型,否则会报错。
例如:
val a:Int=10
注:Kotlin中完全抛弃了java中的基本数据类型,全部使用对象数据类(Int、Long、Short、Float、Double、Boolean、Char、Byte)
那么我们应该什么时候使用val,什么时候使用var呢?
建议:永远优先使用val来声明一个变量,当val无法满足需求的时候再使用var,这样的程序会更加的健壮。
1. 2 函数
函数是用来运行代码的载体。Kotlin的函数语法规则如下:
fun 函数名(参数名:参数类型):返回值参数类型{
return 返回值
}
其中,fun是定义函数的关键字,参数括号之后的返回值根据需要可要可不要,如果函数不需要返回值则,“:返回值参数类型” 这部分可以不写。下面让我们通过一个简单的例子来了解kotlin函数的一些特点:
fun main(){
val a=10
val b=40
val largerNum = largerNum(a, b)
print("largerNum=$largerNum")
}
fun largerNum(num1: Int, num2: Int): Int {
return max(num1, num2)//max()是kotlin中已经封装好的
}
和java一样,kotlin中程序的入口也是main()函数,上述代码和预期一样输出结果是“largerNum=40”。但是根据kotlin的特性,上述代码显得不够简洁,因为Kotlin中规定:
当一个函数中只有一行代码时,Kotlin允许我们不必编写函数体,可以直接将唯一的一行代码写在函数定义的尾部,中间用等号连接即可。,所以上面的函数可以简化为:
fun largerNum(num1: Int, num2: Int): Int = max(num1, num2)
使用这种语法,return关键字也可以省略了,然而上述代码还可以再进一步简化,因为max()函数的返回值是一个Int值,而largerNum()函数的尾部又使用了等号连接,所以kotlin可以根据类型推导机制推导出largerNum()函数的返回值必然是一个Int值,这样就不用显式声明返回值类型了,所以进一步简化后为:
fun largerNum(num1: Int, num2: Int) = max(num1, num2)
2. 程序逻辑控制
程序的执行语句主要分为3种:顺序语句、条件语句和循环语句。
2.1 if条件语句
Kotlin中的条件语句主要有两种实现方式:if 和 when。
Kotlin中的if语句和java中的几乎没有任何区别,唯一区别就是kotlin中的if语句是可以有返回值的,返回值就是if语句每一个条件中最后一行代码的返回值,下面通过一个简单的例子了解一下:
fun largeNum(num1:Int,num2:Int):Int{
var value=0
if(num1>num2){
value=num1
}else{
value=num2
}
return value
}
上面是类似于java的写法,下面我们通过if返回值这个特性简化一下:
fun largeNum(num1:Int,num2:Int):Int{
return if(num1>num2){
num1
}else{
num2
}
}
根据之前学的一个语法糖,你 觉得上述代码够精简了吗?答案当然是No,回顾一下之前的语法糖:当一个函数只有一行代码时,可以省略函数体部分,直接将这一行代码用等号串连在函数的尾部。所以进一步简化:
fun largeNum(num1:Int,num2:Int):Int=if(num1>num2){num1}else{num2}
是不是比原来简化了很多,你以为这就完了,没错,还可以再进一步简化,当你的执行逻辑只有一行代码时,{ }可以省略,所以还可以简化如下:
fun largeNum(num1:Int,num2:Int):Int=if(num1>num2) num1 else num2
2.2 when条件语句
Kotlin中的when语句有点类似于java中的switch语句,但又远比switch语句强大得多。
switch语句的缺点:
- 只能传入整型或短于整型的变量作为条件,jdk1.7之后增加了对字符串变量的支持,但如果你的判断逻辑使用的不是上述几种类型的变量,那就没法使用;
- 每个case条件在最后都要主动加上break,否则执行完当前case后会依次执行下面的case,这一特性曾经导致过很多奇怪的bug,就是因为有人忘记添加break;
而kotlin不仅解决了上述问题,还增加了许多更强大的功能。下面就来介绍一下when语句。
2.2.1 带参写法
语法结构:
when(参数){
匹配值->{执行逻辑}
}
我们来写一个通过姓名查询成绩的简单例子:
fun getScore(name:String)= when(name){
"Tom" -> 80
"LiLi" -> 40
"Jack" -> 90
else ->0
}
上述代码使用了单行代码函数的语法糖,when语句和if语句一样,也是可以有返回值的,when语句允许传入一个任意类型的参数,然后在when的结构体中定义一系列的条件。那通常什么时候应该使用when语句呢?当你的判断条件非常多的时候,就应该考虑使用when语句了
除了精准匹配之外,when语句还允许进行类型匹配,比如:
fun checkNum(num:Number){
when(num){
is Int -> print("number is Int")
is Double -> print("number is Double")
else -> print("number not support")
}
}
注:Int 、Double 等与数字相关的都是Number的子类
上述代码中,is 关键字就是类型匹配的核心,相当于java中的instanceof关键字。
2.2.1 无参写法
when语句还有一种不带参数的用法,虽然可能不太常用,但有时候却能发挥很强的扩展性。 拿前面的getScore()函数举例,如果不在when语句中传入参数的话,还可以这么写:
fun getScore(name:String)= when{
name=="Tom" -> 80
name=="XiaoLi" -> 40
name=="Jack" -> 90
else ->0
}
注意:Kotlin中判断字符串或对象是否相等可以直接使用==关键字,而不用像java那样调用equals()方法。
可以看到,这种用法是讲判断的表达式完整的写在when的结构体中,可能你会觉得这种写法比较冗余,但有些场景必须使用这种写法才能实现,例如:假设要所有名字以Tom开头的人,查询到的分数都是88,如果使用有参的when语句来写就无法实现,而使用无参的写法可以这样写:
fun getScore(name:String)= when{
name.startsWith("Tom")-> 88
name=="Tom" -> 80
name=="XiaoLi" -> 40
name=="Jack" -> 90
else ->0
}
2.2 循环语句
在java中主要提供了while和for循环语句,而kotlin也提供了while和for循环语句,其中while循环不管是语法还是使用技巧上都和java的没有任何区别。所以我们主要学习一下Kotlin中的for循环。
Kotlin将java中最常用的for-i循环直接舍弃了,而是将java中的for-each循环进行了大幅度的改进,变成了for-in循环。
在学习for-in循环之前,我们要先来通过代码了解一下kotlin中 区间 的概念:
val range1=0..10 //[0,10]
val range2=0 until 10 //[0,10)
val range3=10 downTo 0 //[10,0]
在kotlin中, . . 是创建两端闭区间的关键字,until是用来创建一个左闭右开区间的关键字,downTo 是用来创建一个降序区间的关键字,下面我们来看下它们在for循环中的简单使用:
fun main(){
testFor1()
testFor2()
testFor3()
}
fun testFor1(){
for (i in 0..10){
println("i=$i")
}
}
fun testFor2(){
for (i in 0 until 10){
println("i=$i")
}
}
fun testFor3(){
for (i in 10 downTo 0){
println("i=$i")
}
}
另外,我们在使用for循环的时候经常会有需要跳过某些元素的使用场景,为此kotlin中设计了一个step关键字,通过一个简单的例子了解一下:
for (i in 0..10 step 3){//区间[0,10],每次循环i+=3
println("i=$i")
}
for-in循环除了可以对区间进行遍历之外,还可以用于遍历数组和集合,我们在学到集合的时候顺便讲解。