一个kotlin的Smart cast导致的编译问题

前言

一篇库存文章,感觉再不发的话马上就要发霉了

问题

之前在写代码的时候遇到个蛮有意思的编译问题,感觉可以拿出来分享一下,首先先看一段简单的代码

有个函数,代码总共就没几行,定义了一个局部变量temp,然后让这个temprepeat函数内执行加0.3并且打印出减去0.3后的结果,看起来代码没啥问题,抛开具体的执行结果,我们来编译一下这段代码看看

很奇怪的现象发生了,居然来了个编译报错,说的是无法进行智能转换,局部变量temp被一个可变的闭包结构捕获了,这个我就不乐意了,捕获了又咋样呢,影响你啥了就给我报个错,实在没啥头绪,只好先问问Gemini它有什么办法

分析

Gemini说,kotlin编译器无法保证一个可空的可变变量在一个闭包结构内进行修改以及访问,因为在这期间可能会被其他线程或者异步回调修改为null,就算代码看起来是同步执行的,但是编译器为了防止这个潜在的安全性问题,还是会阻止编译顺利通过,所以才报错,话虽这么说,但是不得不吐槽一下,编译器你要不要这么含蓄,有错咱就标红吗,常见的一些编译器报错,都会在相关代码上有一根红线,可以在红线的位置得到对应的报错信息

类似于上面这种代码,有错误立马就能看到,而不会像我们今天举的这个智能转换的例子,必须得在编译期间才会抛出问题,如果是小项目也就算了,但是如果换成一个大项目,随便编译一下就要花个几分钟,结果包没出来,看到一堆红字,影响效率的同时心情也不美丽,吐槽完了,那么这种问题该如何解决呢?很简单

使用空安全符?

虽然加上空安全符后会有提示说这个安全符可以不加,但忽略就好

使用let函数

一个意思,就是多加一层非空的判断,这样就能阻止在闭包结构内对局部变量进行智能转换而引发的编译问题

升级kotlin版本至2.0

这个问题kotlin官方也给出了答复,有人提了一个issue,而kotlin也认定这是一个bug,最终在2.0版本已经修复了,如果条件允许,可以将项目的kotlin版本升级至2.0版本,这样这个编译问题自动就会消失

换个例子

上述例子过于简单,可能有人会觉得实际场景中不太会遇到这种问题,那么我们看看下面这段代码

这个例子就跟我遇到的问题比较相似了,首先有个类CoffeeHolder,内部有一个静态内部类InnerHolder,在InnerHolder内部只有一个挂起函数runJob,这个时候有一个函数,它接收InnerHolder作为参数,并且在内部执行了runJob操作

最后在Activity中,有个函数runHolder执行了testHolder,代码如下

有了文章前半部分的介绍,我们现在可以立马知道这段代码不会编译通过的,在闭包(协程)中对局部变量holder进行了修改也就是赋值,随后在testHoldr中访问,编译报错的地方也就是testHolder所在的一行

解决办法就如上面提到的那样,给holder添加上空安全符或者其他非空判断才行

最后

如果有谁也遇到过这种,编辑器本身不会报错,但是在编译的过程中会报错的代码,欢迎在评论区分享

相关推荐
萧行之1 小时前
可视化技术复盘:从图形语法看 D3、Vega-Lite、ECharts、Observable Plot
前端·学习·数据可视化
157092511348 小时前
Android进阶之光:HTTP协议原理深度解析
android·网络协议·http
终端安全笔记9 小时前
安卓五品牌通道差在哪:监管通道拆解
android
尾善爱看海9 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
v_34836087629 小时前
Android native端 堆栈打印
android·算法
一笑的小酒馆10 小时前
AndroidKMP之导航和WebView
android
驳是10 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea10 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持10 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者10 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc