Android 如何";锁;Kotlin中的静态对象

Android 如何";锁;Kotlin中的静态对象,android,kotlin,Android,Kotlin,嗯,我有一种情况,在a类中,我得到“X数据”。 我想将此“X数据”存储在对象X中一次,然后确保此对象的值不可能更改。(设定一次就忘了它) 我的做法: object X { var attribute1: String var attribute2: String } 显然,由于对象属性是var,它们在将来是可变的。我怎样才能避免这种情况?有没有办法分配值(在某段时间内…),然后锁定对象直到应用程序退出?您可以使用lateinit var attribute1:String告诉编

嗯,我有一种情况,在
a类中,我得到“X数据”。
我想将此“X数据”存储在
对象X
中一次,然后确保此对象的值不可能更改。(设定一次就忘了它)

我的做法:

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

显然,由于对象属性是
var
,它们在将来是可变的。我怎样才能避免这种情况?有没有办法分配值(在某段时间内…),然后锁定对象直到应用程序退出?

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

没有像您所说的那样用
lateinit val
来“锁定”值


有更多信息。

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

没有像您所说的那样用
lateinit val
来“锁定”值


您将获得更多信息。

您可以使用委托属性

class MyProperty<T : Any> {

    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")
    }
}
在上面的示例中,如果在设置值之前尝试访问
myProperty
,则会引发异常,但您可以根据自己的意愿处理该异常(返回默认值?可能为null?)

如果您多次尝试分配该值,也会出现异常,但您可以以不同的方式处理该异常,例如,不再设置该值,以便

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

将打印“foo”

您可以使用委托属性

class MyProperty<T : Any> {

    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")
    }
}
在上面的示例中,如果在设置值之前尝试访问
myProperty
,则会引发异常,但您可以根据自己的意愿处理该异常(返回默认值?可能为null?)

如果您多次尝试分配该值,也会出现异常,但您可以以不同的方式处理该异常,例如,不再设置该值,以便

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

将打印
“foo”

我建议您将var替换为val,使这些属性成为最终属性

var类似于general变量,在kotlin中称为可变变量,可以多次赋值

val类似于常量变量,在kotlin中称为不可变,只能初始化一次


我建议您将var替换为val,使这些属性成为最终属性

var类似于general变量,在kotlin中称为可变变量,可以多次赋值

val类似于常量变量,在kotlin中称为不可变,只能初始化一次


在kotlin中不能
lateinit
不可变属性,并且
lateinit var
不允许自定义设置程序。 因此,我的方法是使用一个backing属性、自定义getter和自定义setter实现lateinit var行为。这与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
}

在kotlin中不能
lateinit
不可变属性,并且
lateinit var
不允许自定义设置程序。 因此,我的方法是使用一个backing属性、自定义getter和自定义setter实现lateinit var行为。这与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)
    }
}

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

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)
    }
}

X会在“X数据”可用之前使用吗?X会在“X数据”可用之前使用吗?此方法的问题在于它是在运行时检查的,而不是在编译时检查的。但是,我认为没有编译时检查方法,除非您使用两个变量-
var
val
,这两个变量在使用
var
时也不会进行编译时检查。您是对的,它是在运行时检查的,但是如果您使用
val
,则无法直接在属性上赋值。您可以使用setter,但一次性赋值属性的所有魔力都消失了then@lelloman我想说,对于在初始化之前进行访问,UninitializedPropertyAccessException更可取。谢谢@PaulGeorgPodlech这更合适indeed@lelloman不幸的是,您的解决方案不适用于可为空的类型。关于这个主题有一个线程和一个解决方案。这个方法的问题是它是在运行时检查的,而不是在编译时检查的。但是,我认为没有编译时检查方法,除非您使用两个变量-
var
val
,这两个变量在使用
var
时也不会进行编译时检查。您是对的,它是在运行时检查的,但是如果您使用
val
,则无法直接在属性上赋值。您可以使用setter,但一次性赋值属性的所有魔力都消失了then@lelloman我想说,对于在初始化之前进行访问,UninitializedPropertyAccessException更可取。谢谢@PaulGeorgPodlech这更合适indeed@lelloman不幸的是,您的解决方案不适用于可为空的类型。有一个关于这个主题的线程和一个解决方案。