Throwing Exceptions and Writing Your Own Exception Classes
A thrown exception is an object carrying the call stack and an error message from the failure point to the handler.
Try it: try / except / else / finally
How an exception jumps out of a try block to the first matching except clause, when else runs, and why finally always runs.
How it works
- Statements in try run until one raises an exception; the rest of try is skipped.
- Python checks the except clauses in order and runs the first one whose type matches.
- If nothing was raised, the else block runs instead.
- finally runs in every case.
Default run (9 steps): Call safe_divide('4'). … Return 25.0. Output was: Worked: 25.0 / Done.
Simplified: One fixed function; int() and / are modelled exactly (including how Python prints floats), but nothing is executed as Python.
Loading the simulation…
Why Letting a Program Crash Can Be Right
Many beginners who learn about exceptions arrive with a simple plan. They wrap the risky code in a try..catch, catch every possible error, and expect the program never to crash again. The goal is understandable, because a crashing program feels like a failure. This article examines that belief before it takes hold, because the Java class hierarchy for exceptions shows why it is mistaken. The organization of these classes reflects a deliberate distinction between problems a program can reasonably respond to and problems it cannot.
What do you think happens?
If an exception is thrown three method calls deep, what happens to the methods that were in the middle of running?
Reveal answer
They are skipped, and control moves toward the nearest handler
A thrown exception abandons the normal flow of the active methods. Control travels back up the chain of active calls until it reaches a handler that can deal with the exception. The frames in between do not resume where they left off.
What Travels Inside an Exception Object
When something goes wrong at runtime, the item that is thrown is an object, not a bare error code or a message string. That object is an instance of a class in the family rooted at java.lang.Throwable. Every exception object must be an instance of some subclass of Throwable, and each distinct kind of problem usually has its own subclass.
Because it is an object, the exception can carry information. The source identifies two pieces that matter most. The first is the subroutine call stack, a list of the subroutines that were active when the exception was thrown. This list is always included. Because one subroutine can call another, several subroutines may be active at once, and the call stack records that chain. The second is an error message describing what caused the exception. The object can also hold other data, which is why an exception is more than a simple signal that something failed.
A thrown exception is an object carrying the call stack and an error message from the failure point to the handler. The exception object is a carrier: it moves information from the place where the failure happened to the place where the program decides what to do about it.
Following a Thrown Exception Up the Call Stack
Imagine three methods where main calls processOrder, and processOrder calls parseQuantity. If parseQuantity throws an exception, the exception does not return normally to processOrder. The methods that are still active are unwound in reverse order of their calls until a handler is found. In this arrangement, processOrder has no catch block, so it is skipped as well, and control lands in the try..catch inside main. The diagram shows the chain of active calls at the moment of failure.
Read the diagram from the deepest active call outward. The frames marked as changed are the ones abandoned when the exception is thrown. The call stack stored inside the exception object records this same chain, which is why a handler can later see exactly which subroutines were active at the failure point.
The Throwable Family Tree
The classes that represent exceptions form a tree with Throwable at the root. Throwable has exactly two direct subclasses, Error and Exception. Each of those has many predefined subclasses, and programmers can add their own subclasses to represent new kinds of exception. The full tree is large, so the diagram shows Throwable together with a few of its subclasses, which is enough to see the structure that matters for handling decisions.
Read the diagram from the top down. Every line descending from Throwable is a subclass relationship, so every class below it is also a kind of Throwable. The split at the second level matters most. The left branch leads to Error, and the right branch leads to Exception. The source uses this split to separate the two groups by how a program should treat them. The RuntimeException shown under Exception is one of the classes that the source treats as a special case, discussed in the next section.
Exempt and Mandatory Exception Classes
Errors and RuntimeExceptions, along with their subclasses, share a property: a program can simply ignore the possibility that they might occur. The source defines ignoring here as being content to let the program crash if the exception happens. Every exception class outside those two groups is different. For all of them, exception handling is described as mandatory, in a particular sense that the source says it will discuss later.
A short sorting rule captures this. Errors and RuntimeExceptions are the exempt groups, and everything else in the Exception branch falls under the mandatory requirement. The exemption does not mean the program is safe with those failures. It means the language does not force you to plan for them, while the good practice from the source still applies to how you respond to them.
Why Catch-All Handlers Hide Problems
The source is direct about the beginner's plan. A programmer should avoid the temptation to put in a catch-all handler so that errors do not crash the program. If there is no reasonable way to respond to an error, it is usually better to let the program crash, because trying to continue in that situation tends to make things worse. In the worst case, the program keeps running and produces an incorrect answer without giving any indication that the answer might be wrong.
Common mistake Catching every possible exception so the program never crashes
What it looks liketry { processAll(); } catch (Exception e) { }Why it failsThe empty handler discards the message and the call stack, so the failure leaves no trace and the program may continue with wrong results.
Do this insteadCatch only the exceptions you have a reasonable response to, and let the others surface so the underlying bug can be found and fixed.
Common mistake Treating a RuntimeException as something to routinely catch
What it looks likeA NullPointerException-style problem silently caught and ignored in a loop
Why it failsThe source notes that
RuntimeExceptionusually points to a bug that should be fixed, so catching it hides the defect instead of removing it.Do this insteadFix the code that produces the problem, and reserve handlers for failures the program can genuinely recover from.
Common mistake Assuming an ignored exception means the program is safe
Why it failsThe exemption only means the language does not force you to plan for Errors and RuntimeExceptions. It says nothing about whether the program behaves correctly afterward.
Do this insteadTreat the exemption as a compiler rule, not a guarantee of correctness.
Writing Your Own Exception Class
Because every exception is an object whose class belongs to the Throwable family, a programmer can add a subclass to represent a new kind of problem. The source notes that programmers can add their own subclasses to the tree. The example below creates a checked-style exception by extending Exception, so that the class sits in the branch the source describes as meant to be caught. Its constructor passes a message up to the parent class, which is how the message travels inside the object.
- extends Exception places the new class beneath Exception in the hierarchy
super(message)hands the error message up to the parent, which stores it in the object
Caught: Requested 80.0 but balance is 50.0- throw creates a new exception object and starts the unwinding described earlier
- The throws clause declares the exception so that the caller must handle or declare it
- The catch block reads the message stored inside the exception object
Practice: Sorting Exception Classes
For each of the following, decide whether the exception class is in an exempt group (handling optional) or a mandatory group: Error, RuntimeException, a custom subclass of Exception, and a custom subclass of RuntimeException. Then explain in one sentence why the custom RuntimeException subclass is still exempt even though you wrote it yourself.
Hints
- Start from the sorting rule: Errors and RuntimeExceptions, along with their subclasses, are the exempt groups.
- Check whether your custom class extends
RuntimeExceptionor Exception, since its parent determines its branch.
Key Takeaways
- A thrown exception is an object, not a bare code, and it carries the call stack and an error message from the failure point to the handler.
- Throwable has two direct subclasses, Error and Exception, and the hierarchy is organized around that split.
- Errors and RuntimeExceptions, with their subclasses, are exempt: a program may ignore them and let it crash, while other Exception classes make handling mandatory.
- Catch-all handlers that hide failures are a mistake, since letting an unrecoverable error crash the program is often better than producing a silently wrong answer.
- Programmers can write their own exception classes by extending Exception or
RuntimeException, inheriting the message and call stack behavior from the parent.