Throwing and Custom Exceptions

throw and Custom Exception Classes

Example

Create your own exception types by extending Exception (or a more specific class). throw is an expression of type Nothing, so it can be used with ?:.

class InsufficientBalanceException(val needed: Double) :
    Exception("Insufficient balance: need ${needed} more")

class Account(var balance: Double) {
    fun withdraw(amount: Double) {
        if (amount > balance) throw InsufficientBalanceException(amount - balance)
        balance -= amount
    }
}

fun findUser(id: Int): String? = if (id == 1) "Asha" else null

fun main() {
    val acc = Account(1000.0)
    try {
        acc.withdraw(400.0)
        acc.withdraw(800.0)
    } catch (e: InsufficientBalanceException) {
        println(e.message)
        println("Shortfall: ${e.needed}")
    }

    try {
        val name = findUser(2) ?: throw IllegalArgumentException("User 2 not found")
        println(name)
    } catch (e: IllegalArgumentException) {
        println("Error: ${e.message}")
    }
}

Output

Insufficient balance: need 200.0 more
Shortfall: 200.0
Error: User 2 not found

require, check and error

The standard library has short helpers for common checks:

FunctionThrowsUse for
require(cond) { msg }IllegalArgumentExceptionvalidating function arguments
requireNotNull(x) { msg }IllegalArgumentExceptionargument must not be null
check(cond) { msg }IllegalStateExceptionvalidating object state
error(msg)IllegalStateExceptionunreachable / impossible situation

Example

class Player {
    var started = false
    fun play(song: String) {
        check(started) { "Call start() before play()" }
        println("Playing $song")
    }
}

fun setVolume(level: Int) {
    require(level in 0..100) { "Volume must be 0-100, was $level" }
    println("Volume set to $level")
}

fun main() {
    setVolume(70)
    try { setVolume(150) } catch (e: IllegalArgumentException) { println(e.message) }
    try { Player().play("Naatu Naatu") } catch (e: IllegalStateException) { println(e.message) }
}

Output

Volume set to 70
Volume must be 0-100, was 150
Call start() before play()