I create a Kotlin-class with a class attribute, which I want to initialize in the constructor:
public class TestClass {
private var context : Context? = null // Nullable attribute
public constructor(context : Context) {
this.context = context
}
public fun doSomeVoodoo() {
val text : String = context!!.getString(R.string.abc_action_bar_home_description)
}
}
Unfortunately I have to declare the attribute as Nullable with the "?" sign, although the attribute will be initialized in the constructor. Declaring this attribute as Nullable-attribute makes it always necessary to force an NonNull-value with "!!" or to provide a Null-check with "?".
Is there any way to avoid this, if the class attribute will be initialized in the constructor? I would like to appreciate a solution like this one:
public class TestClass {
private var context : Context // Non-Nullable attribute
public constructor(context : Context) {
this.context = context
}
public fun doSomeVoodoo() {
val text : String = context.getString(R.string.abc_action_bar_home_description)
}
}
As shown by D3xter you have the option of setting it in the constructor. You also have other options. Here they all are...
Create the property within the constructor (as per @D3xter), this is the most common case for simple properties initialized directly by the primary constructor:
You can declare the
val
property and not initialize it, assuming all possible constructors do actually initialize it (as per your second example in the question being asked). This is normal when you have more than one constructor that could initialize a value differently:You can pass in constructor parameters that are not property declarations, and then use those within property initializations. This is common when you have more complex initializations or need to use delegated properties:
Using
lateinit
modifier when you cannot initialize the value during construction, but you are sure it will be done before your first read access. This is common when a dependency injection, IoC container, or something creates an empty version of your class and then initializes it immediately:For
lateinit
the property must currently be avar
and does not work with primitive types.You can also declare a
var
property and not initialize it if you use a delegate designed for that purpose, such asDelegates.notNull()
. This is similar tolateinit
and common when you want avar
that has no initial state, but is set later after construction at unknown point in time:I had a similar problem where I didn't want to hold onto the object after construction. Using
lazy
orlateinit
resulted in inefficient bytecode so after some research I settled on this approach and returned to post the answer in case it helps:Solution
alternatively, the above can be further simplified into:
Decompiled Bytecode
And the decompiled java version of this feels a bit more acceptable than the other approaches and no reference to the context is held after construction:
If the only thing you are doing in the constructor is an assignment, then you could use the Primary Constructor with a private Property.
e.g: