一、介绍
如今在Android开发中,应用层开发语言主要是Java和Kotlin,Kotlin是后来加入的,主导的语言还是Java。kotlin的加入仿佛让会kotlin语言的开发者更屌一些,其实不然。
有人说kotlin的引入是解决开发者复杂的逻辑,并且对空指针控制的比较友好,但是我们在开发过程中会发现,好像并不是这么回事,甚至有些开发者发现,在使用过程中会出现莫名其妙的错误,而且还不好定位。
这时候,我们应该去分析,kotlin适不适合自己,自己能不能驾驭?
二、分析Java与kotlin实战中的利与弊
学过政治都知道,任何东西都是一把双刃剑,既有好的一面也有不好的一面。不能什么都照搬过来。kotlin的好是建立在你已很好的掌握,但是不好的是你如果只会基础,在使用过程中,无法避免一些异常情况。但是Java的友好是适合新手使用,普及度高。
kotlin的弊端与分析
1、参数为null
参数为null这种很容易引起空指针,为什么会出现这种情况?是受Java的写法有关系
Java:
public void log(String txt)
Kotlin:
public fun log(txt:String)
正常Java你是可以传null进去,但是在kotlin,你传null就会报错
分析:
Java中,你参数可以传任何,你传null也是没问题,但是你在kotlin中,就没有这么随意了,这是为什么呢?
在kotlin中,任何参数都会被修饰,为空或者不为空,默认是NotNull。如果你不能传递null值过去。
如何避免?
只要我们是通过kotlin语法,你在任何参数申明都需要设置成为可为null
public fun log(txt:String?)
这个时候,在参数中,已变成可为null。
2、lateinit 报错未初始化先使用
lateinit 是稍后初始化,这个只能做全局,不能出现在方法体,但是也有个问题。如果你用lateinit
修饰一个变量,那么这个变量可以不先申明变量值,等使用时再初始化。
但是这个也会出现一个问题,如果你没初始化就使用会报错
lateinit var txt: String public fun log() { println(txt) }
有人会说,我不能判空嘛?判空也不行。只要你使用之前就必须初始化,否则就会报错。这个问题在新手特别容易犯错。
所以为什么这个关键字往往出现在修饰View的初始化使用比较多。这个在使用的时候进行判空,所以该字段默认为null,但是你使用必须要有值,只要你调用get方法就会触发。
思考:
有人会问,如果我直接修改变量的get方法,如果为null,那么get直接给他初始化。
lateinit不允许修改set和get。
但是Java就不会,Java是所见即所得,你的东西就是你的东西,kotlin是通过自己的语言限制,翻译成Java语言。所以,你不了解或者说不清楚目标类,很容易造成风险,并且这种bug被带到线上概率很大
3、参数类型强转"!!"导致null空指针
这种错误在方法调用很容易出现,而且这种BUG的概率非常高,导致项目质量很差。
public fun log(txt:String)
分析:
我们申请一个方法,参数不为null,在Java过程中,这种你不需要管,直接调用,一般对null的判断会在方法体中进行
Java:
public void log(String txt){
if(txt!=null){}
}
但是你在kotlin中,只能在调用处进行判断,否则就要将参数通过强制表示不为null,"!!"
我们在项目中进程遇到log(msg!!)这种错误的写法,这种写法,如果你的实参申请可以为null,但是形参不能为null,这个时候你只能通过"!!"来强转,但是:你的实参如果为null,这个时候就会报空指针,这是为什么?
这是因为你的实参在调用时已进行强制转换,也会提前进行空指针异常检查,所以在使用 "!!"强转符号时,一定要判空,否则会报错,但是Java中,我们随便传null。
4.形参为Val修饰的常量,无法修改
在kotlin中,形参是传值类型,你是无法直接修改变量,必须通过其他变量接收完再修改
默认是Val类型
public fun addOne(item:Int):Int{ val relVal=item+1 return relVal }
5.默认为null的变量引用
默认值为null,如果变量已申请为这种,那么你以后的使用将离不开"?"和"!!"转换。
var temp:String?=null
这种区分全局和局部
1、全局:
如果是全局,对于IDE来说,任何时刻都有可能是null,所以在方法中使用,默认当成null来处理
所以,你即使判空,还是不行。需要一辈子跟着"?"和"!!"搭配使用。
2、局部:
如果是局部,只要你在使用之前判断过一次,在合理的校验范围内都是有效
public fun log(mm:String) { var txt:String?=null if (txt==null) return
txt.length }
就是这种有起义的原因,导致在实战中,很多人很难理解
三、总结
通过kotlin的自身问题,其实kotlin就是一种插件语言,最终还是翻译成Java,只是目前来看,通过翻译的目标类,还是Java本身,但是增加了特别多的校验,导致写法和Java有很大的不同。这种不同来自我们的习惯问题。有人提前判空,有人喜欢丢在使用出判空,调用处让语法自然一些。
Android应用不像PC,空指针是致命的BUG,出现一个就会导致崩溃。所以,kotlin对空指针校验特别严格,也对使用埋下了隐患,新手可以绕开校验,但是对于绕开的原理不够理解,就会引起崩溃。
kotlin也不是一无是处,他更像是一个插件,插件的好处是自然的,可扩展等也是kotlin的自身优势。
所以,通过上面的分析,大家可以自行去选择项目中的语言,是kotlin还是Java,如果你向往kotlin的写法,那么就得去了解kotlin的原理,以及要改变自己在Java中的开发习惯。kotlin是先判断后使用,而Java写法很随意,由开发者自行定义,kotlin都是翻译好的。
最后,用好可以事半功倍,用不好,会引起各种不好排查的BUG。最后送一句话:水能载舟亦能覆舟。