try-catch Block in Java – Explained with Examples
The try-catch block is Java's basic tool for handling exceptions. Code that might fail goes in the try block; code that responds to a specific failure goes in a catch block. If no exception occurs, the catch block is skipped. If one does, Java jumps straight to the matching catch block, and the program continues instead of crashing.
This tutorial covers the syntax, exactly how control flows through try-catch, how exception types are matched, the rules for ordering catch blocks, and how to rethrow or wrap exceptions.
1. Syntax
try {
// code that may throw an exception
} catch (ExceptionType variableName) {
// code that handles that exception
}
- A
trymust be followed by at least onecatchor afinally(or be a try-with-resources statement). - The catch parameter declares which exception type it handles, and gives you access to the exception object.
- Variables declared inside
tryare not visible incatch; declare them before thetryif both need them.
2. A First Example
Parsing user input is a classic use: if the text is not a number, fall back to a default instead of crashing.
public class TryCatchBasics {
static int parseQuantity(String text) {
try {
return Integer.parseInt(text.trim());
} catch (NumberFormatException e) {
System.out.println(" '" + text + "' is not a number, using 1");
return 1; // sensible fallback
}
}
public static void main(String[] args) {
for (String input : new String[] {"5", " 12 ", "two", ""}) {
System.out.println("quantity = " + parseQuantity(input));
}
}
}
quantity = 5 quantity = 12 'two' is not a number, using 1 quantity = 1 '' is not a number, using 1 quantity = 1
3. How Control Flows Through try-catch
- Statements in
tryrun in order. - If one throws an exception, the rest of the
tryblock is skipped. - Java looks for the first
catchwhose type matches the exception and runs it. - Execution continues after the whole try-catch statement.
- If no catch matches, the exception propagates to the calling method.
public class ControlFlow {
public static void main(String[] args) {
int[] stock = {5, 0, 3};
for (int i = 0; i < stock.length; i++) {
try {
System.out.println("step A: item " + i);
int perDay = 30 / stock[i]; // fails when stock is 0
System.out.println("step B: lasts " + perDay + " days");
} catch (ArithmeticException e) {
System.out.println("caught: " + e.getMessage() + " (step B skipped)");
}
System.out.println("step C: after try-catch");
}
}
}
step A: item 0 step B: lasts 6 days step C: after try-catch step A: item 1 caught: / by zero (step B skipped) step C: after try-catch step A: item 2 step B: lasts 10 days step C: after try-catch
For item 1, "step B" was skipped, the catch block ran, and the loop continued normally with "step C".
4. Matching Exception Types
A catch block handles its declared type and all its subclasses. Catching IOException also catches FileNotFoundException; catching RuntimeException also catches NullPointerException:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CatchOrder {
public static void main(String[] args) {
// A catch block for a parent type also catches its subclasses
try {
new FileReader("missing.txt").close();
} catch (FileNotFoundException e) { // most specific first
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) { // then the more general type
System.out.println("Other I/O problem: " + e.getMessage());
}
try {
Object item = findItem("pen");
System.out.println(item.toString()); // item is null
} catch (RuntimeException e) { // catches NullPointerException too
System.out.println("Caught as RuntimeException: " + e.getClass().getSimpleName());
}
}
static Object findItem(String name) { return null; } // pretend nothing was found
}
File not found: missing.txt (No such file or directory) Caught as RuntimeException: NullPointerException
When several catch blocks are listed, the first match wins, so put specific exceptions before general ones. Putting a parent type first makes the child catch unreachable, and the compiler rejects it:
Bad.java:4: error: exception NumberFormatException has already been caught
catch (NumberFormatException e) { }
^
1 error
More on this in Multiple catch Blocks.
5. Rethrowing and Wrapping Exceptions
Sometimes the right response is not to recover but to translate a low-level exception into one that makes sense at a higher level, while keeping the original as the cause:
import java.util.Map;
public class WrapAndRethrow {
static class ConfigException extends RuntimeException {
ConfigException(String message, Throwable cause) { super(message, cause); }
}
static int readPort(Map<String, String> config) {
try {
return Integer.parseInt(config.get("port"));
} catch (NumberFormatException e) {
// Translate a low-level error into one that makes sense to callers, keeping the cause
throw new ConfigException("Invalid port in configuration", e);
}
}
public static void main(String[] args) {
try {
readPort(Map.of("port", "80a"));
} catch (ConfigException e) {
System.out.println(e.getMessage());
System.out.println("caused by: " + e.getCause());
}
}
}
Invalid port in configuration caused by: java.lang.NumberFormatException: For input string: "80a"
Always pass the original exception to the new one's constructor. Losing the cause makes problems very hard to diagnose.
6. What to Do in a catch Block
- Recover: use a default value, retry, or ask the user again.
- Report: log the exception with its stack trace and show a clear message.
- Translate: wrap it in a more meaningful exception and rethrow.
- Clean up partial work, then rethrow.
ignored.7. Rules and Tips
- Keep
tryblocks small: only the statements that can throw the exception you are handling. - Catch the most specific exception you can handle.
- Do not use try-catch for normal control flow, for example to detect the end of an array.
- Catching a checked exception that the
tryblock cannot throw is a compile error. - Use
finallyor try-with-resources for clean-up code that must always run. - Catch several unrelated types in one block with multi-catch:
catch (IOException | SQLException e).
8. Summary
trywraps risky code;catchhandles a specific exception type and its subclasses.- When an exception occurs, the rest of the try block is skipped and the first matching catch runs.
- Order catch blocks from specific to general; the compiler rejects unreachable catches.
- Rethrow or wrap exceptions, always keeping the original cause.
- Never swallow exceptions silently.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is a try-catch block in Java?
A statement that runs code in a try block and, if an exception of a listed type occurs, runs the matching catch block instead of letting the exception stop the program.
Q2. Can I use try without catch?
Yes, with finally (try { } finally { }) or as a try-with-resources statement. A plain try on its own does not compile.
Q3. Can I use catch without try?
No. A catch block must always follow a try block.
Q4. What happens to the remaining statements in try after an exception?
They are skipped. Control jumps to the matching catch block, then continues after the whole try-catch statement.
Q5. What happens if no catch block matches?
The exception propagates to the calling method. If nothing catches it, the thread ends with a stack trace.
Q6. Can one catch block handle multiple exception types?
Yes, since Java 7: catch (IOException | SQLException e). The types must not be subclasses of each other.
Q7. Why must specific exceptions be caught before general ones?
Because the first matching catch wins. A general catch first would handle everything, making later specific catches unreachable, which the compiler reports as an error.
Q8. Is it okay to catch Exception?
At the top level of an application (to log unexpected errors) it can be. Elsewhere, catch specific types so you do not accidentally handle bugs you did not anticipate.
Q9. Can a variable declared in try be used in catch?
No. Its scope ends with the try block. Declare it before the try statement if both blocks need it.
Q10. Can I nest try-catch blocks?
Yes. A try-catch can appear inside a try, catch or finally block. See Nested try Block.
Q11. How do I print the exception details in a catch block?
Use e.getMessage() for the message, e.toString() for type and message, or e.printStackTrace() (better: a logger) for the full stack trace.
Q12. What is exception wrapping?
Catching a low-level exception and throwing a higher-level one with the original as its cause: throw new ServiceException("msg", e);.
Q13. Does try-catch slow down my program?
A try block that completes normally costs essentially nothing. Throwing and catching exceptions is more expensive, which is why they should not be used for normal control flow.
Q14. Can I catch a checked exception that is never thrown?
No. The compiler reports an error if the try block cannot throw that checked exception. Unchecked exceptions and Exception itself can always be caught.
Q15. Can a catch block throw an exception?
Yes. It can rethrow the caught exception (throw e;) or throw a new one. If a finally block exists, it runs before the new exception leaves the method.
Q16. What is an empty catch block?
A catch block with no code. It silently ignores the exception, which usually hides bugs. At minimum, log the exception or explain in a comment why it is safe to ignore.
Q17. Can I catch Error with try-catch?
Technically yes, since Error is a Throwable, but you normally should not, because errors signal problems the program cannot reliably recover from.
Q18. What is the scope of the exception variable?
The variable declared in catch (Exception e) exists only inside that catch block. Since Java 22 you can write catch (Exception _) if you do not use it.
Q19. Can I use try-catch inside a loop?
Yes. Handling an exception for one iteration lets the loop continue with the next item, as shown in the control-flow example.
Q20. Should every method have a try-catch?
No. Handle exceptions where you can respond meaningfully; elsewhere, let them propagate or declare them with throws.