When writing code in Kotlin, you may encounter an error called
“Null can not be a value of a non-null type”.
This error occurs when you try to assign null to a variable, argument,
or other value whose type does not allow null.
In Kotlin, types that allow null and types that do not allow null
are clearly distinguished, so when migrating from Java or another language
to Kotlin, the handling of null may cause errors.
This article introduces the main causes to check and basic solutions
when “Null can not be a value of a non-null type” appears in Kotlin.
- What Is “Null can not be a value of a non-null type”?
- Difference Between String and String?
- Cause 1: Assigning Null to a Non-Null Variable
- Cause 2: Assigning Null to Other Types Such as Int or Boolean
- Cause 3: The Function Argument Is a Non-Null Type
- Cause 4: Specifying Null as a Function Return Value
- Cause 5: Using Null as an Initial Value
- Using lateinit
- Cause 6: Assigning a Nullable Value to a Non-Null Type
- Specifying an Initial Value with the Elvis Operator
- Performing a Null Check
- Using the Safe Call Operator “?.”
- Forcibly Treating a Value as Non-Null with “!!”
- When It Occurs in Android Development
- When Receiving Values from Java Code or Libraries
- Making Everything Nullable Is Not Always the Right Solution
- Order of Checks When “Null can not be a value of a non-null type” Appears
- Check the Specific Error Location
- Summary
What Is “Null can not be a value of a non-null type”?
“Null can not be a value of a non-null type” is an error indicating
that null has been specified for a type that cannot store null.
For example, suppose you have the following code.
val name: String = null
In this code,
name is defined as a
String type.
Kotlin’s String type cannot store null as it is.
Therefore, attempting to assign null results in the
“Null can not be a value of a non-null type” error.
In Kotlin, types that do not allow null are distinguished as non-null types,
while types that allow null are distinguished as nullable types.
If there is a possibility of handling null,
it is important to understand this difference.
Difference Between String and String?
In Kotlin,
String and
String? are treated as different types.
val name: String = "Taro"
Because String does not allow null,
it must always contain a String value.
On the other hand, adding
? after the type name
makes it a nullable type that allows null.
val name: String? = null
In this case,
null can be assigned to name.
Cause 1: Assigning Null to a Non-Null Variable
The most straightforward cause is directly assigning null
to a variable that does not allow null.
var message: String = null
Because String is a non-null type,
null cannot be assigned to it.
If you need to store null,
change it to a nullable type.
var message: String? = null
If null is not necessary,
specify an appropriate String value as the initial value.
var message: String = ""
Cause 2: Assigning Null to Other Types Such as Int or Boolean
Restrictions related to null are not limited to String.
Int, Long, Double, Boolean, and other types also cannot store null
unless ? is added.
val number: Int = null
val enabled: Boolean = null
If you need to allow null,
define them as nullable types as follows.
val number: Int? = null
val enabled: Boolean? = null
There is no need to make values nullable if they have no possibility
of storing null.
It is important to determine the type after checking
whether the null state is actually necessary.
Cause 3: The Function Argument Is a Non-Null Type
An error also occurs when null is passed as a function argument
if the argument is a non-null type.
fun showMessage(message: String) {
println(message)
}
showMessage(null)
The argument of showMessage() is a
String type,
so null cannot be passed to it.
If the function needs to accept null,
change the argument to a nullable type.
fun showMessage(message: String?) {
println(message)
}
showMessage(null)
On the other hand, if the function does not need to accept null
by design, pass a value other than null from the calling side.
Cause 4: Specifying Null as a Function Return Value
If a function’s return value is defined as a non-null type,
returning null results in an error.
fun getName(): String {
return null
}
Because this function is defined to return a String type,
it cannot return null.
If there is a possibility that null will be returned,
make the return type nullable.
fun getName(): String? {
return null
}
If there is no need to return null,
modify the process so that it returns a String value.
Cause 5: Using Null as an Initial Value
If you try to initialize a variable that you plan to assign a value to later
by temporarily setting it to null,
an error occurs if it is a non-null type.
var userName: String = null
userName = "Taro"
If you use null as the initial value,
make the variable nullable.
var userName: String? = null
userName = "Taro"
However, if it is a property that will definitely be assigned a value later,
a method other than making it nullable may be more appropriate.
Using lateinit
For class properties and similar values that cannot be specified
at initialization but will definitely be assigned a value before use,
lateinit may be used.
lateinit var userName: String
fun setup() {
userName = "Taro"
}
With this method,
there is no need to specify null as the initial value.
If a property declared with lateinit is used
before a value is assigned to it, an exception occurs.
Use it when the property is guaranteed to be initialized before use.
Cause 6: Assigning a Nullable Value to a Non-Null Type
Even if null is not written directly,
assigning a value that may be null to a non-null type
results in an error due to a type mismatch.
val text: String? = null
val message: String = text
Because text is
String?,
it may be null.
Therefore, it cannot be directly assigned to
String, which does not allow null.
Specifying an Initial Value with the Elvis Operator
If you want to use another value when a nullable value is null,
you can use the Elvis operator
?:.
val text: String? = null
val message: String = text ?: "Default"
In this case,
if text is not null, its value is used,
and if it is null,
"Default" is used.
Therefore,
message always contains a String value.
Performing a Null Check
When using a nullable value,
you can check that it is not null before processing it.
val text: String? = "Hello"
if (text != null) {
println(text.length)
}
Within a scope where
text != null is true,
Kotlin may be able to treat text as a non-null value.
Using the Safe Call Operator “?.”
When accessing properties or functions of a nullable object,
you can use the safe call operator
?..
val text: String? = null
println(text?.length)
If text is null,
length is not accessed,
and the result of the entire expression becomes null.
If it is not null,
length is obtained as usual.
Forcibly Treating a Value as Non-Null with “!!”
Kotlin has the
!! operator,
which forcibly treats a nullable value as non-null.
val text: String? = "Hello"
val message: String = text!!
In this code,
text is forcibly treated as a String type.
However, if the actual value is null,
an exception occurs at runtime.
!! may make it easy to avoid a compilation error,
but it does not guarantee safety if the value is null.
First consider whether the situation can be handled
with a null check, safe call, or Elvis operator.
When It Occurs in Android Development
In Android apps,
there are many situations where values that may be null are handled,
such as data obtained from Intent, Bundle, View, and APIs.
For example, when retrieving a string from an Intent,
the return value may be a nullable type.
val name: String? = intent.getStringExtra("name")
If you try to directly assign this value to a non-null type,
you need to consider the possibility of null.
val name: String = intent.getStringExtra("name") ?: ""
In this example,
an empty string is used if the value cannot be obtained.
When Receiving Values from Java Code or Libraries
When using Java code or libraries written in Java from Kotlin,
you need to be careful about how null is handled.
Because Java does not distinguish as clearly as Kotlin
at the type level whether null is allowed,
values received from Java may be null.
When using values obtained from external APIs or libraries,
check the return value specifications
and perform a null check if necessary.
Making Everything Nullable Is Not Always the Right Solution
When “Null can not be a value of a non-null type” is displayed,
adding
? after the type may resolve the error.
var name: String? = null
However,
if all variables are made nullable,
you need to consider null every time those values are used.
Keeping values that should always exist as non-null types
and making only values that actually require a null state nullable
makes the intent of the code clearer.
Rather than adding ? only to eliminate the error,
determine the type by considering whether the variable actually needs
a state in which “no value exists”.
Order of Checks When “Null can not be a value of a non-null type” Appears
If you do not know the cause,
checking the following items in order
can make it easier to isolate the problem.
- Check the type of the variable to which null is being assigned.
- Check whether
?is added after the type. - Check whether the variable actually needs null.
- Check the types of function arguments and return values.
- Check whether a nullable value is being assigned to a non-null type.
- Check whether an initial value can be specified with the Elvis operator.
- Check whether the situation can be handled with a null check or safe call.
- If the property is initialized later, check whether
lateinitis appropriate. - Check whether
!!is being used to forcibly avoid the problem. - Check whether return values from Android APIs or external libraries are nullable.
Check the Specific Error Location
When resolving “Null can not be a value of a non-null type”,
it is important to check not only where null is specified,
but also how that value is defined in terms of its type.
Example:
val name: String = null
→ Change to String? if null is required
fun getName(): String {
return null
}
→ Change the return type to String? if null is returned
val text: String? = null
val message: String = text
→ Consider a null check or the Elvis operator
val name: String = intent.getStringExtra("name")
→ Check whether the return value may be null
Summary
Kotlin’s
“Null can not be a value of a non-null type”
is an error that occurs when null is specified
for a type that does not allow null.
In Kotlin,
types that allow null and types that do not allow null
are clearly distinguished, such as
String and
String?.
When the error is displayed,
first check whether the relevant variable,
function argument, return value, or other value
is a nullable type or a non-null type.
If a null state is necessary,
add ? to make the type nullable,
and if null is unnecessary,
set an appropriate initial value or other value.
Also, when retrieving a value from a nullable type,
you can write safe processing that takes null into account
by using null checks,
the safe call operator ?.,
the Elvis operator ?:,
and similar methods.
Rather than making everything nullable simply to eliminate the error
or frequently using !!,
it is important to check whether the value can actually be null
and select the appropriate type.
