10

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.

Jonas
  • 121,568
  • 97
  • 310
  • 388
JS Rolón
  • 273
  • 1
  • 9

4 Answers4

6

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.

Anirudh Ramanathan
  • 46,179
  • 22
  • 132
  • 191
  • 1
    Example of something that causes a checked exception: you try to write some data to a file, but the disk is full. That's not a bug in your program, but it's a situation that your program has to deal with somehow, so it produces a checked exception (specifically, `IOException`) that your program must catch. – Wyzard Nov 11 '12 at 17:17
  • @Wyzard One of the things I don't really grasp is the *handling* part. What is to handle or to deal with it? In your example, handling the exception would mean, for example, telling the user the operation couldn't be performed? Delete some data so that my data can be written to disk? – JS Rolón Nov 11 '12 at 17:23
  • In the case of a full disk, you'd probably just want to tell the user that their file couldn't be saved. But there's no universal answer for what it means to handle an exception. It depends entirely on what the problem is, and how it makes the most sense for your program to either resolve it, or at least avoid crashing or losing data. – Wyzard Nov 11 '12 at 17:31
  • @Teckizt Agree with Wyzard here. Exceptions are intended towards providing a better user-experience. So you should report the error to the user, and gracefully terminate if you have to. – Anirudh Ramanathan Nov 11 '12 at 17:32
  • 1
    In some cases, there's really no way that the program can continue to run (in a useful or meaningful way) after some types of problems, so the best you can do is output whatever information a human will need to resolve the problem manually, then terminate the program as gracefully as possible under the circumstances. – Wyzard Nov 11 '12 at 17:33
1

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 (e.g. 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.

JimmyB
  • 12,101
  • 2
  • 28
  • 44
1

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 i.e. 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.

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
  • @Teckizt: That is correct. Its always better to use checked exception, if possible so that scenario handling doesn't go un-noticed/un-handled. This will help in long term. Sometimes it's not possible to know the possible type of exceptions, then you have to use unchecked exceptions with no other choice. – Yogendra Singh Nov 11 '12 at 18:02
  • +1 But still there is problem in the solution `getDataFromFile` call should be inside try block so that if its `null` the it will not get called as no point in retrieving data from `null` file – Amit Deshpande Nov 12 '12 at 03:44
  • @AmitD: Agree. That is one way, but I took the same point to explain the concept, which starts from the very first paragraph in the explanation. >When you get FileNotFoundException then your bufferedReader is not initialized with file stream. In that case, your next statement i.e. getDataFromFile(bufferedReader); will fail as there is no bufferedReader to read the data. – Yogendra Singh Nov 12 '12 at 04:09
1

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.

akuhn
  • 27,477
  • 2
  • 76
  • 91
  • Would that I could +5 this... Heck, I will. I'm going to go to 5 of your other posts and +1 them! – Bill K Nov 16 '13 at 08:05
  • Checked exceptions would IMHO be useful *if* there were any easy way for a method to declare that it *doesn't handle* certain exceptions, and if checked exception instances would be converted to unchecked ones when bubbling up through such a method. That would be especially nice if code could specify such behavior for exceptions that it itself throws (if it expects to throw `FooException` itself, but it calls a method which *unexpectedly* throws `FooException`, a caller which wants to catch the former probably shouldn't catch the latter. – supercat Jan 13 '14 at 23:23