前言
最近没有什么好写的,正好对kt做一个总结。可以来简单聊聊使用kt时的一些tips,如果有大佬有其它更好的建议,希望能分享出来,废话不多说,直接开始。
1. 转成java进行预览
通过AS的Tools-> Kotlin -> Show Kotlin Bytecode 然后会显示一个机器语言的预览窗口,再点击Decompile就能显示java的预览效果。
2. 字符串模板
在Java中我们做字符串拼接要用 + 号,比如一些打印带变量,例如写成Log.v(“mmp”,"code is " + code)
在kotlin中有 $ 符号来表示字符串模板,还是挺方便的。
上面的代码可以写成 Log.v(“mmp”,“code is ${code}”)
3. get/set方法
kotlin中的get/set方法会直接写在变量下边。
private var data : String ?= null
set(value) {
// todo
field = value
}
get() {
// todo
return field
}
记得刚开始从java转kotlin的时候还觉得这种写法挺奇怪的,感觉有点不舒服。但是当代码量大的时候,它的get/set方法和变量绑成一块,找指定的代码的时候还是挺方便的。
4. data类
data类是kotlin中的数据类,在创建kt文件的时候可以直接选择
data class TestData(
var name : String ?= "",
var age : Int ?= 0,
var sex : Int ?= 0,
)
使用时调用
val testData = TestData(age = 18)
有设置默认值的情况下能直接传指定参数,看得出使用起来非常简单,一般项目开发中的数据类都是使用data,就不会像java一样写一个类然后再写get/set方法来作为数据类了。kotlin提供这个data类对开发来说是能提供很大的便利。
5. ? 和 !! 判空
平时java中开发都是需要再很多地方进行判空的,一个稍不注意,就会出现空指针。我刚毕业的时候就是有的时候在使用对象时候忘记判空,当时还没kt,正巧某些极端的情况下测试也没测出来,你想想,在线上出现空指针的错误是一件多么丢人的事。
比如A对象中有B子对象,B对象中又有C子对象,然后一直有DEFG子对象。这没啥奇怪的,当业务复杂时,数据结构就会嵌套多个对象,如果这时候用java来写判空的代码
if(a != null && a.b != null && a.b.c != null && ...... && a.b.c.d.e.f.g != null){
}
这样代码是没问题,但多少确实会让人觉得不舒服。而在kt中?和!!可以实现判空的效果,如果不为空的话就继续执行,比如上面的代码可以改成
a?.b?.c?.d?.e?.f?.g?.let{
}
相对于java而言,首先写法更简单了,而且不容易漏判,因为如果可能为空的情况,你不用?符号,编译器就会提醒你,比如
可以看到编译器会提醒你,这对于我这种写代码比较快的人来说,简直就是福音。
而!!对于?不同在于!!如果为空的话会抛出异常。具体情况具体使用。
6. 扩展函数
我这里先啰嗦几句,其实kotlin里面的这些操作,只是一些思想。最终的实现也是会转成java去实现。可以简单理解成根据某些开发思想对原本的Java代码进行了封装。
扩展函数可以简单的理解成在原有的类的基础上去给这个类追加方法,并且这种操作不会对原本的类进行修改。那一听就很符合开闭原则的思想了。
假如我给上面的数据类TestData追加判断是否是男生的方法(一般不会直接对数据类做扩展,我这里是为了演示)
fun TestData.isBoy() : Boolean{
return sex == 1
}
这段代码在哪里写都得,不一定要在TestData里面写,调用的时候
val testData : TestData? = TestData(age = 18)
if (testData?.isBoy() == true){
......
}
可以看到扩展函数的使用很方便。但是也要注意,不要乱写,因为它是在哪里定义都行,所以最好是管理起来,这种代码不要到处乱飞,我一般如果对某个类加扩展函数,会给这个类单独写一个扩展文件进行管理。
还有,有些操作,你是需要对原本文件进行修改的,不是说一个文件你写好之后,之后都不会对这个文件进行修改,之后所有的修改都通过扩展函数去做,并不是这样的。
然后这里可以提出一个问题扩展一下,扩展函数内部java代码是怎么实现的?
7. 伴生对象
在kotlin里面没有静态一说法,取而代之的是伴生对象
通过关键代码块
companion object{
}
如果我们要定义类方法,就需要把方法定义在companion object里面。它表面上的效果就是和java中的静态的效果一样。但你不能说伴生对象就是静态,伴生是另一个概念,在Scala中也有伴生对象的概念,准确的说是Kotlin使用伴生对象来实现Java静态的效果,但不能说伴生就是静态
8. object类
说了伴生,那就涉及到kotlin中object这个关键词,我们如果要实现单例的效果,可以使用kotlin的object类
object类和data类一样可以直接创建出来
object TestObject {
fun test(){
}
}
调用的时候直接调用
TestObject.test()
看起来像java调用类方法,其实它是单例,也就是类似于java中的TestObject.getInstance().test() 这种写法
可以看出kt中实现单例也比Java方便很多。
9. 高阶函数 let、with、apply、run、also
这几个就是kotlin中比较重要也实用得比较多的操作符了,如果用得顺手,将会大大增加你的开发效率。这几个是学kt一定要会的,官方已经有很详细的介绍了,这里就只简单讲讲。
(1)let
先看看let表达式的定义: inline fun <T, R> T.let(block: (T) -> R): R
看不到没关系,只需要知道他是某个变量能调用let方法,在let代码块中能拿到这个变量,并最终返回最后一行
val result = testData?.let {
it.age
}
Log.d("mmp", "测试结果 $result")
可以看到结果
其他的高阶函数也是类似,我后面就不一一演示结果了。
这里只是介绍这些操作符,而如何使用熟练,这个就得靠积累了,我也不敢说我就已经能很熟练运用这些操作符。什么场合使用哪个操作符能达到最大的收益,最合适,这个就需要各位自己去思考了。
(2) run
run有两个用法,inline fun run(block: () -> R): R 和 inline fun <T, R> T.run(block: T.() -> R): R
val result = run {
"result"
}
testData?.run {
this.sex
}
(3) also
inline fun T.also(block: (T) -> Unit): T
这里可以看出对象调用also方法,返回值是它自己,比如
val result = testData.also {
it?.sex
}
Log.d("mmp", "测试结果 ${result}")
可以看到结果
(4) apply
inline fun T.apply(block: T.() -> Unit): T
apply可能有人看不懂这个表达式,这里可以解释一下,它的意思是它的内部作用域就是调用 apply的参数,例如
testData?.apply {
sex = 1
name = "xxxxx"
}
可以看到我这里使用的时候不需要it.sex这样。当然run那也是这样,可以看到它编译器中会有提示this
(5)with
inline fun <T, R> with(receiver: T, block: T.() -> R): R
可以这样使用
val result = with(testData!!){
sex = 1
name = "ABC"
name
}
和上面的类似,这里就不过多介绍了。因为这些操作符光讲是没办法让人熟练的,需要自己去使用,用多了就熟练了,如果熟练的使用,对开发来说大有好处。但是又不得不讲,因为这是kt中必须要会的东西。
10. 高阶函数和Lambda表达式
高阶函数和Lambda表达式也是比较重要的东西,并且也是没办法三言两语讲清楚的,必须经常使用,才能熟练的运用并且拥有自己的感悟。但其实高阶函数也是把双刃剑,如果你极致的去使用,导致你的代码能快速的去实现一些嵌套,但是别人不一定能一眼看得懂你写得啥玩意,但你又不能不用,因为他能为开发带来很大的便利。
这里就举几个简单的例子说说,主要是为了证明好用。
比如Lambda表达式,我们用Java写setOnClickListener,就不如用kt写的舒服
tv.setOnClickListener {
}
在kotlin中,函数还能作为参数进行传递。比如我想写一个回调,在java中,我需要定义一个接口,然后在外层传递一个匿名类进来,而在kt中,简单的回调就无需去写接口,写接口倒是不麻烦,但是相信很多人在命名的时候会纠结一段时间
private fun test(callback: () -> Unit) {
callback.invoke()
}
// 在外层调用
test{
}
可以看到这样写就非常的方便,无需定义接口,这就是kt中高阶函数和Lambda表达式的魅力。当然我这里的操作也只是简单的介绍,如果你能熟练使用,你会发现在实际开发中用上高阶函数的地方并不少。