Why use try finally with an empty try block?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A try and finally pair exists to guarantee cleanup after code in the try block finishes, whether that finish is normal, exceptional, or caused by an early return. If the try block is literally empty, that guarantee becomes almost useless, which is why an empty try with a finally block is usually a code smell rather than a deliberate technique.
What finally Is Actually For
The classic use case is resource cleanup:
Here the finally block matters because readData(in) may:
- complete normally
- throw an exception
- return early through some control path
The finally block guarantees in.close() still runs.
What Happens With an Empty try
Now compare that with:
Because the try block contains no work, cleanup() runs immediately every time. In normal handwritten code, that is usually equivalent to writing:
So the question becomes: what extra behavior did the empty try actually buy you? In most cases, the answer is none.
When It Appears in Real Code
You may still see this pattern for a few reasons:
- code generation left a structural placeholder behind
- a refactor removed the contents of the
tryblock but not the surrounding structure - the author intended to add guarded code later and never finished
Those are explanations, but they are not usually good reasons to keep the pattern.
It Does Not Provide Magical Exception Handling
Some developers assume an empty try plus finally changes exception behavior globally around nearby code. It does not. The finally only pairs with control flow that enters the try block itself.
For example:
This does not protect doSetup() or doMoreWork(). It only guarantees that cleanup() runs after entering and leaving the empty try, which is immediate. That makes the structure misleading because it suggests a protected region that does not really exist.
Better Alternatives
If you want cleanup for real work, put that real work in the try block.
If there is no protected work left, remove the try and finally entirely.
In Java specifically, try-with-resources is often even better:
That expresses the intent more clearly than a manual finally block.
Rare Edge Cases
There are niche situations involving generated bytecode, instrumentation, or staged refactoring where an empty try block might exist temporarily. But in ordinary application code, it is rarely the right final form. Most reviewers should treat it as a sign to simplify or clarify the surrounding control flow.
Common Pitfalls
The biggest pitfall is assuming the empty try protects code outside the block. It does not; only code inside the try participates in the finally guarantee.
Another common mistake is leaving the pattern in place after the real contents of the try were removed during refactoring. That leaves confusing structure without meaningful behavior.
Developers also sometimes keep it because "finally always runs," but that misses the point. finally is useful when it is paired with a nontrivial protected region. Without that region, the structure just adds noise.
Summary
- '
finallyexists to guarantee cleanup after code insidetryfinishes.' - If the
tryblock is empty, thefinallyblock usually adds no useful behavior. - In normal code, an empty
trywithfinallyis usually a smell left by refactoring or code generation. - Put the real protected work inside the
try, or remove the structure entirely. - In Java,
try-with-resourcesis often a clearer alternative for resource cleanup.

