The Programmers Guide To Kotlin - Exceptions
Written by Mike James   
Thursday, 30 July 2020
Article Index
The Programmers Guide To Kotlin - Exceptions
Finally

Kotlin has exceptions - but what do you do with them? In this extract from The Programmers Guide To Kotlin by Mike James, we look at and its approach to exceptions and how to work with them.

Programmer's Guide To Kotlin

Now Available as a Print Book

cover

You can buy it from: Amazon

Contents

Some Chapters Already Available On The Web

  1. What makes Kotlin Special (Book Only)
  2. The Basics: Variables, Primitive Types and Functions
  3. Control
  4. Strings and Arrays
  5. The Class & The Object
  6. Inheritance
  7. The Type Hierarchy 
            Extract  Type and its problems
            Extract  Smart Casts
  8. Generics
            Extract Basic Generics
            Extract Covariance & Contravariance
  9. Collections, Iterators, Sequences & Ranges
            Extract     Collections
            Extract Iterators & Sequences
  10. Advanced functions 
  11. Anonymous, Lamdas & Inline Functions
            Extract    Annoymous and Lambda Functions
            ExtractInline Functions
  12. Data classes, enums and destructuring
            Extract  Data Classes
            Extract      Enums & Sealed Classes 
            Extract 
         Delegated Properties 
            Extract      Destructuring  **NEW!**
  13. Exceptions, Annotations & Reflection
            Extract Exceptions
            Extract Annotation & Reflection 
  14. Working with Java
            Extract Using Swing  

Exceptions are a way of dealing with “out of band” behavior and could almost be considered to be part of metaprogramming. All three qualify for the status of something that you tackle when you have become completely comfortable with the main features of Kotlin.

Exceptions

Exceptions in Kotlin work in the way that they do in most modern languages, and of course Java. There are some interesting differences, however.

An exception is an error or a fault condition that is difficult to test for before it happens, but it has to be admitted that many exceptions are simply excuses not to test for the error.
For example, division by zero is an error that can usually be tested for beforehand:

if(b!=0) result=a/b

but in most cases it is treated an exception to the normal flow of control within the program.

The whole idea of exception handling is that it can provide a sort of alternative flow of control for your code so that you can express your algorithm in two clear parts – one for what happens when everything works, and another for what happens when there is a problem.

Exceptions also allow you to unwind the call stack to get back to an earlier condition that represents things before the error occurred so that you can have another attempt.

In Kotlin and Java exceptions are handled using a try-catch block:

try{
    var result=a/b
}
catch(e:ArithmeticException){     println(e) }

The statements within the try block are executed and control passes out of the try-catch to the next instruction if everything works.

If there is a problem while the program is running, then an exception is thrown and the catch blocks are checked in the order they occur for one that matches the type of the exception object. Exceptions "throw" an exception object and all exception objects are descended from Throwable.

Which exception a catch block handles is determined by the type of the catch parameter. If the exception object is of that type or a subtype then the catch block is executed and the program continues after the try-catch block.

There can be multiple catch blocks after a try and each one can handle a different possible exception. In this way the catch blocks form a multi-way selection, with the same form as a when, for what is to happen based on the type of the thrown object.

Notice that unlike Java, Kotlin doesn't currently support multi-catch expressions. That is, you can't use a single catch to handle more than one type of exception if they are not derived classes.

If the exception is unhandled, i.e. there is no catch block, then a return is executed and the next function up the call stack is checked for an exception handler that accepts the exception. If one is not found a return is executed and the search for an exception handler continues. Eventually the top level is reached and if no exception handler is found the program halts with a run-time exception which is reported to the user. This unwinding of the call stack is the reason that an exception can get back to an early part of the program that can try the task again or give better error information to the user.

For example, if we define a function to do the division:

fun div(a:Int,b:Int):Int=a/b

and call it from within a try-catch block:

try{
    div(1,0)
}
catch(e:ArithmeticException){     println(e) }

Then the exception occurs in the div function, but because it is unhandled it is passed up to the main program which does handle it.



Last Updated ( Monday, 03 August 2020 )