在Kotlin中,修饰符const val仅用于文件级的编译时常量,或者在对象(object)和伴随对象中声明。 在类内部声明为val的属性成为普通的最终属性,没有静态初始化。 重要的特点是:const val不能被继承,而val可以被重写(如果允许)。
常量(const val)不能是抽象的,因为它们必须在编译时具有值。 普通的val通过开放属性允许在层次结构中实现常量模式,然而在运行时,它们将通过getter可用,这与Java中的编译不同。
open class Base { open val info: String = "base" } class Child : Base() { override val info = "child" } object Constants { const val APPLICATION_NAME = "MyApp" }
可以在接口或抽象类中声明
const val,然后重写/继承它吗?
不可以。 在Kotlin中,不能在接口或抽象类中声明const val——这仅允许在对象(object)和顶层。 没有可供继承的类似static final变量。
interface Foo { // const val X = "constant" // 编译错误:const 'val'仅允许在顶层、对象或伴随对象中 }
故事
团队试图通过在多个Android模块中通过继承接口重用字符串常量,将它们声明为
const val——结果收到编译错误,并被迫将常量移动到顶层,从而恶化了封装性。
故事
在项目中将所有Java static final字段转换为Kotlin的
val字段在开放类中,期望相同的行为(编译时常量),但它们成为了普通的属性,有getter。 结果,访问时间增加,这对微服务应用程序的热路径产生了负面影响。
故事
在将Java的常量容器类迁移到Kotlin时,开发人员在伴随对象中创建了常量,但在Java代码中遇到了访问问题:常量被视为伴随对象本身的字段,而不是类的字段,这导致API混淆和额外的互操作性错误。