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

前言

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

问题

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

有个函数,代码总共就没几行,定义了一个局部变量temp,然后让这个temp在repeat函数内执行加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添加上空安全符或者其他非空判断才行

最后

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

相关推荐
变与不变8067 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半7 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck7 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.7 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子7 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常7 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常7 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋8 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
警醒与鞭策8 小时前
Codex桌面版与Claude桌面版使用设置
android·unity·ai·性能优化
鸿蒙开发9 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos