在程序里避开踩雷:安全引用空虚值、例外处理和延後、惰性初始化 Null Safety, Exception, lateinit, lazy

「哇,原来研究室是这样的啊。」诗忆东张西望。

「是呀,这里是大家办公的地方,实验的机器不在这里,所以你可以放心坐下来。」唯心拉开身边的椅子,回头继续写报告。

诗忆下午的时间有空堂,想要找个安静的地方自习,但系计中(系上的计算机中心,提供多台公共电脑和舒适的冷气)和图书馆都人满为患,回寝室又太远。於是传讯息问学姐还有没有适合的地方,没想到学姐回答可以去她的研究室。

诗忆坐下後,拿出笔电开始研究讲义上的Nullable范例,她在宣告变数的类别後面加上问号。

fun main() {
    var drink : Drink?
    println(drink)
}

IDE马上吐出红字错误Variable 'drink' must be initialized

「你忘记初始化了。」唯心几乎是和IDE同时反应。

「喔,学姐你有在看啊。」诗忆害羞地用手指搔搔脸。「我可以顺便问问这个字怎麽发音吗?」

null在台湾还满盛行念成『怒喔』,但如果要和英美人士交流的话,音标是『nʌl』,发音接近NO。基本上沟通就是要让对方听懂,所以建议两种念法都记下来。null是一个特殊的值,当变数被设定成null这个空虚值,就代表这个变数失去原类别的所有能力,只剩下Any支援的函式,被扔在记忆体hashCode为0的位置,所有的null变数都是被扔在那,所以通常是拿来解放原本占据的记忆体的。所以?.後面的函式和属性只在变数非null的时候才会去呼叫。」唯心一边帮她修正程序一边说。

fun main() {
    var drink : Drink? = null
    println(drink)
    println(drink?.name)
}

IDE这次没有红字,印出两行null

「不能延後初始化吗?」诗忆问。

唯心注意到萤幕的脏污,拿出拭镜布擦乾净了才回答。

「可以,不过valvar延後初始化的方法不同唷,var是在前面加上lateinitval是在後面加上by lazy。意义上不太一样,lateinit是希望开发者能自发在用到这个变数前初始化,如果在用到变数时还是没有初始化的话就会抛出UninitializedPropertyAccessException错误;而by lazy则事先准备好初始化的方法,程序会在用到变数的前一刻才初始化。」

fun main() {
    lateinit var drink : Drink
    drink = Drink("奶茶", 50)
    println(drink)
}
fun main() {
    val drink : Drink by lazy {
        println("initial")
    	Drink("奶茶", 50)//初始化的部分要放在lazy里的最後一行唷
    }
    println(drink)
}

「之前练习四则运算的时候就想问,Exception到底是什麽啊?」

唯心乾脆盖上笔电,专心回答诗忆。

throw Exception归属於Nothing类别,是一种中断程序、放置安全闸的手段,比如说,程序还没设计完的时候通常会放个TODO,如果有谁不小心呼叫了这个未完成的地方,就会收到错误。之前的四则运算则是挡住不支援的字元符号,而有些Exception是系统抛出的,可以的话尽量不要踩到那些坑,像是很有名的NPE指的就是NullPointerException,当程序企图操作已经null化的变数就会引爆。因为Kotlin有预先检查,相对於同生态系的Java程序语言来说Null Safety程度比较高,但是也因为同生态系内的程序语言可以互相使用对方的函式库,所以还是有可能踩到对方的坑。不过,也不能说Kotlin自己就不会发生NullPointerException,如果刻意呼叫throw NullPointerException或是使用!!无视null状态,会爆炸的还是会爆炸。」

fun 饮料优惠活动() {
    TODO("总有一天要完成")
}

fun notSupport(char: Char): Nothing {
    throw IllegalArgumentException("Not Support ${char}!")
}

fun main() {
    var drink : Drink? = null
    println(drink)
    println(drink!!.name)//会爆炸
}

「遇到Exception只能爆炸吗?不会吧?」诗忆怀疑。

唯心点头。「如你猜测的,对於在预期中可以包容的Exception,能用try-catch包起来不让它爆炸。」

fun main() {
    try {
        notSupport('#')
    } catch (e: IllegalArgumentException) {
        println(e.message)
    }
}

程序顺利执行,印出一般颜色的Not Support #!


<<:  Day10 分页与分段的记忆体管理

>>:  【Docker 攻略】MySQL 安装篇 | 安装资料库 好快的说 !

Day30完赛心得!

完赛心得感想 老实说会参加这个比赛其实有一个原因是学校要求的门槛是要参加比赛XD 但30天铁人赛确实...

[Day7]-进阶for回圈

巢状回圈 所谓的巢状回圈,就是一个回圈里还有另一个回圈,两者变数尽量不要相同以免搞混 Break指...

24.unity对话处理(List与class)

今天要做的事情就是让系统可以分辨 哪段文字=角色,哪段文字=心情,哪段文字=对话内容! 进行文字标记...

【DAY 4】 Power Automate 简介 + 订便当系统

哈罗大家好~ 今天要简单说明 “ Power Automate “ 这个强大的流程引擎以及示范一个用...

Day00 前言与目录

每天整理一个程序知识点, 让自己建立笔记习惯。 本业缘故内容以前端为主, 但只要跟网路程序数位相关的...