简体   繁体   中英

Why use IOexception instead of Exception when catching?

I can't seem to phrase this correctly for the search engine to pick up any meaningful results.

try{
    BufferedReader reader = new BufferedReader( new FileReader("foo.bar") );
}
catch(Exception e){
    println( e.getMessage() );
}

So FileReader only throws the FileNotFoundException , which as I understand it is an IOException , which is an Exception. Can someone explain why I would catch FileNotFoundException or IOException instead of just specifying the generic "Exception" and not having to import an exception (ie import java.io.FileNotFoundException;) ? Is it strictly for readability?

I've caught the exception using all three names and I can't find a difference.

EDIT:--------------------

private BufferedReader askUserForFile(String prompt){
        BufferedReader rd = null;
        while(rd == null){
            try{
                String filename = readLine(prompt);
                rd = new BufferedReader( new FileReader(filename) );
            }
            catch(Exception e){
                println(e.getMessage());
            }
        }
        return rd;
    }

Exception is the mother of all exceptions, including all RuntimeException subclasses. When you specify to catch it, you'll get much more fish in the net than you wanted, like NullPointerException s, IllegalArgumentException s and so on.

While catching the generic Exception is the right thing to do at some point in your code, catching it at any lower layer is almost certainly wrong and can hurt the behavior of your application.

The more important skill to learn in Java is not how to catch exceptions, but how to not catch them, instead letting them propagate up the call stack, towards the exception barrier , the one common spot in the code where all errors are caught and uniformly handled (typically by logging, rolling back the transaction, and similar).

The difference is there could be other problems inside the code of your try block that could throw other types of Exception s including subclasses of RuntimeException (which don't have to be declared).

If you just catch Exception , then you will catch all of those other errors too which may hide a different problem. Also your code inside the catch block can't assume the Exception happened due to an IOException since any kind of exception will be caught.

As a followup to dkatzel's answer, let's assume you start to read from the file in the same try block and the file tells you which value in a array of options to use:

String toPrint = {"Hi", "World", "I'm", "A", "String", "Array"};
try{
    BufferedReader reader = new BufferedReader( new FileReader("foo.bar") );
    String line = reader.readLine();
    System.out.println(toPrint[Integer.parseInt(line)]);

}
catch(Exception e){
    println( e.getMessage() );
}

Now you have absolutely no idea what really went wrong except through the stack trace. You can't handle any fixable problems. You can't tell in code whether the file doesn't exist ( FileNotFoundException ), you don't have access to the file, ( IOException ), if the first line wasn't an Integer ( NumberFormatException ), or the number was bigger than the array length ( ArrayIndexOutOfBoundsException ). If you wanted to print a default value if you couldn't read the number, you could instead catch a NumberFormatException and print the value instead of having to quit the entire program.

I'll admit this is a pretty contrived example, but it should give you an explanation of why catching Exception is bad. Marko also has a very good answer, stating that it usually is better to let the exception propagate up (especially with RuntimeException s) than to create a bunch of messy code trying to deal with every single problem that can happen.

What if you want to do a different action with different exceptions? You can make a catch block for IOException and for example, make it show a message box. Then make another catch block for a FileNotFoundException and make it create a new file and try to open it again, or even rethrow the exception. Hope I explained myself correctly. Cheers!

The reason is whenever you program, you have to think about all the possibilities and it is useful to do something for a specific error. Exception is a catch all method of catching errors and will handle all exceptions the same. IOException will catch any IO Exceptions so it will treat file not found and and other IO Exception (like EOFException ) the same. FileNotFoundException will only catch file not found exceptions so you can handle it instead of just logging it.

Some errors will happen and being able to handle each individual case keeps your program running. In this case, file not found can make you select another file so the program doesn't crash and it handles the situation.

FileNotFoundException is an IOException which is an Exception

You are right. But if you catch Exception objects you will catch any exception triggered by your code, not only the FileNotFound exception.

Let's say that your code can throw more than one kind of exception:

try {
    /*
     * Code, code and more code
     */
} catch(ExceptionType1 e) {
        System.err.println("Something went wrong! It is a type 1 exception");
} catch(ExceptionType2 e) {
        System.err.println("Something went wrong! It is a type 2 exception");
} catch(Exception e) {
        System.err.println("Something went wrong! It is not any of the known exception types");
}

Compare the above possibility with this:

try {
    /*
     * Code, code and more code
     */
} catch(Exception e) {
        System.err.println("Something went wrong! Can be exception type 1, 2 or something else");
}

As you can see, differentiating the exception types can help you understand what went wrong in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM