如何在Kotlin中“锁定”静态对象

那么,我有一个情况,在Class A我得到“X数据”。 我想在Object X存储这个“X DATA”一次,然后确保这个对象的值是不可能改变的。 (设置一次,忘记它)。

我的方法是:

 object X { var attribute1: String var attribute2: String } 

显然,由于对象属性是var所以将来可以改变。 我怎么能避免这个? 有没有一种方法来分配值(在一段时间..),然后锁定对象,直到应用程序退出?

你可以使用委托属性

 class MyProperty { private var value: T? = null operator fun getValue(myObject: MyObject, property: KProperty<*>): T = value ?: throw UninitializedPropertyAccessException() operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = when (this.value) { null -> this.value = value else -> throw IllegalAccessException("Property already initialized") } } 

然后在你的对象中使用var

 object MyObject { var myProperty by MyProperty() } 

在上面的示例中,如果您在设置值之前尝试访问myProperty ,则会引发exception,但是您可以根据需要处理该exception(返回默认值?也许是null?)。

如果您尝试多次赋值,您也会遇到exception,但您可以采取不同的处理方式,例如,只需不再设置值即可

 MyObject.myProperty = "foo" MyObject.myProperty = "bar" println(MyObject.myProperty) 

将打印"foo"

您可以使用lateinit var attribute1: String来告诉编译器,在使用attribute1之前,您将管理设置attribute1为非空值。

如你所说,没有像lateinit val “锁定”价值的东西。

文档有更多的信息。

我建议你通过用val替换var来使这些属性最终。

var就像通用variables,它在kotlin中被称为可变variables,可以被分配多次。

val就像常量variables,它在kotlin中被称为不可变的,并且只能被初始化一次。

你不能在kotlin中lateinit不可变的属性,而lateinit var不允许自定义设置器。 所以我的方法是实现后备variables行为与后援财产,自定义getter和自定义setter。 这是lellomans解决方案相当类似的方法。

 object X { private lateinit var backingprop: String var attribute: String set(arg) { if (this::backingprop.isInitialized) throw IllegalAccessException("Property already initialized") backingprop = arg } get() = backingprop } 

我警告你! 但是你可以使用这样的例子:

 object Immutable { val immutableString: String = mutableStaticString ?: "some default value, just in case" } var mutableStaticString: String? = null class App : Application() { override fun onCreate() { super.onCreate() mutableStaticString = "hello duct tape solutions!" android.util.Log.d("ductTape", mutableStaticString) android.util.Log.d("ductTape", Immutable.immutableString) } } 

我建议创建一个简单的不可变data类:

 data class X(val a: String, val b: String) 

像这样创建在A

 X(“first”, “second”) 

A创建的这个X实例应该被分配给该实例A的成员属性。 您可以将其包装到companion object中,以静态方式访问:

 class A { companion object { lateinit var x: X fun initX() { x = X("first", "second") } } } //usage example A1.initX() println(A1.x)