Kotlin中的一个伟大创前举就是空指针的处理,在代码的编译阶段就能检测可能出现的空指针问题,示例代码如下:

data class Person(var name: String? = null)

fun sayHello(name: String) {
    println("Hello $name")
}

fun main() {
    val person = Person("Even")
    if (person.name != null) {
        sayHello(person.name)
    }
}

在IntelliJ中,如上代码会报错,如下:

提示的错误信息翻译为:智能强制转换为’String’是不可能的,因为’person.name’是一个可变属性,此时可能已经被更改了。

要想编译通过,需要这样做:

sayHello(person.name!!)

哎?我记得学Kotlin的时候有解释说如果已经判断了不是空了的话,就不需要添加 !! 符号的,为什么这里不添加的话会报错呢?其实原因就是报错信息上提示的,因为name是用var修饰的,而且这是一个成员变量,虽然你做了非空的判断,但是判断之后,这个成员属性有可能在其它线程被修改了,比如在其他线程设置为null了,所以,这样的话就会出现空指针异常了,所以添加 !! 符号来解决报错不是最佳实践,在我这个示例中,我们知道没有开多线程去修改person的name属性,所以可以加 !! 来解决,但是最好不要这样做,如果我们知道name属性不会被修改,则可以使用val修饰,如下:

可以看到,此时不需要添加 !! 也不报错了,因为IDE知道name是一个不可变属性,判断了不是空之后,就永远不可能是空了。

有时候,name属性就需要发生变化,就必须声明为var,此时怎么解决呢?,可以通过添加局部变量解决,如下:

如上代码,IDE没有报错。我们通过添加一个val类型的name局部变量来保存person.name的值,这样的话,判断了name为不为空之后,即使person.name在子线程被设置为空了,但是局部变量name不会受到影响。我们在阅读一些系统源码的时候,不论是Java源码或是Kotlin的源码,经常发现别人在判断一个对象的属性的可空性的时候,都是先声明一个局部变量保存该对象属性再来判断,不懂事的时候就会奇怪别人为什么要多此一举,现在明白了,别人是为了预防直接判断对象属性出现的多线程修改带来的问题。

添加局部变量的话,即使是var类型的局部变量IDE也能判断是否为空,示例如下:

如上代码,可以看到,局部变量name是可变类型的,但是也不需要添加 !! 符号,因为var类型的局部变量不会被子线程修改,所以判断了不为空之后就不会为空。最后赋值了”Lily“,然后传给sayHello(name),这里并没有做非空判断啊,sayHello接受的是不可空的String,但是name是一个可空String啊,道理也很简单,因为这是局部变量,没有子线程的干扰,IDE能检测到name在传给sayHello之前是赋值了”Lily"的,之后没有再赋值为null也是能检测出来的,所以这里不需要做可空判断也能编译通过。如果没有赋值“Lily",则IDE就不知道name是否为空了,就会报错,如下:

或者,如果我们使用的是一个成员变量,即使前一句代码赋值了下一句就用也是会报错的,原因就是它有可能在子线程被设置为null了,如下:

所以,Kotlin是真的很强,如果你在使用一个变量,只要IDE没报错,你就可以放心的使用,不需要做空判断,你可以放心,运行时不会有空指针问题的。如果IDE报错了,就是有可能发生空指针的,此时你就不要强制添加 !! 来逃避问题了,一定要做合理的空指针判断处理。如果你使用Java的话,要不要做空指针处理IDE是没有提示的,你只能自己用脑子去想要不要做空指针判断处理,事实往往是我们根本就不去想要不要做处理,或者即使思考过了,也会有思考出错的时候,比如可能出现空指针的地方,但是你写代码时你认为不会出现空指针,所以你没做非空判断处理,则运行时就有可能出现空指针异常了。而Kotlin就会有提示,只要IDE没报错就不用做空指针处理,只要IDE报错了就要做空指针处理,这真是爽歪歪啊,你不需要去思考什么时候应该添加空指针判断处理了!

注:这个可空判断也适用于类型智能转换,这个知识点在官网教程上也找到了答案:https://kotlinlang.org/docs/typecasts.html#unsafe-cast-operator,相关内容如下:

Note that smart casts work only when the compiler can guarantee that the variable won’t change between the check and the usage. More specifically, smart casts can be used under the following conditions:

val local variables - always, with the exception of local delegated properties.

val properties - if the property is private or internal or if the check is performed in the same module where the property is declared. Smart casts cannot be used on open properties or properties that have custom getters.

var local variables - if the variable is not modified between the check and the usage, is not captured in a lambda that modifies it, and is not a local delegated property.

var properties - never, because the variable can be modified at any time by other code.

附:?.和!!.

其实kotlin是非常人性话的,你定义了一个可为空的变量但是你依然可以去操作的。我们修改一下上面的写法:

val a:String = "我加小明"
val b:String ?= null
val c:String? = "我加小明"

  println(a.length)
  println(b?.length)
   println(c!!.length)

这样编译就通过。

这里的**?.**就是相当于Java的如果为空就返回null 而kotlin强制让我们去处理,这样就避免了很多空指针异常

if(b==null) return null;

当然如果你不想直接为null,你说当为空时我想自己去处理,kotlin还有语法**?:**

val b:String ?= null
 println(b?.length?:"我错了")

!!. 表示我任性,告诉编译器不要去做非空检查,为空就抛异常

总结

到此这篇关于Kotlin中空判断处理操作的文章就介绍到这了,更多相关Kotlin空判断处理内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Kotlin中空判断处理操作实例的更多相关文章

  1. Kotlin难点解析:extension和this指针

    扩展是Kotlin语言中使用非常简单的一个特性。关于这个问题,其实我之前的一篇文章[[Kotlin]LambdaandExtension](https://www.jianshu.com/p/d7a...中有提到过。为了解决这个问题,官方提出了两个新的概念:dispatchreceiver和extensionreceiver。extensionreceiver:中文翻译为扩展接收者。为了简化,这里我们将dispatchreceiver简称为DR,将extensionreceiver简称为ER。如果你习惯了

  2. android – Kotlin类NoClassDefFoundError崩溃

    我有一个使用以下库的现有Android项目:>Autovalue>Dagger2>RxJava>Retrolambda我正在尝试添加Kotlin支持,以便我可以将项目慢慢迁移到Kotlin.这就是我所做的.>添加了Kotlin依赖.>将其中一个类转换为Kt类并转移到src/main/kotlin/..包中.>在源集中添加了kotlin.sourceSets{main.java.srcDirs=’s

  3. android – Kotlin和Dagger2

    我正在尝试将Kotlin添加到我的项目中,但在启用Kotlin之后我无法构建,因为Dagger2类不再生成.我尝试了第二个项目,我有同样的问题.这些是我为启用Kotlin所做的改变:项目build.gradle:Appbuild.gradle:错误发生在这里:其中不再定义DaggerObjectGraph.任何帮助将不胜感激.解决方法只需删除

  4. android – 在Kotlin中不能使用argb color int值吗?

    当我想在Kotlin中为TextView的textColor设置动画时:发生此错误:似乎在Kotlin中不能将值0xFF8363FF和0xFFC953BE强制转换为Int,但是,它在Java中是正常的:有任何想法吗?提前致谢.解决方法0xFF8363FF是Long,而不是Int.你必须明确地将它们转换为Int:关键是0xFFC953BE的数值是4291384254,因此它应该存储在Long变量中.但这里的高位是符号位,表示负数:-3583042,可以存储在Int中.这就是两种语言之间的区别.在Kotlin

  5. 什么是我可以使用Kotlin的最早的Android API级别?

    我认为这个问题很清楚但是我能在Kotlin上定位的最早API级别是什么?解决方法实际上,任何API级别.这是因为Kotlin被编译为JVM6平台的字节码,所有AndroidAPI级别都支持该字节码.因此,除非您在Kotlin代码中使用任何较新的AndroidAPI,否则它不需要任何特定的API级别.

  6. android – Kotlin数据类和可空类型

    我是Kotlin的新手,我不知道为什么编译器会抱怨这段代码:编译器抱怨测试?.data.length,它说我应该这样做:test?.length.但是数据变量是String,而不是String?,所以我不明白为什么我要把它?当我想检查长度.解决方法表达式test?.data部分可以为空:它是test.data或null.因此,获取其长度并不是零安全的,而是应该再次使用safecalloperator:test?.length.可空性通过整个调用链传播:你必须将这些链写成?.)).e),因为,如果其中一个左

  7. android – Kotlin自定义获取执行方法调用

    像这样的东西:仍在使用Kotlin并且不确定get()方法是否会引用编辑器而不是创建新的编辑器.解决方法第二个属性声明适合您的需要:它有一个customgetter,因此获取属性值将始终执行getter,并且不存储该值.你可能会被等号get()=…

  8. android – Kotlin合成扩展和几个包含相同的布局

    我找了一些这样的:我在Studio中看到我可以访问dayName但是dayNameTextView引用了哪一个?正常,如果我只有一个包含的布局,它工作正常.但现在我有多次包含相同的布局.我当然可以这样做:但我正在寻找好的解决方案.版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  9. android – java.lang.IllegalArgumentException:指定为非null的参数为null:方法kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull

    我收到了这个错误java.lang.IllegalArgumentException:指定为非null的参数为null:方法kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,参数事件为线覆盖funonEditorAction(v:TextView,actionId:Int,event:KeyEvent)以下是整个代码.这段代码最初是在ja

  10. android – Kotlin:如何访问CustomView的Attrs

    我在Kotlin中创建了一个自定义视图,并希望访问它的属性资源.以下是我的代码请注意,这将在init函数的attrs中出错.我想知道如何进入attrs?

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部