如何判断Val的取值是编译期确定还是运行期确定?
判断val取值为编译期已知/运行期已知的实操方法
语法层面初步判定
Kotlin中只有满足以下所有条件的val才属于语法层面的编译期常量:
- 被
const关键字修饰 - 定义在顶层作用域,或是伴生对象/object类的成员
- 赋值为原始类型、String的字面量,或是其他编译期常量表达式
不符合上述条件的val,哪怕赋值的是原始类型或String字面量,也属于运行期才能确定取值的变量。
IDE校验方法
- 尝试将目标val作为注解参数使用:注解参数强制要求传入编译期常量,如果IDE没有报错,说明该val是编译期已知的,反之则是运行期确定
- IntelliJ IDEA可开启常量表达式高亮:在设置中搜索「常量表达式」,开启高亮选项后,所有编译期可确定的常量表达式会被特殊标记,肉眼可直接区分
- 尝试给目标val添加
const修饰符:如果IDE没有抛出「Const 'val' should have a constant initializer」错误,说明该val的取值编译期可确定,否则为运行期确定
反编译/字节码验证方法
- 用IDEA自带工具验证:右键目标Kotlin类文件,选择「Show Kotlin Bytecode」,再点击面板上的「Decompile」查看反编译后的Java代码:
- 如果是编译期常量,反编译结果中会出现
public static final的常量定义,所有引用该val的地方会直接替换为字面量,不会调用生成的getter方法 - 如果是运行期确定的val,反编译结果中会存在对应的getter方法,所有引用位置都会调用getter取值
- 如果是编译期常量,反编译结果中会出现
- 也可以编译生成class文件后,执行
javap -c 类名.class命令查看字节码:编译期常量会在类的ConstantValue属性中定义,调用位置直接嵌入字面量,无getter调用逻辑
内容的提问来源于stack exchange,提问作者Chia Hao Yu
相关产品推荐
相关产品推荐

