I have been trying to find out answer to this question but did not get any satisfactory explanation. Here is some background:
Java 7 allows us to catch multiple exceptions in a single catch block provided those exceptions are from diffrent hierarchy. Eg:
try {
// some code
} catch(SQLException | FileNotFoundException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
But if exceptions are from the same hierarchy we must use multiple catch blocks like:
try {
// some code
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
But if I try to write code like below compiler complains that "The exception FileNotFoundException is already caught by the alternative IOException"
try {
// some code
} catch(FileNotFoundException | IOException e) { // compiler error
e.printStackTrace();
}
Now my question is: Why compiler reports an error in last case, can't it figure out that FileNotFoundException is special case of IOException? This would save code duplication when my exception handling logic is same.
Why compiler reports an error in last case, can't it figure out that FileNotFoundException is special case of IOException?
Because FileNotFoundException is a subclass of IOException. In other words, the "FileNotFoundException |" part is redundant.
The reason why the code below is ok...
} catch(FileNotFoundException e) {
...
} catch(IOException e) {
...
}
...is because here the IOException clause matters: If a SocketException is thrown for instance, it will pass the by the FileNotFoundException part, and get caught in the IOException clause.
When catching an exception you have order your catch clauses from the most specific to the most general.
Consider the following hierachy:
class MyException extends Exception {}
class MySubException extends MyException {}
If a part of your code throws MyException an an other part throws MySubException you have to catch MySubException first.
catch(MySubException e){
} catch(MyException e){
}
Its the same thing like using the instanceof operator.
If you test if an instance of MySubException is an instanceof MyException the result will be true.
mse = new MySubException();
if(mse instanceof MyException){
println("MyException");
} else if(mse instanceof MySubException){
println("MySubException");
}
This piece of code will never print "MySubException".
mse = new MySubException();
if(mse instanceof MySubException){
println("MySubException");
} else if(mse instanceof MyException){
println("MyException");
}
This would be the correct order.
Its because FileNotFoundException extends IOException, as you said its of same hierarchy, you cannot add them to same catch block.
Related
Assuming we are talking about all the exceptions that extends base Exception class,
is:
try {
some code;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
catch (MyOwnException e)
{
e.printStackTrace();
}
same as:
try {
some code;
}
catch (Exception e) {
e.printStackTrace();
}
I am wondering in which case I MUST use the former one?
In the 2nd option Exception will catch all exception, not only those explicitly listed in the first option.
Use the 1st option if you want to catch only selected exceptions, and respond differently to each.
If you want to catch only selected exceptions, and have the same response to all of them, you could use:
catch (InterruptedException | ExecutionException | MyOwnException e)
{
e.printStackTrace();
}
It is good practice to use Exception sub classes rather than Exception class. If you use Exception then it would be difficult to debug.
Here is a link for reference
http://howtodoinjava.com/best-practices/java-exception-handling-best-practices/#3
If you have multiple exceptions which all are extending from...we'll say IndexOutOfBoundsException, then unless you specifically want to print a different message for StringIndexOutOfBoundsException or another sub-class you should catch an IndexOutOfBoundsException. On the other hand if you have multiple exceptions extending from the Exception class, it is proper format to create a multi-catch statement at least in JDK 1.8:
try {
// Stuff
}catch(InterruptedException | ClassNotFoundException | IOException ex) {
ex.printStackTrace();
}
The former one where you create multiple catch statements is if you were trying to do what I said before.
try {
// Stuff
}catch(StringIndexOutOfBoundsException se) {
System.err.println("String index out of bounds!");
}catch(ArrayIndexOutOfBoundsException ae) {
System.err.println("Array index out of bounds!");
}catch(IndexOutOfBoundsException e) {
System.err.println("Index out of bounds!");
}
look at the next code lines please:
public void methodBla(){
try{
system.out.println(2/0);
{
catch(MyArithmeticException me){
system.out.println("Error: My exception");
}
catch(Exception a){
system.out.println("Error: general exception");
}
}
I don't understand why, when I'm trying to catch an ArithmeticException with my customize class: MyArithmeticException which extends ArithmeticException.
Public class MyArithmeticException extends ArithmeticException{
public MyArithmeticException(String str){
super("My Exception " + str);
}
}
MyArithmeticException doesnt catch it, its only catch the second "catch"(catch(Exception a)).
Thanks
Z
It is simple, because the statement 2/0 doesn't throw a MyArithmeticException. It throws ArithmeticException and since you didn't catch ArithmeticException, it is catched by the second catch.
The java language doesn't know if you want to derive your own exception type from any language defined exception. So if you need to throw your own type you should catch it and re-throw it as a ArithmeticException:
public void methodBla(){
try{
try{
system.out.println(2/0);
catch(ArithmeticException e){
throw new MyArithmeticException(e);
}
}
catch(MyArithmeticException me){
system.out.println("Error: My exception");
}
catch(Exception a){
system.out.println("Error: general exception");
}
}
Good Luck.
The problem is that an Arithmetic exception would be thrown. Not a "MyAritmeticException" so it cant be caught by the first catch clause, so it results to the second catch clause.
In other words, 2/0 will throw an AritmeticException which is the superclass of your exception thus it will not triger the MyArithmeticException catch block because thats a subclass.
If you want to customise the message of the exception you can do that in the catch statement, where you can get the message by Exception#getMessage() or Exception#getLocalizedMessage(); (the difference of the two can be found here)
I have a code that invokes an external API via EJB and that API occasionally leaks an exception that is not part of the client kit, therefore resulting in ClassNotFoundException.
I have a try-catch block surrounding the call:
try {
thirdPartyLibrary.finalInvokeMethod();
} catch (SomeException exception) {
//Do something
} catch(
..
} catch (Exception exception) {
if (exception instanceof ClassNotFoundException) {
log.error("....");
}
}
I want to avoid using instanceof in catch, but if I add a separate catch clause for ClassNotFoundException, the compiler produces an error "Unreachable catch block", since thirdPartyLibrary.finalInvokeMethod(); doesn't throw ClassNotFoundException.
Is there a better way to address the issue?
I've found a workaround. I've wrapped the thirdPartyLibrary.finalInvokeMethod(); in another method that throws the checked exception. So I got a dedicated catch clause without a compiler error.
private someMethod() {
try {
callExternalAPI();
} catch (SomeException exception) {
//Do something
} catch(
..
} catch (ClassNotFoundException exception) {
log.error("....");
//Do something
} catch (Exception exception) {
//Do something
}
}
private void callExternalAPI() throws ClassNotFoundException {
thirdPartyLibrary.finalInvokeMethod();
}
I have encountered a scenario while working with exceptions, following is the sample code.I am trying to understand why following code fails to compile. I am checking the exception type before rethrow which is unchecked exception.
public class TestException {
public void test() throws FileNotFoundException {
FileReader test = new FileReader("");
}
public static void main(String[] args){
TestException test=new TestException();
try {
test.test();
} catch (Exception e) {
// TODO Auto-generated catch block
if(e instanceof ArithmeticException){
throw e;
}
else{
e.printStackTrace();
}
}
}
}
You are still throwing a reference variable e of type Exception. Exception is a checked type. The compiler only knows the reference variable's type, not the referenced object's. If you want to keep main's method signature as-is, you'll need to either wrap e into an unchecked exception type (such as ArithmeticException):
if(e instanceof ArithmeticException){
throw new ArithmeticException(e.getMessage());
}
or cast it as an unchecked exception:
if(e instanceof ArithmeticException){
throw (ArithmeticException)e;
}
Since the reference variable e is of type java.lang.Exception, throw e will throw checked exception. Thus it has to be declared in throws section in the method signature.
Try changing your catch block as follows:-
if(e instanceof ArithmeticException){
throw (ArithmeticException)e;
}
else{
e.printStackTrace();
}
You could also use a hack with Generics to throw an checked Exception as an unchecked one:
http://www.gamlor.info/wordpress/2010/02/throwing-checked-excpetions-like-unchecked-exceptions-in-java/
I like to use this over throw new RuntimeException(e), since the latter creates unnecessary output in a Stacktrace and its harder to catch somewhere else (you have to check the cause instead of the excetion itself).
catch (Exception e) {
Here is the effective declaration of e.
if(e instanceof ArithmeticException){
Here you are doing a runtime check of the type of e.
throw e;
At this point the compile-time type of e is Exception. So the compiler enforces its rules.
I will suggest to use two catch blocks.
typechecking in catch block is not a good practice where you can catch that specific class using other catch statement.
catch (ArithmeticException e) {
// TODO Auto-generated catch block
throw e;
}
catch(Exception e)
{
e.printStackTrace();
}
#Silly Freak I agree with you.
If you throw any exception then you should handle it but in your program your are able to throw but nowhere you are handling the exception, so just handle the exception by adding throws in main class like this:-
package first;
import java.io.FileNotFoundException;
import java.io.FileReader;
class A3{
public void test() throws FileNotFoundException {
FileReader test = new FileReader("");
}
public static void main(String[] args) throws Exception{
A3 test=new A3();
try {
test.test();
} catch (Exception e) {
// TODO Auto-generated catch block
if(e instanceof ArithmeticException){
throw e;
}
else{
e.printStackTrace();
}
}
}
}
In C#, I can use the throw; statement to rethrow an exception while preserving the stack trace:
try
{
...
}
catch (Exception e)
{
if (e is FooException)
throw;
}
Is there something like this in Java (that doesn't lose the original stack trace)?
catch (WhateverException e) {
throw e;
}
will simply rethrow the exception you've caught (obviously the surrounding method has to permit this via its signature etc.). The exception will maintain the original stack trace.
You can also wrap the exception in another one AND keep the original stack trace by passing in the Exception as a Throwable as the cause parameter:
try
{
...
}
catch (Exception e)
{
throw new YourOwnException(e);
}
I would prefer:
try
{
...
}
catch (FooException fe){
throw fe;
}
catch (Exception e)
{
// Note: don't catch all exceptions like this unless you know what you
// are doing.
...
}
In Java is almost the same:
try
{
...
}
catch (Exception e)
{
if (e instanceof FooException)
throw e;
}
In Java, you just throw the exception you caught, so throw e rather than just throw. Java maintains the stack trace.
Stack trace is prserved if you wrap the catched excetion into an other exception (to provide more info) or if you just rethrow the catched excetion.
try{
...
}catch (FooException e){
throw new BarException("Some usefull info", e);
}
something like this
try
{
...
}
catch (FooException e)
{
throw e;
}
catch (Exception e)
{
...
}
public int read(byte[] a) throws IOException {
try {
return in.read(a);
} catch (final Throwable t) {
/* can do something here, like in=null; */
throw t;
}
}
This is a concrete example where the method throws an IOException. The final means t can only hold an exception thrown from the try block. Additional reading material can be found here and here.
I was just having a similar situation in which my code potentially throws a number of different exceptions that I just wanted to rethrow. The solution described above was not working for me, because Eclipse told me that throw e; leads to an unhandeled exception, so I just did this:
try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}
Worked for me....:)