Everytime I run this code, everything works fine, but if deposit methods throws an error,
only the catch in the main method catches the exception and prints the string, despite the catch in the ExceptionsDemo. Why does that happen?
public class ExceptionsDemo {
public static void show() throws IOException {
var account = new Account();
try {
account.deposit(0);//this method might throw an IOException
account.withDraw(2);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}
}
}
public class Main {
public static void main(String[] args) {
try {
ExceptionsDemo.show();
} catch (IOException e) {
System.out.println("An unexpected error occurred");
}
}
}
This happens because in your show() method, you are catching a specific type of exception called InsufficientFundsException. But the exception thrown by account.deposit() is IOException which is caught only in your main method. That is why the catch in the main method gets executed and not the catch in ExcpetionsDemo
If you want to catch IOException in your ExceptionsDemo class you can do this:
public static void show() {
var account = new Account();
try {
account.deposit(0);//this method might throw an IOException
account.withDraw(2);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
A single try block can have multiple catch blocks for each type of exception and the handling of each exception can be customized to what you want by coding it in each of their catch blocks.
Your ExceptionsDemo throws a IOException, your catch in ExceptionsDemo only catches a InsufficientFundsException so it will not be caught in the ExceptionsDemo, it will bubble to the caller, and be caught there, providing there is a catch block to handle said exception, which it does, otherwise you'll have an uncaught exception. It's not been rethrown from ExceptionsDemo, because its not being caught in the first place
try {
// do what you want
} catch (InsufficientFundsException e) {
// catch what you want
} catch (Exception e) {
// catch unexpected errors, if you want (optional)
}
Related
Take this as example:
public class TestClass {
public static void test() throws SSLHandshakeException {
throw new SSLHandshakeException("I'm a SSL Exception");
}
public static void main(String[] args) throws SSLHandshakeException {
try {
test ();
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
}
}
}
So, I have my test method in which I'm just throwing an SSLHandshakeException which is a subtype of IOException.
The output for this is "I`m handling IO exception".
Why does this happen? I expected that my method will throw the SSLHandshakeException. Is there a rule that catch is more important than throws?
I just want to avoid using
try {
test ();
} catch (SSLHandshakeException se) {
throw se;
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
}
Because I consider it less readable
Is there a rule that catch is more important than throws?
They are two completely different things. The throws keyword is part of the method signature and is saying 'This method can throw this exception, so every caller should handle that explicitly.'
Wether or not the method actually throws that exception is irrelevant here.
As for the catch statement. SSLHandshakeException is an IOException, and so it is caught as expected.
To get the behaviour you intent you can write:
try {
test ();
} catch (SSLHandshakeException sslExc) {
throw sslExc;
} catch (IOException ioe) {
System.out.println("I`m handling IO exception that is not an SSLHandshakeException");
}
Edit: You say you find this less readable. But honestly this is just the best way. If it would behave the way you proposed than you would never be able to catch an SSLHandshakeException in a method that might also throw it? What if you want to catch it in certain conditions but throw it in others? It would just be too limiting and unintuitive.
An alternative is like so; but in my opinion this is even less readable:
try {
test ();
} catch (IOException ioe) {
if(ioe instanceof SSLHandshakeException)
throw ioe;
System.out.println("I`m handling IO exception that is not an SSLHandshakeException");
}
That's probably because you printed your custom string instead of message of exception. Try this :
public static void main(String[] args) throws SSLHandshakeException {
try {
test ();
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
System.out.println(ioe.getMessage());
}
}
SSLHandshakeException is a subclass of javax.net.ssl.SSLException wich is a subclass of java.io.IOException.
So this code :
public static void main(String[] args) throws SSLHandshakeException {
try {
test ();
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
}
}
will catch and IOException, and thus print the message "I`m handling IO exception".
I need to handle Exceptions which are raised by Catch block code in Java
Example, to "handle" an Exception:
try
{
// try do something
}
catch (Exception e)
{
System.out.println("Caught Exception: " + e.getMessage());
//Do some more
}
More info see: See: https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html
However if you want another catch in your try catch, you can do the following:
try
{
//Do something
}
catch (IOException e)
{
System.out.println("Caught IOException: " + e.getMessage());
try
{
// Try something else
}
catch ( Exception e1 )
{
System.out.println("Caught Another exception: " + e1.getMessage());
}
}
Be careful with nested try/catch, when your try catch is getting to complex/large, consider splitting it up into its own method. For example:
try {
// do something here
}
catch(IOException e)
{
System.out.println("Caught IOException: " + e.getMessage());
foo();
}
private void foo()
{
try {
// do something here (when we have the IO exception)
}
catch(Exception e)
{
System.out.println("Caught another exception: " + e.getMessage());
}
}
Instead of cascading try/catch (like in most of the other answers), I advise you to call another method, executing the required operations. Your code will be easier to maintain by this way.
In this method, put a try/catch block to protect the code.
Example :
public int classicMethodInCaseOfException(int exampleParam) {
try {
// TODO
}
catch(Exception e)
{
methodInCaseOfException();
}
}
public int methodInCaseOfException()
{
try {
// TODO
}
catch(Exception e)
{
//TODO
}
}
Do as you would do in an usual try/catch situation :
try{
throw new Exception();
}catch(Exception e1){
try{
throw new Exception();
}catch(Exception e2){
//do something
}
}
You can add new try catch block in your main catch block.
try
{
int b=10/0;
}catch(ArithmeticException e)
{
System.out.println("ArithmeticException occurred");
try
{
int c=20/0;
}catch(ArithmeticException e1)
{
System.out.println("Another ArithmeticException occurred");
}
}
I think the most clean way is to create method which is catching the exceptions occurs in its body. However it can be very dependent to the situation and type of code you are dealing with.
One example of what you are asking about is closing a Stream which is opened in a try-catch-finally block. For example:
package a;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream("temp.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
//TODO: Log the exception and handle it,
// for example show a message to the user
} finally {
//out.close(); //Second level exception is
// occurring in closing the
// Stream. Move it to a new method:
closeOutPutStreamResource(out);
}
}
private static void closeOutPutStreamResource(OutputStream out){
try {
out.close();
} catch (IOException e) {
// TODO: log the exception and ignore
// if it's not important
// OR
// Throw an instance of RuntimeException
// or one of it's subclasses
// which doesn't make you to catch it
// using a try-catch block (unchecked)
throw new CloseOutPutStreamException(e);
}
}
}
class CloseOutPutStreamException extends RuntimeException{
public CloseOutPutStreamException() {
super();
}
public CloseOutPutStreamException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public CloseOutPutStreamException(String message, Throwable cause) {
super(message, cause);
}
public CloseOutPutStreamException(String message) {
super(message);
}
public CloseOutPutStreamException(Throwable cause) {
super(cause);
}
}
Here I illustrated a situation which the second level exception is occurring in the finally block, but the same can apply for the exceptions occur in the catch block.
In my point of view writing methods such as closeOutPutStreamResource can be useful because they are packaging a boiler plate code for handling very common exceptions and they are making your codes more elegant.
Also it would be your choice to catch and log the exception in closeOutPutStreamResource or to throw it to other layers of your program. But it would be more elegant to wrap this unimportant checked exceptions into RuntimeException without a need for catching.
Hope this would be helpful.
You can use try catch block any where in methods or in block, so you can write try catch in catch block as well.
try {
// master try
}catch(Exception e){
// master catch
try {
// child try in master catch
}catch(Exception e1){
// child catch in master catch
}
}//master catch
It's not necessary to have a nested try-catch block when catch block throws Exception as all answers here suggest. You can enclose the caller method with try-catch to handle that Exception.
class Test {
public static void main(String[] args) {
try {
String s = "5.6";
Integer.parseInt(s); // Cause a NumberFormatException
int i = 0;
int y = 2 / i;
}
catch (Exception ex) {
System.out.println("NumberFormatException");
}
catch (RuntimeException ex) {
System.out.println("RuntimeException");
}
}
}
The correct answer is that the program has a compilation error. I thought that the catch (Exception ex) would catch all exceptions including NumberFormatException, that it was a general exception that caught them all?
The block:
catch (Exception ex) {
System.out.println("NumberFormatException");
}
will catch all the exceptions, as the Exception class is the base class for all the exceptions.
When you catch Exception, you catch all the exceptions that extend Exception, which, all the exceptions do. Hence it produces the error that RuntimeException has already been caught
public class SampleCloseable implements AutoCloseable {
private String name;
public SampleCloseable(String name){
this.name = name;
}
#Override
public void close() throws Exception {
System.out.println("closing: " + this.name);
}
}
and the main class
public class Main{
public static void main(String args[]) {
try(SampleCloseable sampleCloseable = new SampleCloseable("test1")){
System.out.println("im in a try block");
} catch (IOException e) {
System.out.println("IOException is never thrown");
} catch (Exception e) {
} finally{
System.out.println("finally");
}
}
}
But when i removed the throws exception on close() method inside SampleCloseable
i am getting a compiler error saying that IOException is never thrown in the corresponding try block.
Because you're throwing a generic Exception. Since an IOException inherits from Exception, it might be thrown by the close() method. The caller doesn't know that it doesn't actually get thrown. It only sees the method signature that says that it could.
In fact, the close() method is free to throw any Exception of any kind. Of course that's bad practice, you should specify what specific Exceptions you're throwing.
Your confusion may that around the fact the in Java 7, the exception that is [declared to be] thrown from the close method is thrown inside the try block, so your catch block has to catch it as well.
Your close method is declared to throw an Exception, so your catch blocks have to catch that, or the method has to be declared to throw Exception.
And since IOException is a subclass of Exception, you are of course allowed to try and catch that as well, as long as your also catch/declare Exception itself.
See JLS 14.20.3.2:
The meaning of an extended try-with-resources statement [...] is given
by the following translation to a basic try-with-resources statement
(ยง14.20.3.1) nested inside a try-catch or try-finally or
try-catch-finally statement.
Your code is effectively translated to the below. Although a bit longish, it should be clear from the below what's happening in your code.
public static void main(String args[]) {
try {
Throwable primaryEx = null ;
SampleCloseable sampleCloseable = new SampleCloseable("test1")
try {
System.out.println("im in a try block");
} catch (Throwable t) {
primaryEx = t;
throw t;
} finally {
if (sampleCloseable != null) {
if (primaryEx != null) {
try {
sampleCloseable.close();
} catch (Throwable suppressedExc) {
primaryEx.addSuppressed(suppressedExc);
}
} else {
sampleCloseable.close();
}
}
} catch (IOException e) {
System.out.println("IOException is never thrown");
} catch (Exception e) {
} finally{
System.out.println("finally");
}
}
In Java, if a general exception is caught and rethrown, will outer methods still be able to catch specific exceptions?
In other words, can I do this:
try {
try {
//...
} catch (Exception e) {
//...
throw e;
}
} catch (SpecificException e) {
//...
}
re-throwing an exception does not change anything about it (it's still the same object originally thrown).
While jtahlborn answer is correct, there is one more appreciation: the compiler will see that you are throwing an exception of the generic type (even if at runtime it can be only of the specific class) and will force you to declare the generic exception in the method header.
private void test() throws FileNotFoundException {
try {
throw new FileNotFoundException("Es una exception");
} catch (IOException e) {
throw e; <-- Error because the method only throws
FileNotFoundException, not IOException
}
}
e is indeed FileNotFoundException, but as it is declared as IOException the compiler works with the broader class. What you can do is "cast" the exception.
throw (FileNotFoundException) e;
Eclipse marks the "throw e" in the inner catch as an unhandled exception, BUT it does catch the exception because when I run this it prints "It worked!". Thanks #jtahlborn. Unfortunately this means that there will still need to be an unnecessary try/catch block somewhere.
public class Tester {
public static void main(String[] args) {
try {
try {
throw new SpecificException("Test!");
} catch (Exception e) {
throw e;
}
} catch (SpecificException e) {
System.out.println("It worked!");
}
}
}