4 minutes read

You already know what an exception is and how it can occur and crash your program. Also, you know how to understand where an exception happened. In this topic, we're going to discuss other types of exceptions and a way to prevent them. Moreover, we'll learn a way to produce exceptions ourselves.

Another type of exceptions

Consider the following code:

fun calculateSpentMoney(total: Int, itemPrice: Int): Int {
    val amountToBuy = total / itemPrice
    return amountToBuy * itemPrice
}

This function can be used in the following situation. Let's imagine you want to calculate how much you will spend if you buy a maximum number of hamburgers whose price is itemPrice and you have total money. How will the function work? For example, itemPrice is $2 and you have $37 in total. The function will return 36.

Don't you see a problem here? We do: what if items are free? Some candies for tasting at a chocolate factory? We are definitely grabbing many of them and not spending a cent!

However, the function isn't ready for free stuff... If we call it like calculateSpentMoney(37, 0), it will produce an ArithmeticException with the / by zero message.

A way to fix

No need to worry: in many cases, we can prevent exceptions. We just need to decide which cases are problematic. Here, when items are free, the function should return 0, but it crashes.

Actually, we've just formulated our special case. So, let's handle this situation by simply adding a condition:

fun calculateSpentMoney(total: Int, itemPrice: Int): Int {
    if (itemPrice == 0) {
        return 0
    }
    val amountToBuy = total / itemPrice
    return amountToBuy * itemPrice
}

This was an example of preventing your code from a crash: we predicted an edge case.

Remember: in many cases, you can avoid exceptions using conditions. So think about special cases in your program and add checks.

Throwing exceptions

We know one more special case of input data for our function: negative numbers. The function doesn't crash, but the results are useless.

Let's list special cases:

  • we can't have a negative amount of cash in our pockets,

  • if an item price is negative, we can take all the items, but we don't know how many there are.

In both cases, there are no sensible results the function can return. If we return, for example, 0, we will suppress an error quietly.

So we are producing an exception ourselves! In Kotlin, there is the throw keyword to do this. Just put an exception object after the word, and it will happen:

fun calculateSpentMoney(total: Int, itemPrice: Int): Int {
    if (total < 0) {
        throw Exception("Total can't be negative")
    }
    if (itemPrice < 0) {
        throw Exception("Item price can't be negative")
    }
    if (itemPrice == 0) {
        return 0
    }
    val amountToBuy = total / itemPrice
    return amountToBuy * itemPrice
}

For example, if somebody calls this function like calculateSpentMoney(-10, 4), the first condition is true, and the program crashes with the provided exception message.

Why should we write Exception(...)? That's the right question! Actually, all exceptions are located in a hierarchy tree. In this way, Exception represents a common type without any specifics. There are other, more specific types, like ArithmeticException and NumberFormatException. They help to better define what exactly happened. However, these types of exceptions are beyond the current topic. We will devote another topic to the hierarchy overview, and you will learn more about other exception types.

Don't forget that an exception is an object, so you can put it into a variable: val countError = Exception("Number is too big"). If you do this, the program won't crash. It will crash only when you do something like throw countError.

Remember that when we throw an exception the return type is Nothing.

fun makeAnException(): Nothing {
    throw Exception("I'm an exception!")
}

Conclusion

Now you know some other types of exceptions and how to produce your own. All in all, the main fact here is that there can be situations when you can avoid an exception and situations when you better produce an exception manually.

530 learners liked this piece of theory. 8 didn't like it. What about you?
Report a typo