Skip to content

JA4. Generic And Exception Handling

Statement

Reflecting upon the following resources, explain the concept of generics and exception handling in Kotlin for both.

Solution

Generics are a way to make classes and functions more usable, that is, doing the same operations on its content regardless of their type. For example a generic listOf() function will do the same operations wether you put strings, numbers, or Users in it (assuming User is a custom type); and the items in the list should be of the same type.

The problem is that Kotlin is staticky typed, and the compiler tries to infer types of elements; but it may not always be accurate so you can specify the type of the elements in the list using generics.

When the system infers a type as Any (which is the implicit parent of all types), you can specify the type of the elements in the list using generics.

The advantages of generics that they provide type safety, and reduce the need for type casting (as you do the casting once at the definition of the generic class or function, and not every time you use it). Finally, generics allows for more compile time checking, and leave less room for runtime errors.

The syntax for generics is to put the type in angle brackets after the class name, and use the type as a normal type in the class or function.

class MyGenericPrinter<T> {
    private var value : T? = null
    fun set(value: T) { this.value = value }
    fun get() : T? = value
    fun print() { println(value) }
}

// main.kt
fun main() {
    val intPrinter = MyGenericPrinter<Int>() // define printer for Int
    val stringPrinter = MyGenericPrinter<String>() // define printer for String

    intPrinter.set(5) // set value to 5
    stringPrinter.set("Hello") // set value to "Hello"
    intPrinter.print() //5
    stringPrinter.print() //Hello

    intPrinter.set("Hello") // error: type mismatch (expected Int, found String)

}

Exceptions are interrupts that indicate that the program went a wrong path, and the program itself can not decide where to go next and decides to crash. You as programmer should be prepared for such emergencies, and handle them gracefully.

Gracefully means that you have received the exception, and defines an alternative path to be followed to get the best user experience. For example, upon entering the wrong email or password on a Login screen, the app should not crash, but rather display a message to the user that the email or password is wrong, and allow them to try again.

Technically, the Exception class is the base of all Errors; all application, libraries errors extends this class. You can also define your own exceptions by extending the Exception class. In java, however, Exceptions and Errors extend the Throwable class.

The syntax is to put the block that may throw an exception in a try block, and the alternative path in a catch block. The catch block can have multiple catch blocks, each handling a different type of exception. The finally block is optional, and is executed regardless of whether an exception is thrown or not.

The Exception class has a message property that you can use to get the message of the exception, and a printStackTrace() function that prints the stack trace of the exception.

try {
   //code that code potentially throw and exception
 } catch(e: Some_Exception) {
   //code to handle if this exception is occurred
 } catch(e: Exception) {
   //you can have multiple catch blocks
   //code to handle if this exception is occurred
 } finally {
   //code that will be executed regardless of whether an exception is thrown or not
 }
  • You can also try/catch on variable assignment
 val x = try { someFunction() } catch(e: Exception) { 0}
 //x will be 0 if an exception is thrown from someFunction()

References