一、var和val
在之前的博客中,我们经常使用到var和val这两个关键字,这两个关键字有什么区别呢?val定义的值是不可变的,而val定义的值是可以变的。这让我们想起来Java中final这个关键字,其实val使用起来和Java中的final没什么区别,但是在本质上其实是不一样的,具体怎么不一样呢?如果你去看编译后的字节码就知道了。那Java中的final关键字和Kotlin中的谁是完全一样的呢?在val前加一个const关键字,即const val。这两个值用语言描述一下就能知道区别了,没有必要上代码了~
二、函数
函数在上两篇的博客中我经常使用到,最常见的就是main函数了,它是Kotlin程序的入口。
fun main(args: Array<String>) {
}
大家都知道,Java中的main函数,有一个返回值void,那Kotlin的main函数的返回值呢?其实Kotlin的main函数返回值是Unit,被省略了,它的作用和Java中的void是一样的,如下
fun main(args: Array<String>):Unit{
}
如果返回值是其他类型的函数,在方法后面写其他值即可,如下:
fun test():Int{
return 1
}
上述的代码块返回值只有1,所以还可以进行优化:
fun test():Int=1
等号后面的内容,相当于方法体中内容。
其实,方法也可以没有名称,被一个变量接收,这个是Java所没有的,如下代码
fun main(args: Array<String>){
testFun("gzc")
}
val testFun = fun(str:String)= println("$str")
上述的代码会输出相应的字符串,非常神奇吧
三、Lambda表达式
Lambda表达式其实就是匿名函数,在Kotlin中这个方式是非常常见的,所以,Lambda表达式非常重要。我举两个简单的例子,来理解一下
fun main(args: Array<String>) {
println(lambda1(1, 2))
lambda2(2, 2)
}
val lambda1 = { i1: Int, i2: Int -> i1 + i2 }
val lambda2 = { i1: Int, i2: Int -> println("$i1+$i2=${i1 + i2}");i1 + i2 }
我们看lambda1这个表达式,i1和i2是方法的参数,i1+i2是方法的返回值。初次见Lambda表达式会非常别扭,虽然这样的写法简略了不少,但是参数和返回值表现的不是那么清晰。其实我们只需要记住->前面的就是参数,而后面最后一行或者分好分割的最后一段代码就是返回值,比如lambda2这个例子,分号前面有一个打印函数,但是分号最后的i1+i2参数这个表达式的返回值
四、运算符
关于运算法我先贴出官方文档
https://kotlinlang.org/docs/reference/operator-overloading.html
运算符有很多,比如+ - * / %等,其实在Kotlin中都每一个运算符都有一个相应的函数与之对应,比如+对应的函数就是plus,-对应的就是minus等,还有很多很多,在官方文档都有描述。如果每一个运算符是函数,那么能不能覆写呢?当然能了,这也就是Kotlin的一个特点是Java所没有的,下面我来举个例子:
class A(var i1:Int){
operator fun plus(a:A):Int{
return i1+a.i1
}
}
fun main(args: Array<String>) {
var a1 = A(5)
var a2 = A(7)
println(a1+a2)
}
最后输出是5+7的值12。我来简单解释一下上面代码的含义:创建了一个类A,构造器接收了一个Int类型的变量i1,覆写plus方法,这个plus方法便是的含义就是+的意思,这个在官方文档中有介绍。plus函数前面需要由operator关键字修饰,表示覆写的方法是一个运算符。而plus方法接收了一个A类型的参数,这个参数就是+后面的类型,返回值就是两个A类构造器接收的参数相加之和。我们再看下面的代码:
class B(var i1:Int){
operator fun plus(b:B):B{
return B(i1+b.i1)
}
override fun toString(): String {
return "值为$i1"
}
}
fun main(args: Array<String>) {
var b1:B = B(4)
var b2:B = B(5)
println(b1+b2)
}
现在定义了一个类B,构造器接收的参数依然是一个Int类型,但是plus函数所接受的参数变为B类型,也就是说+后面接收的对象需要是B类型的,就像是main函数里写的那样。如果我们不写B中的toString方法,进行输出,你会发现是一个你看不懂的值,这是为什么呢?因为plus方法的返回值是一个B类型的,直接输出B类型,是一个内存地址。所以我们覆写toString方法,自定义toString方法的返回值。main方法中直接输出了b1+b2的返回值,也就是plus方法的返回值。所以i1为9,输出的结果就是toString自定义的结果
五、表达式
中缀表达式
什么是中缀表达式呢?被关键字infix修饰的函数就是就是中缀表达式,我们来看下面代码:
class A(var i: Int)
class B(var i: Int) {
infix fun equel(a: A): Boolean {
return i == a.i
}
}
fun main(args: Array<String>) {
var a = A(1)
var b = B(1)
println(b equel a)
}
其他的我就不说了,重点说一下被infix修饰的equel方法,接收参数为A类型,返回值为Boolean类型。在equal方法内部比较出入的参数值,并返回结果。上述的代码返回值为true。中缀表达式在某些业务场景很有应用性,但是也不要乱用,否则会导致代码的可读性变低。
分支表达式
在Java中的分支表达式有if和switch,而Kotlin中有if和when与之相对应。我们先说if吧,和Java中的用法基本一致,如下代码
fun main(args: Array<String>) {
var i=1
if(i is Int){
println("i 是Int类型")
}else{
println("i 不是Int类型")
}
}
没什么的特别说明,Kotlin中的if还有一种特殊的用法,就是if表达式有返回值,如下代码:
fun main(args: Array<String>) {
var i=1
var b = if(i is Int) true else false
println("b=$b")
}
if表达式中的代码表示如果i是Int类型,则返回true,否则返回false。和Lambda表达式非常相似,当然我们也可以在返回值前面写其他的代码,如下:
fun main(args: Array<String>) {
var i=1
var b = if(i is Int){
println("i是Int类型")
true
}else{
println("i不是Int类型")
false
}
println("b=$b")
}
if表达式我们说完了,接下来我们说一下when这个表达式,其实when是加强版的switch,为什么这么说呢?大家都知道,switch接收的类型是有限的,并不是能判断所有的类型,而且break这个关键字是不能少的。但是Kotlin中的when不同,而且所表达的内容更加丰富,看如下代码:
fun main(args: Array<String>) {
var i = 1
when(i){
1-> println("i的值为1") //如果i等于1
is Int-> println("i是Int类型")//如果i的值是Int类型
in 1..100-> println("在范围内")//如果1在1-100范围内
}
}
我在代码中写了相应的注释注明了条件的含义,->后面的代码就是条件成功执行的代码,而且不需要break。如果相同条件都符合,想执行一种条件怎么办,我们只需要将条件用逗号分隔即可,如下:
fun main(args: Array<String>) {
var i = 1
when(i){
1,is Int,in 1..100-> println("条件符合")
}
}
when既然是表达式,那也应该有返回值,和if一样,如下代码:
fun main(args: Array<String>) {
var i = 5
var b = when{
i==1->true
else->false
}
}
如果i==1则返回true,否则的话返回false