Kotlin可空性探索

目录介绍

  • 01.可空性
  • 02.安全调用运算符:?.
  • 03.Elvis运算符:?:
  • 04.安全转换运算符:as?
  • 05.非空断言:!!
  • 06.let函数说明
  • 07.可空类型的扩展
  • 08.Java中判断方式
  • 09.kotlin是否解决NPE
  • 10.kotlin如何约束非空判断
  • 11.导致NPE的场景

想换个工作,渴望同行内推我

  • 个人信息
    • 姓名:杨充【26岁】
    • 邮箱:yangchong211@163.com
    • 微信:13667225184
    • GitHub:https://github.com/yangchong211
    • 博客汇总:https://github.com/yangchong211/YCBlogs
    • 干活集中营:Android端技术博客和开源项目审核员
    • 目前工作情况:在职状态
    • 技术项目和博客:GitHub项目7k以上star,follower1.1k以上,发表博客100多篇。
    • 热爱技术:开源项目和博客多次被鸿洋,郭霖,Android技术周刊,干活集中营等等推荐。
    • 学历:武汉软件工程职业学院,大专学历
    • 工作年限:3年多
    • 工作地点:北京
  • 关于近期投递简历一点感想
    • 从进入Android这个行业以来,前两次几乎都是朋友内推,面试机会相对容易,都是一个App一个人做或者两个人做,用户相对来说并不多。这次想着离职,主要是想进入一个较大的平台,大概可以理解为Android端有个至少四五人,可以进行技术交流,渴望自己能够在技术上突破,这就像自己平时独自跑步,和跟着一群跑马拉松的人跑步,那种紧张感肯定是不一样的。
    • 近段时间,尝试着向一些较大的公司投递简历,大概在拉钩上投了15个左右(不喜欢海投),发现绝大多数简历到不了技术那里,就被人事说学历不够,经验不够,工作不匹配等情况回绝。不过也可以理解,看简历无非就是学历和经验,貌似自己的履历是差了一点。
    • 这大概是第一次在网上发一个主动希望同行内推的介绍,如果你的公司有Android方面的招聘,能否内推一下我这个小人物,感谢。

01.可空性

  • 在 Kotlin 中,类型系统区分一个引用是可以容纳 null (可空引用)还是不能容纳(非空引
    用)。 例如,String 类型的常规变量不能指向 null
    var name: String = "yc"
    //编译错误
    //name = null
    
  • 如果希望一个变量可以储存 null 引用,需要显式地在类型名称后面加上问好来标记它:
    var name: String? = "yc"
    name = null
    
  • 问号可以加在任何类型的后面来表示这个类型的变量可以存储 null 引用:Int?、Doubld? 、Long? 等
  • Kotlin 对可空类型的显式支持有助于防止 NullPointerException 导致的异常问题,编译器不允许不对可空变量做 null 检查就直接调用其属性
    fun check(name: String?): Boolean {
        //编译器不允许不对 name 做 null 检查就直接调用其属性
        return name.isNotEmpty()
    }
    
  • 需要显式地进行 null 检查
    fun check(name: String?): Boolean {
        if (name != null) {
            return name.isNotEmpty()
        }
        return false
    }
    

02.安全调用运算符:?.

  • 安全调用运算符:?.
    • 允许把一次 null 检查和一次方法调用合并为一个操作,如果变量值非空,则方法或属性会被调用,否则直接返回 null
  • 例如,以下两种写法是完全等同的:
    fun check(name: String?) {
        if (name != null) {
            println(name.toUpperCase())
        } else {
            println(null)
        }
    }
    
    fun check(name: String?) {
        println(name?.toUpperCase())
    }
    

03.Elvis运算符:?:

  • Elvis 运算符:?:
    • 用于替代 ?. 直接返回默认值 null 的情况,Elvis 运算符接收两个运算数,如果第一个运算数不为 null ,运算结果就是其运算结果值,如果第一个运算数为 null ,运算结果就是第二个运算数
  • 例如,以下两种写法是完全等同的:
    fun check(name: String?) {
        if (name != null) {
            println(name)
        } else {
            println("yc")
        }
    }
    
    fun check(name: String?) {
        println(name ?: "yc")
    }
    

04.安全转换运算符:as?

  • 安全转换运算符:as? 用于把值转换为指定的类型,如果值不适合该类型则返回 null
    fun check(any: Any?) {
        val result = any as? String
        println(result ?: println("is not String"))
    }
    

05.非空断言:!!

  • 非空断言用于把任何值转换为非空类型,如果对 null 值做非空断言,则会抛出异常
    fun main(args: Array<String>) {
        var name: String? = "yc"
        check(name) //7
    
        name = null
        check(name) //KotlinNullPointerException
    }
    
    fun check(name: String?) {
        println(name!!.length)
    }
    

06.let函数说明

  • let 函数可用于在表达式不为 null 时才执行指定代码块
    fun main(args: Array<String>) {
        var name: String? = "yc"
        check(name) //yc
    
        name = null
        check(name) //什么都不会输出
    }
    
    fun check(name: String?) {
        name?.let {
            println(name)
        }
    }
    

07.可空类型的扩展

  • 为可空类型定义扩展函数是一种更强大的处理 null 值的方式,可以允许接收者为 null 的调用,并在该函数中处理 null ,而不是在确保变量不为 null 之后再调用它的方法
    • 例如,如下方法可以被正常调用而不会发生空指针异常
    val name: String? = null
    println(name.isNullOrEmpty()) //true
    
    • isNullOrEmpty() 的方法签名如下所示,可以看到这是为可空类型 CharSequence? 定义的扩展函数,方法中已经处理了方法调用者为 null 的情况
    @kotlin.internal.InlineOnly
    public inline fun CharSequence?.isNullOrEmpty(): Boolean {
        contract {
            returns(false) implies (this@isNullOrEmpty != null)
        }
    
        return this == null || this.length == 0
    }
    

08.Java中判断方式

8.1 防御式编程

  • “防御式编程”大家应该不陌生,核心思想是不信任任何“外部”输入。
    • 不管是真实的用户输入还是其他模块传入的实参,具体点就是各种判空。创建一个方法需要判空,创建一个逻辑块需要判空,甚至自己的代码内部也需要判空(防止对象的回收之类的)。
    public void showToast(Activity activity) {
       if (activity == null) {
           return;
       }
    }
    

8.2 契约式编程

  • 各个模块之间约定好一种规则,大家按照规则来办事,出了问题找没有遵守规则的人负责,这样可以避免大量的判空逻辑。Android 提供了相关的注解以及最基础的检查来协助开发者,示例如下:博客
    public void showToast(@NonNull Activity activity) {
       ......
    }
    
  • 给 Activity 增加了 @NonNull 的注解,就是向所有调用这个方法的人声明了一个约定,调用方应该保证传入的 activity 非空。当然聪明的你应该知道,这是一个很弱的限制,调用方没注意或者不理会这个注解的话,程序就依然还有 NPE 导致的 crash 的风险。

09.kotlin是否解决NPE

  • 有些文章说 Kotlin 帮开发者解决了NPE(NullPointerException),这个说法是不对的。Kotlin没有帮开发者解决了NPE,而是通过在语言层面增加各种强规则,强制开发者去自己处理可能的空指针问题,达到尽量减少(只能减少而无法完全避免)出现 NPE 的目的。

10.kotlin如何约束非空判断

  • 声明阶段
    • 变量需要决定自己是否可为空,比如 private var goodsId: String ?= null,这样就是可接受 null
  • 传递阶段
    • 在变量传递阶段,必须保持“可空性”一致,比如形参声明是不为空的,那么实参必须本身是非空或者转为非空才能正常传递。示例如下:
    private var goodsId: String? = null
    private fun Main(){
        getName(goodsId!!)
    }
    
    private fun getName(name : String){
        Log.i("", "---$name")
    }
    
    • 还有一种方式,在方法中添加?
    private fun Main(){
        getName(goodsId)
    }
    
    private fun getName(name : String?){
        Log.i("", "---$name")
    }
    
  • 使用阶段
    • 在使用阶段,需要严格判空
    var time: Long? = 1000
    
    private fun Main(){
        time!!.toFloat()
        time?.toInt()
    }
    
  • 得出结论
    • 总的来说 Kotlin 为了解决 NPE 做了大量语言层级的强限制,的确可以做到减少 NPE 的发生。但这种既“契约式”(判空)又“防御式”(声明空与非空)的方案会让开发者做更多的工作,会更“麻烦”一点。

11.导致NPE的场景

11.1 方法参数声明非空

  • 比如,请求网络接口,需要传递参数,这种情况下每个字段都可能为空,为了增强逻辑,可以在方法参数上加上"?",可以避免后端处理参数值时抛出空指针异常。博客
    /**
     * 用户登陆
     */
    @POST("user/login")
    fun userLogin(
            @Query("username") userName: String?,
            @Query("password") password: String?
    ): Observable<ResponseBean<LoginBean>>
    

11.2 !! 强行转为非空

  • 当将可空类型赋值给非空类型时,需要有对空类型的判断,确保非空才能赋值(Kotlin 的约束)。使用!! 可以很方便得将“可空”转为“非空”,但可空变量值为 null,则会 crash。
    • 因此使用上建议在确保非空时才用 !!: param!!
    • 否则还是尽量放在判空代码块里:
    param?.let {
       doSomething(it)
    }
    

想换个工作,渴望同行内推我

  • 个人信息
    • 姓名:杨充【26岁】
    • 邮箱:yangchong211@163.com
    • 微信:13667225184
    • GitHub:https://github.com/yangchong211
    • 博客汇总:https://github.com/yangchong211/YCBlogs
    • 干活集中营:Android端技术博客和开源项目审核员
    • 目前工作情况:在职状态
    • 技术项目和博客:GitHub项目7k以上star,follower1.1k以上,发表博客100多篇。
    • 热爱技术:开源项目和博客多次被鸿洋,郭霖,Android技术周刊,干活集中营等等推荐。
    • 学历:武汉软件工程职业学院,大专学历
    • 工作年限:3年多
    • 工作地点:北京
  • 关于近期投递简历一点感想
    • 从进入Android这个行业以来,前两次几乎都是朋友内推,面试机会相对容易,都是一个App一个人做或者两个人做,用户相对来说并不多。这次想着离职,主要是想进入一个较大的平台,大概可以理解为Android端有个至少四五人,可以进行技术交流,渴望自己能够在技术上突破,这就像自己平时独自跑步,和跟着一群跑马拉松的人跑步,那种紧张感肯定是不一样的。
    • 近段时间,尝试着向一些较大的公司投递简历,大概在拉钩上投了15个左右(不喜欢海投),发现绝大多数简历到不了技术那里,就被人事说学历不够,经验不够,工作不匹配等情况回绝。不过也可以理解,看简历无非就是学历和经验,貌似自己的履历是差了一点。
    • 这大概是第一次在网上发一个主动希望同行内推的介绍,如果你的公司有Android方面的招聘,能否内推一下我这个小人物,感谢。

关于其他内容介绍

01.关于博客汇总链接

02.关于我的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341