6.1 Exception Handling
Failure is always a possibility.
Kotlin finds basic errors when it analyzes your program. Errors that cannot be detected at compile time must be dealt with at runtime. In Exception, you learned to throw exceptions. In this atom, we catch exceptions.
Historically, failures were often disastrous. For example, programs written in the C language would simply stop working, lost their data, and potentially crash the operating system.
Improved error handling is a powerful way to increase code reliability. Error handling is especially important when creating reusable program components. To create a robust system, each component must be robust. With consistent error handling, components can reliably communicate problems to client code.
Modern applications often use concurrency, and a concurrent program must survive non-critical exceptions. A server, for example, should recover when an open session is terminated via an exception.
Exceptions conflate three activities:
1.
Error reporting
2.
Recovery
3.
Resource cleanup
Let's consider each one.
Reporting
Standard library exceptions are often adequate. For more specific exception handling, you can inherit new exception types from Exception or a subtype:
A throw expression, as in main(), requires an instance of a Throwable subtype. To define new exception types, inherit Exception (which extends Throwable). Both Exception1 and Exception2 inherit Exception, while Exception3 inherits Exception2.
Recovery
The ambition of exception handling is recovery. This means that you fix the problem, return the program to a stable state, and resume execution. Recovery often includes logging information about the error.
Quite often, recovery isn't possible. An exception might represent an unrecoverable program failure, either a coding error or something uncontrollable in the environment.
When an exception is thrown, the exception-handling mechanism looks for an appropriate place to continue execution. An exception keeps moving out to higher levels, from function1() that threw the exception, to function2() that calls function1(), to function3() that calls function2(), and so on until reaching main(). A matching handler catches the exception. This stops the search and runs that handler. If the program never finds a matching handler, it terminates with a console stack trace.
Uncommenting the call to function3() produces the following stack trace:
Any of function1(), function2() or function3() can catch the exception and handle it, preventing the exception from terminating the program.
An exception handler is the catch keyword followed by a parameter list containing the exception you're handling. This is followed by a block of code implementing the recovery.
In the following example, the function toss() produce different exceptions for arguments 1-3, otherwise it return "OK". test() contains a complete set of handlers for the toss() function:
6.3 The Nothing Type
A Nothing return type indicates a function that never returns
This is usually a function that always throws an exception.
Here's a function that produces an infinite loop (avoid these)—because it never returns, its return type is Nothing:
Nothing is a built-in Kotlin type with no instances.
A practical example is the built-in TODO(), which has a return type of Nothing and throws NotImplementedError:
Both later() and later2() return non-Nothing types even though TODO() returns Nothing. Nothing is compatible with any type.
later() and later2() compile successfully. If you call either one, an exception reminds you to write implementations. TODO() is a useful tool for "sketching" a code framework to verify that everything fits together before filling in the details.
In the following, fail() always throws an Exception so it returns Nothing. Notice that a call to fail() is more readable and compact that explicitly throwing an exception:
fail() allows you to easily change the error-handling strategy. For example, you can change the exception type or log an additional message before throwing an exception.
This throws a BadData exception if the argument is not a String:
... 나중에 다시