Question

My question is more on design, The java compiler forces us to catch a checked exception (e.g. FileNotFoundException) but does not forces us to catch an unchecked exception (e.g. NullPointerException). I want to understand the reason, why is compiler designed in such a way?.

The explaination Unchecked Exceptions — The Controversy suggest that it is done for improving readability.

Isn't it a big cost to not to catch runtime exceptions?

Edit: by cost i mean, getting runtime exceptions in live environment rather than at compile time itself. If such exceptions are handled during compilation itself, there is no possibility of a bug leak. The cost of fixing bugs increases with the delay in phase they are detected.

Was it helpful?

Solution 2

Design is all about tradeoffs. It is not feasible to design a system that handles every situation; we have enough trouble designing systems that handle fairly common situations.

The tradeoff between checked and unchecked exceptions seems to me to be a language design issue where this kind of tradeoff is codified; the API designers, system and application both, are allowed to determine whether the catching of a given exception should be mandated by the compiler or not.

  • Does the exception reflect something so important that the caller of this method should not be allowed to just "skip it" and let the program crash?
  • Is the exception something that application programmers are liable to forget to do, and therefore should be forced to at least write catch (Exception e) {} so people can point at them and scream?
  • Does the exception reflect something that an application programmer might well think is a situation handled by the call, but in fact isn't?

It seems to me the kind of flexibility that Java has always been good for -- the API designer is allowed the choice.

OTHER TIPS

The justification for this is actually contained within the Java Language Specification in section 11.2. Here is the relevant exerpt:

11.2. Compile-Time Checking of Exceptions

The unchecked exception classes (§11.1.1) are exempted from compile-time checking.

Of the unchecked exception classes, error classes are exempted because they can occur at many points in the program and recovery from them is difficult or impossible. A program declaring such exceptions would be cluttered, pointlessly. Sophisticated programs may yet wish to catch and attempt to recover from some of these conditions.

Of the unchecked exception classes, run-time exception classes are exempted because, in the judgment of the designers of the Java programming language, having to declare such exceptions would not aid significantly in establishing the correctness of programs. Many of the operations and constructs of the Java programming language can result in exceptions at run time. The information available to a Java compiler, and the level of analysis a compiler performs, are usually not sufficient to establish that such run-time exceptions cannot occur, even though this may be obvious to the programmer. Requiring such exception classes to be declared would simply be an irritation to programmers.

For example, certain code might implement a circular data structure that, by construction, can never involve null references; the programmer can then be certain that a NullPointerException cannot occur, but it would be difficult for a Java compiler to prove it. The theorem-proving technology that is needed to establish such global properties of data structures is beyond the scope of this specification.

As developers we can, at least to a certain extent, control whether or not an unchecked exception can be thrown by the code that we write. For instance, we can avoid encountering a NullPointerException by either checking for null before we attempt the operation which would result in the exception, or we can write our code such that that variable can never be null in the first place. Similarly, we can avoid a NumberFormatException by implementing a sanity check to ensure that our input definitely is a number before we try and parse it as one, etc...

If you've been sensible writing your code, you should rarely (if ever) encounter a RuntimeException (or subclass thereof), so requiring you to put try-catch blocks around every piece of code that might throw one would result in a horiffic mess of hundreds of small try-catch blocks in even simple classes, or one giant catch-everything block, neither of which are particularly desirable, and add lots of largely unnecessary bloat to your code.

Being forced to catch all unchecked exceptions would make even 'simple' operations like using System.out.println() much more verbose.

Let's see what we would have to write to print a blank line to the console if we were forced to catch all unchecked exceptions (Note: this is something of a worst-case scenario, where exceptions are simply propagated instead of handled within the API):

System.out.println();
//         ^ Theoretically this could throw a NullPointerException

So, we'd have to account for that:

try {
    System.out.println();
} catch (NullPointerException e) {
    // In practice this won't happen, but we're forced to deal with
    // it all the same...
}

We're not done yet. We need to see what out is, and how println() works to see if there's anything else we need to handle. out is actually a PrintStream object, so what can we tell about its println() method?

Here's println():

public void println() {
    newLine();
}

This means we now need to see what newLine() does...

private void newLine() {
    try {
        synchronized (this) {
            ensureOpen();
            textOut.newLine();
            textOut.flushBuffer();
            charOut.flushBuffer();
            if (autoFlush)
                out.flush();
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}

Lots more sources of NullPointerExceptions in here, but we've already caught that. interrupt() can (eventually) throw a SecurityException, and can also cause an InterruptedException, so we'll have to handle those two as well.

try {
    System.out.println();
} catch (NullPointerException e) {

} catch (SecurityException e) {

} catch (InterruptedException e) {

}

textOut.newLine() eventually ends up in Writer#write(String, int, int), which deals with a char[], so we immediately have a source of an ArrayIndexOutOfBoundsException as well. It also calls String#getChars(int, int, char[], int), which can itself throw a StringIndexOutOfBoundsException. Gotta handle that too...

try {
    System.out.println();
} catch (NullPointerException e) {

} catch (SecurityException e) {

} catch (InterruptedException e) {

} catch (ArrayIndexOutOfBoundsException e) {

} catch (StringIndexOutOfBoundsException e) {

}

It also calls BufferedWriter#write(char[], int, int), which can throw an IndexOutOfBoundsException...

try {
    System.out.println();
} catch (NullPointerException e) {

} catch (SecurityException e) {

} catch (InterruptedException e) {

} catch (ArrayIndexOutOfBoundsException e) {

} catch (StringIndexOutOfBoundsException e) {

} catch (IndexOutOfBoundsException e) {

}

We're now a six separate Runtime Exceptions from this one method call, and this doesn't include all of the potential exceptions that can pop out of the various native method calls along the way (of which there are several), and doesn't include any subclass of Error either.

If we genuinely were forced to catch all exceptions, Java would be the worse for it.

but does not forces us to catch an unchecked exception (e.g. NullPointerException). I want to understand the reason, why is compiler designed in such a way?.

Because Java would be completely unusable as a language if it were different.

You mention the most glaring example: NullPointerException. That can happen any time you access an instance field or method or access an array. Which is a very large percentage of all lines of Java code. Essentially, a NullPointerException can happen everywhere, and a few others as well (ClassCastException, ArrayIndexOutOfBoundsException).

How would you even be able to write code if you were forced to catch them everywhere? And what would you do in the catch blocks? Logging is right out because it would require a method call, which could throw a NullPointerException, which you'd have to handle...

Frankly, checked exceptions are a failed experiment in language design. No other language has adopted them, and large parts of the Java community avoid them wherever possible.

Runtime Exceptions occurs due to,

  1. Programmers oversight
  2. Bad data

Both of them can be rectified in the code itself. And are not intended to happen. Unlike Checked exception which is intended to happen.

In the below method the exception occurs due to the bad input in run time. Which should have been rectified before invoking the function(Bad data).

Character.toChars(-2);

 public static char[] toChars(int codePoint) {
        if (isBmpCodePoint(codePoint)) {
            return new char[] { (char) codePoint };
        } else if (isValidCodePoint(codePoint)) {
            char[] result = new char[2];
            toSurrogates(codePoint, result, 0);
            return result;
        } else {
            throw new IllegalArgumentException();
        }
    }

The program is not able to compile because there are undeclared exception, which is a FileNotFoundException. In order for the program to work without crashing, that exception must be caught or declared to be thrown.

Because unchecked exceptions don't need to be caught, while checked exceptions do need to be handled. Thus, the compiler "forces" you to catch checked exceptions, and let your unchecked exceptions stay uncaught.

More explanation here: Checked vs Unchecked Exceptions in Java

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top