简体   繁体   中英

Hard time understanting checked & unchecked exceptions

I've already read everything I could about this and I still don't understand how to use checked and unchecked exceptions. I think I can't still grasp the concept. I've read around StackOverflow that it's better to use unchecked rather than checked exceptions, but Eclipse forces me to use checked exceptions, as in FileNotFoundException (AFAIK, if Eclipse forces me to insert a try/catch block, it's a checked exception). I'm wondering, is there any way to translate checked into unchecked? What the hell is handling per se? I do not understand what it is to handle an exception.

I have this example here, I would really like to know how to handle (?) this. This one is a checked exception, right?

public void readFile() {
    File foo = new File("./foo.bar");
    try {
        BufferedReader bufferedReader = new BufferedReader(new FileReader(foo));
    } catch (FileNotFoundException e) {
        // What should I do here?
    }
    getDataFromFile(bufferedReader);
}

I've seen various things people do here. Some print a stack trace, that's what I usually do, and I don't see the problem with it. It gives me the information I need to debug. Some people ignore them, I think that shouldn't be done (I saw the JNode OS booter ignoring an exception). Some people simply add the throws declaration in the signature. Some throw more exceptions inside that thing! (I think maybe this is what using unchecked instead of checked means?)

Furthermore, if you add the throws declaration, you will be forced to put a try/catch block further up, and that's inconvenient if you have a very big application. I'm sorry, but I am simply clueless. Completely. I'm trying to learn good and elegant design and this is torturing me.

Unchecked Exception

is an exception due to something that shouldn't happen in the first place, and hence cannot be anticipated. It handles a case that would arise only if your program had a bug .

It is a subclass of RuntimeException (which is a subclass of Exception ), and are usually implemented using IllegalArgumentException , NullPointerException , or IllegalStateException

Unchecked runtime exceptions represent conditions that, generally speaking, reflect errors in your program's logic and cannot be reasonably recovered from at run time.


Checked Exception

is something that could happen, due to unforseen circumstances with the rest of the system. It is outside your direct control, but isn't necessarily a bug , but a case that could be encountered.

It is a subclass of Exception .

From: Exceptions


In your example,

The file not being present is a case you need to handle as it could happen, even in production code, if certain conditions prevail (disk being full). That makes it a checked exception.


Dealing with an exception:

Exceptions are intended towards providing a better user-experience. So you should report the error to the user, and gracefully terminate if you cannot continue.

  1. If it is indeed a case you have anticipated, then you should probably inform the user of the issue, and terminate gracefully if necessary, or move on to do the next thing.

  2. If it is an unchecked exception, the best you could do is to tell the user than an unexpected error occurred, as it isn't something that should happen in the first place, and get the stacktrace reported back to you.

First, exceptions are your friend :) - No, really. Exceptions are quite a powerful and safe way for error handling.

Basically, the difference between checked and unchecked exceptions in Java is the intended reaction to the exception:

A checked exception is usually used to communicate some kind of 'unexpected' result of an operation to the caller, who is considered to want to handle that exceptional state explicitly.

An unchecked exception usually is one that is considered to be more or less un-recoverable from. It is used to indicate some fault condition that is assumed to invalidate the whole operation. Like the NullPointerException these exceptions are more or less latent in almost all operations. Making them checked would mean some nasty overhead in errorhandling needed to be done by the caller.

In your example, you would probably go like this:

public void readFile() {
    File foo = new File("./foo.bar");
    try {
        BufferedReader bufferedReader = new BufferedReader(new FileReader(foo));
        getDataFromFile(bufferedReader);  // If the file could not be found above, this will never execute!
    } catch (IOException e) {
        // React, e.g.:
        System.out.println("Data could not be read due to an IO error.");
    }

}

Re-throwing an exception or wrapping one exception in another is not uncommon. - For example, when an IOException strikes, you may want to do some cleanup, close some open files or the like, before handing the exception as-is or amended to the caller so that he can handle the exception in the appropriate way.

How you actually handle a particular exception is pretty much completely up to you. Depending on the user (eg yourself) and environment that run your code printing the stacktrace may be ok. Or, maybe, you want to retry what you just did after some pause. Or, in the example given, you could show a message to the user and ask him to re-enter the filename, &c.

The latter is by the way something where different classes of exceptions can be used effectively: A FileNotFoundException (which is a subclass of IOException ) may be recoverable from by user interaction; a bare IOException may well be considered unrecoverable from since it may in the worst case even indicate some kind of hardware failure.

Let's take your example(modified) itself to explain.

public void readFile() {
    BufferedReader bufferedReader = null;
    try {
            File foo = new File("./foo.bar");
        bufferedReader = new BufferedReader(new FileReader(foo));
    } catch (FileNotFoundException e) {
        // What should I do here?
    }
    getDataFromFile(bufferedReader);
}

When you get FileNotFoundException exception then your bufferedReader is not initialized with file stream. In that case, your next statement ie getDataFromFile(bufferedReader); will fail as there is no bufferedReader to read the data.

So in catch block, you can do on of the two:

  1. Throw a new custom exception and return from the program
  2. Try correcting the problem in getting the file handle again(one example could be using default file in that case), so the bufferedReader is properly initialized.

This way, CheckedException are helpful in the cases while writing the program itself. They provide you the inputs regarding possible failures and enable you to make a appropriate handling decision upfront.

On the other hand, unchecked exceptions such as NullPointerException are difficult to identify at the compilation time and may go unnoticed. If occurred and not handled, they cause issues at run time.

Checked exceptions are a pain in the ass.

Sorry to use such blunt language, but they are one of the worst design mistakes of Java! If you have to deal with legacy APIs that still use checked exceptions, such as Eclipse or Java's own APIs, what I personally do is to wrap them into my own unchecked exceptions. It is good practice to use your own tagging class. This helps you to recognize these exceptions as being caused by your code, for example in the log files or when debugging.

Personally I take great satisfaction in calling my tagging class BullshitFree so I can rethrow checked exceptions as follows

try {
    // call to legacy API that still uses checked exceptions
} catch(CheckedException exception) {
    throw new BullshitFree(exception);
}

Make sure your BullshitFree exception class actually extends RuntimeException so that it is unchecked!

In the case of your code example there are two options. If there is a way to recover from this, for example by creating the file or reporting the error back to the user, do so. If not, or if it just a small script that you're using for yourself, wrap it in a BullshitFree exception and spend the remainder of the day learning Ruby or another well designed language …

Your milage may vary.

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