简约之美Kotlin(四)让你的代码拒绝空指针

前言

本篇文章将着重介绍Kotlin的特色:空引用安全(Null Safety)。我们知道,包括Java在内的许多编程语言中最常见的陷阱之一就是访问空引用的成员导致空引用异常。在Java中,就是我们熟悉的空指针异常(NullPointerException)



目录

这里写图片描述

1.空引用安全

就像前面介绍的一样,Kotlin除了语法简单之外,一个比较大的特色就是通过其类型系统的定义可以有效的预防空指针的产生。

类型系统:

在Kotlin中,类型系统分为可以持有null类型的(可空引用)和不能为null(非空引用)。我们以String(引用类型)来举个例子:

var a: String = "kotlin null safety"
a= null // 编译报错

这里写图片描述

此时,如果使用变量a去访问其属性或者方法,这时候肯定不会导致空指针。

val len = a.length //编译通过      

如果我想str为null呢?我们可以声明一个变量为空字符串。可以写成String?:

var b: String? = "kotlin null safety"
b= null // 编译通过

这里写图片描述

如果用b变量去访问其属性或者方法,那这样就是不安全,编译报错。

val len = b.length // 错误:变量b不能为null

这里写图片描述

我们可以用下面这种方式来让上述编译通过。

b?.length // 编译通过

如果b变量不能null的话,则返回,这里的类型为Int?,如果b为null的话,则返回null。

除此之外Kotlin还提供了一个非空断言运算符。!!.,可以将任意值转换为非空类型。如果这个值为null时,将会抛出一个空指针异常。开发时,当我们确定要使用的引用一定不会为空,我们这时候对这个引用使用非空断言运算符,如果有意外情况的话,这里就是报错。

这里写图片描述

运行结果如下:

这里写图片描述



2.类型检查与转化

Kotlin中提供了类型检查和类型转换。分别是用 ‘is’关键词用于类型检查‘as’关键字用于类型转换

类型检查:

<!--判断是String类型-->
if (a is String) {
    print(a.length)
}

<!--判断不是String类型-->
if (a!is String) { 
    print("Not a String")
}else {
    print(a.length)
}

在使用类型表达时,要使用这个实例的成员。这里就不用再次作显示转换,在类型检查的过程中编译器自动将类型做了转换。

if (a is String && a.length > 0) {
      print(a.length) //&&前面条件满足,obj后面自动转换为String
}

类型转换:

Kotlin中提供了as关键字作为类型转换的标记。

private var fragments: MutableList<Fragment>? = null

fragments!!.add(homeFragment as Fragment)



3.这个表达式和范围表达式

这个表达式:

这个表达式指的是,在封闭范围内,如果想要访问外部范围(类,拓展功能等)可以通过this@关键字。看个例子。

btn.setOnClickListener({
      startActivity(Intent(this@MainActivity,DemoActivity::class.java))

})

/*通过this@MainActivity来指代外部类引用*/

范围表达式:

我们先来看个例子:

if (i in 1..6) { 
    println(i)   //打印的是1 2 3 4 5 6
}

上述就是Kotlin范围表达式的基本用法,. . 由运算符函数rangeTo形成。按照上述格式,如果是反过来呢?

if (i in 6..1) { 
    println(i)   //打印不出任何东西
}

反序循环的话Kotlin提供了downTo()函数

if (i in 6 downTo 1) { 
    println(i)   //打印出6 5 4 3 2 1
}

循环的步数不是1的话,可以用step()函数。

for (i in 6 downTo 1 step 2) print(i) // 打印 6 4 2

上述就是常用范围表达式的用法。

结尾

本篇对Kotlin语言的特色空指针安全做了介绍。使用Kotlin可以很大程度的防止项目里空指针的发生。各位大佬用起来吧。下篇将对Kotlin中的集合Lambdas表达式以及JavaKotlin的互相调用做介绍。

android 得到另一个Activity的返回值时报错 # activity1.kt ``` override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button.setOnClickListener() { val username: String = editText.text.toString() val intent = Intent("WZC.activity1") startActivity(intent) intent.putExtra("username", username) //startActivity(intent) startActivityForResult(intent, 0) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) val result = data!!.extras.get("result").toString() textView2.text = result } ``` ## activity2.kt ``` override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) val username = intent.extras.get("username") as String textView.text = "Welcome," + username button5.setOnClickListener(){ val intent = Intent("MainActivity") intent.putExtra("result","Result from Main2Activity.") setResult(0,intent) finish() } } } ``` ## 错误日志 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ruaaaaaaaa.myapplication/com.example.ruaaaaaaaa.myapplication.Main2Activity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.os.Bundle.get(java.lang.String)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.os.Bundle.get(java.lang.String)' on a null object reference at com.example.ruaaaaaaaa.myapplication.Main2Activity.onCreate(Main2Activity.kt:14) at android.app.Activity.performCreate(Activity.java:5937) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)  at android.app.ActivityThread.access$800(ActivityThread.java:144)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:135)  at android.app.ActivityThread.main(ActivityThread.java:5221)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)  Application terminated.
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页