[[ Null ]] ⇣
Kotlin prevents you from assigning a null value to a variable of a non-nullable type. If you want a value to be nullable, you must explicitly opt-in.
To mark the type as nullable, place a question mark after the name of the type, like String?.
How to work with the possibility of null
Checking for null with if/else statement
if(quest != null){
// Safe to use `quest`
println(quest.showQuest())
}Using the safe call operator (?.)
val theQuest = quest?.showQuest()
if(theQuest != null){
println(theQuest)
}
// Using `let`
val theQuest = quest?.showQuest()
theQuest.let {
println(theQuest)
}
// using `it` default param
quest?.showQuest()?.let { println(it) }
// same as => .let { theQuest -> println(theQuest) }Using non-null assertion operator (!!)
There are situations where using the double-bang operator is appropriate. Perhaps you do not have control over the type of a variable, but you are sure that it will never be null. As long as you are confident that the variable you are using will not be null when you use it, then !! is an option.
val playerLevel = readLine()? // using safe call operator
.toIntOrNull() // casting the string from stdin
?: 0 // Using the Elvis Operator
// ^ If left hand is null, use the right hand[[ Exceptions ]] ⇣
Throwing an exception
Kotlin allows you to manually signal that an exception has occurred.
private fun obtainQuest(
// ...
): String? {
if (playerLevel <= 0) {
throw IllegalArgumentException(
"level must be at least 1"
)
}
// ..
}Handling exceptions
Kotlin allows handling exceptions by the usage of try/catch.
try {
// some code
} catch (e: Exception) {
// handler
} finally {
// optional finally block
}
// `try` is an expression
val a: Int? = try {
input.toInt()
} catch (e: NumberFormatException) {
null
}Preconditions
These functions allow us to define preconditions that must be true before executing some code.
// before:
if (playerLevel <= 0) {
throw IllegalArgumentException(
"level must be at least 1"
)
}
// using the `require` precondition function
require(playerLevel > 0) { // condition
"level must be at least 1"
// ^ Throws an `IllegalArgumentException` if the condition is false.
}| Function | Description |
|---|---|
| check | Throws an IllegalStateException if the argument is false. |
| checkNotNull | Throws an IllegalStateException if the argument is null. Otherwise returns the non-null value. |
| require | Throws an IllegalArgumentException if the argument is false |
| requireNotNull | Throws an IllegalArgumentException if the argument is null, Otherwise returns the non-null value. |
| error | Throws an IllegalArgumentException with a provided message if the argument is null. Otherwise returns the non-value. |
| assert | Throws an AssertionError if the argument is false and the
assertion compiler flag is enabled |
💡 Prefer
IllegalArgumentExceptionwhen you are checking input to a function andIllegalStateExceptionfor most other scenarios.
Defining a custom exception
class InvalidPlayerLevelException() :
IllegalArgumentException("Invalid player level")
// throw the custom exception
throw InvalidPlayerLevelException()