Kotlin简单问

2020-12-25 10:03:01 浏览数 (1)

前言

今天复习下kotlin相关的知识点和常考考点,通过这些问答相信你也能更一步了解Kotlin。

kotlin为什么被设计出来

kotlin被设计出来并被Google推广,主要有以下优势:

  • 完全兼容Java
  • 更少的空指针异常
  • 更少的代码量,更快的开发速度(lambda表达式,扩展函数)

kotlin工作原理

首先,我们了解下Java的工作原理:

Java 代码是经过编译才能运行的。首先会编译成class文件,然后通过java虚拟机运行,在Android中也就是ART。

所以,任何语言只要能被编译成符合规格的class文件,就能被java虚拟机运行,也就能运行在我们的Android手机上,kotlin亦是如此。

  • 另外Android studio也提供了一个功能,可以查看kotlin对应的字节码:

Tools -> Kotlin -> Show Kotlin Bytecode

再点击Decomplie还可以反编译成Java文件。

kotlin的空安全

  • java中,我们可以任意初始化一个变量,而不需要赋值,比如String,就有它的默认值null。
代码语言:javascript复制
String a;

如果要调用对象的参数,必须判空:

代码语言:javascript复制
if (a!=null){
   Log.d("lz","length=" a.length());
}else{
   Log.d("lz","length=null");
}
  • kotlin中,为了保证减少空指针的问题,不允许直接设置为空,可以通过?=的方式设置可以为空。
代码语言:javascript复制
val a: String ? = null

1)赋值的时候,可以直接使用?来表示这个对象可能为空,如果为空则表达式结果也为空,而不用进行非空判断。

代码语言:javascript复制
//如果 b 非空,就返回 b.length,否则返回 null
val length = b?.length
//如果 b 非空,就返回 String类型的b,否则返回 null
val str = b as? String 

也就是通过问号来表示对象为空则整个表达式结果为空,而不会报错空指针。

2)如果需要设定为空的时候返回的表达式值不为空,可以用操作符?:来表示,也叫Elvis操作符。

代码语言:javascript复制
//b为空则表达式返回-1
val length = b?.length ?: -1

3)如果要将值转换为非空类型,就可以使用 !!来标识非空,但是这种操作符就有可能会抛出空指针异常,如果实际对象为空的话。所以这种操作符相当于去除了空判断。

代码语言:javascript复制
//如果b为空,空指针异常
val length = b!!.length

val和var

val,全称value,声明一个不可变的变量,这种变量在初始赋值之后就再也不能重新赋值了,所以相当于java中的final变量。

var,全称variable(可变的),所以是用来声明一个可变的变量,可以重复赋值。

kotlin中这么设计的原因主要是把不可变变量 这种因素和可变变量拿到同一级来设计,也就是说我们以后编码设计变量的时候,必须要考虑这个变量是不可变还是可变的,保护变量安全,养成良好习惯,而不像以前要在java中需要添加final这种稍微繁琐的举动。

扩展函数(Extension Function)

扩展函数,其实就是扩展类的函数,可以在已有的类中添加新的方法,比继承更加简洁优雅方便。

  • 扩展函数比如:
代码语言:javascript复制

fun Activity.showToast( msgId:Int){
    Toast.makeText(this,msgId,Toast.LENGTH_SHORT).show()
}

这样任何的Activity里面就可以直接调用showToast方法来展示Toast了。

  • 同样,可以设置扩展属性,比如:
代码语言:javascript复制
var <T> MutableList<T>.lastData: T
    //获取List中最后一个对象
    get() = this[this.size - 1]
    //设置List中最后一个对象的值
    set(value) {
        this[this.size - 1] = value
    }

用法:

代码语言:javascript复制
var strs = mutableListOf<String>()
strs.lastData="heihei"
Log.e(TAG,"lastdata= ${strs.lastData}")

这里还涉及到两个知识点:

  • kotlin中,在使用对象的get和set方法,可以直接省略,直接使用属性名即可,会根据表达式的实际功能来添加对应的set或者get方法。
  • kotlin中,对于$符号表示 串模板,就是可计算的代码片段,可以将其计算结果链接到字符串中。

扩展属性原理

kotlin这个扩展功能确实设计的很巧妙,那就一起来研究下它的原理:

按照上面的方法,也就是Tools -> Kotlin -> Show Kotlin Bytecode -> Decomplie, 我们得到showToast扩展函数和使用代码所对应的java代码:

代码语言:javascript复制

//扩展函数
public final class UtilsKt {
   public static final void showToast(@NotNull Activity $this$showToast, int msgId) {
      Intrinsics.checkParameterIsNotNull($this$showToast, "$this$showToast");
      Toast.makeText((Context)$this$showToast, msgId, 0).show();
   }
}

//使用
UtilsKt.showToast(this, 1900026);

可以看到所谓的扩展函数不过就是自动生成一个带有当前对象的函数,扩展函数的所在类被public final修饰,函数被public static final修饰,然后扩展的那个类被作为方法的一个参数传进去,这样就跟我们用java的时候写的工具类很像。

然后使用的时候就跟我们使用工具类一样调用工具类的方法即可。

拜拜

今天就聊这么多了,kotlin东西还是挺多的,也有一些考点,下次继续聊。

?又到周一了,难受呀,祝大家这周工作顺利~

感谢大家的阅读,有一起学习的小伙伴可以关注下公众号—码上积木❤️ 每日三问知识点/面试题,积少成多。

0 人点赞