rationale behind Java's exception hierarchy - java

I find Java's exception hierarchy confusing. Throwable is divided into Error and Exception, and RuntimeException inherits from Exception.
Error is an unchecked exception. Why doesn't Error inherit from RuntimeException then?
Exception is a checked exception. RuntimeException is an unchecked exception, yet it inherits from Exception. Doesn't this violate the Liskov-Substitution-Principle?
Wouldn't it make more sense if Throwable were divided into Exception (checked) and RuntimeException (unchecked), and Error would inherit from RuntimeExeption?

I find Java's exception hierarchy confusing. Throwable is divided into Error and Exception, and RuntimeException inherits from Exception.
A Throwable is anything that can be used to unwind the call stack. This should include some VM level fault (flagged by an Error) and something application specific (flagged by an Exception)
Error is an unchecked exception. Why doesn't Error inherit from RuntimeException then?
Simply because Errors are not Exceptions. There wouldn't be any point in actually "catching" an Error. For eg. What would you do after catching an OutOfMemoryError. Errors are meant to flag something seriously happened at the VM level which is not necessarily handle-able by the programmer
Exception is a checked exception. RuntimeException is an unchecked exception, yet it inherits from Exception. Doesn't this violate the Liskov-Substitution-Principle?
Not really. What the implementors were trying to say was that Exceptions MUST always be checked. Your code will be cleaner if all your methods declare what sort of application/library Exceptions they throw. RuntimeExceptions should only be thrown in case of more general / dynamic situations such as a NullPointerException where the developer might not have coded for the case but is a serious bug which is not exactly something mentioned in the application spec.

The design of exception handling in the two most popular object-oriented frameworks (Java and .NET) is predicated upon the notion that the question of whether to handle a particular exception should depend primarily upon its type, and that the types of exceptions one will want to catch are going to have a hierarchical class relationship. I think Java and .NET do things that way because C++ did it that way, and C++ did it that way because of a desire to avoid hard-wiring any non-primitive types hard-coded into the language. In the absence of a hard-coded type to which all exceptions may be cast, it's impossible for a catch statement to know anything about any exception type for which it is not explicitly prepared. If it will only make sense to catch exceptions one can decode, a catch statement will be able to sensibly act upon those types, and only those types, which derive from the one in the statement.
In retrospect, it probably would have been better to have the decisions of what exceptions should be acted upon and/or resolved by particular catch statements be determined by some means other than the class hierarchy. Among other things, a single attempt to invoke a method may fail because of multiple problems; if that happens, every catch which is associated with any of those problems should trigger, but only when all of the problems have been resolved should normal execution resume. Unfortunately, neither Java nor .NET has any mechanism to achieve such behavior.
With regard to the top-level layout of the hierarchy, I think there was an assumption that every kind of exception that might be thrown by a method would either always be expected by the immediate calling code or never expected by any calling code. Exceptions of the latter type were classified under Error or RuntimeException, while those of the former type were placed elsewhere. In practice, the question of whether an exception is expected by a method's caller should be independent of its place in the hierarchy or even the exception type. The fact that a method is declared as throws FooException does not mean that calling code is always going to expect that the exception could occur. It's very common for code to call a method which is declared as throwing an exception but believe that the circumstances surrounding the call are such that in practice that the particular call won't ever throw.. If the exception does occur, it should behave like an unexpected exception, even if an outer execution context is expecting to catch an exception of that type. Unfortunately, the exception handling mechanisms are what they are, and I don't expect any major overhaul.

I think that even better hierarchy is
Throwable
Exception
CheckedException
RuntimeException
Error
This hierarchy separates Exceptions and Errors (as #Paarth said) and makes it possible to catch all checked exceptions only (without runtime exceptions). But it seems that James Gosling thought different...

Error is not a subclass of Exception because it is not meant to catch (Once an error is occurred usually the program is no longer expected to function). So error should have more higher place in hierarchy as I believe.
It should not violate Liskov substitution because RuntimeException can be catched if you want, but only it's not enforced.

Related

Why do you need to catch "Exception" but not the Subclass "RuntimeException"?

The below picture shows that "Checked" and "Unchecked" Exceptions are subclasses of Exception. I find it confusing that you need to catch an Exception but you don't need to catch a RuntimeException, which directly inherits from Exception. Is there a reason that the devs didn't let us throw Exceptions without needing to catch them?
More specifically: Why can you ignore only RuntimeExceptions and it's children? Why wasn't there a Class introduced called CheckedException extends Exception and you only need to catch it and it's children?
The confusing part is, that you can throw everything below RuntimeException without issue, but when you move up to Exception in the hierarchy, you need to catch it at some point. This is confusing because "abstraction" normally works otherwise. The more you move up, the simpler and more meta everything gets. This is not the case here. The more you move up, the more you have to do (like, putting try/catch after reaching Exception).
If Exception was unchecked then you could implicitly cast checked exceptions to unchecked ones, which would mean that you could throw checked exceptions without catching them like:
public void f() {
Exception e = new IOException();
throw e;
}
and also with overriding methods, if you throw a more specific exception, you can add the requirement to catch the exception that wasn't in the superclass:
public void f() throws Exception {
}
...
#Override
public void f() throws IOException {
}
Suppose they designed it the other way. We have a CheckedException class, and subclasses of that need to be handled, but not other subclasses of Exception.
Now we call a method that might throw an arbitrary Exception:
public static void example() {
functionThatThrowsException();
}
Do we need to handle it? Yes, because that Exception might be a CheckedException. If we didn't need to handle it, we'd be bypassing the checked nature of checked exceptions.
A throwable type with checked descendants must be treated as checked, so checkedness naturally propagates up the inheritance hierarchy. Contrapositively, an unchecked throwable type cannot have checked descendants, so uncheckedness naturally propagates down. This makes it natural to make checkedness the default, and single out specific classes and their descendants as unchecked.
CheckedException (Which does exist) and RuntimeException both extend Exception. Because of this, if something throws a generic Exception (which is always a bad idea), there is no way to tell if the exception could be one or the other, so you have to catch it in case it's a checked one. If you think of the hierarchy in this way, it actually does get simpler the farther up you go.
You seem to have the idea that checked exceptions are more "complex" because you have to do more to work around them. This isn't too healthy a way of thinking about it. Instead, consider this: Exceptions are problems with the program itself - the code. We need to find these exceptions and handle them properly. After already having this concept of exception handling, we discover that there are some problems that we simply can't predict.
"How was I supposed to know the user would enter 'meow' when asked for an integer! I shouldn't have to code around that!" And so, NumberFormatException was born, and you don't have to catch it because it's a "logical error", not an issue caused by bad code (Although, arguably, it might be considered bad code if you don't handle this situation in some way).
In short, reverse your thinking. Exceptions are problems with the program that can be handled. There are some exceptions, however, that are unexpected and are a result of bad design more than incorrect code. Thus there is the addition of RuntimeExceptions which cannot possibly be expected to occur, but certainly can occur.
Perhaps it would help to not think of exception classes in terms of inheritance but simply disjoint sets of classes, one set is checked and other is not. You're right that there could be a CheckedException class allowing us to check only when explicitly intended.
However having the broader/generalized range checked helps in enforcing the catch or specify pattern. Having checked exception allows a reader of the code to figure out quickly that this piece of code needs special attention and enforcing their handling at compile time reducing the runtime bugs.
We can throw any kind of exception, checked or unchecked. If Exception or any super class of RuntimeException were to be set as checked exception then all the sub classes would become checked exceptions. As compiler is most likely checking if an instance of exception or a class in the throws clause derives from a class. It could easily have done that by checking for a specific package which probably would have been more appropriate as being checked or unchecked has simply nothing to do with the inheritance.

Definition of checked Java exception?

I see that one definition can be this:
Generally RuntimeExceptions are exceptions that can be prevented
programmatically.
But that is still not the definition of a checked exception. I thought checked exceptions were "exceptions that can be handled at compile-time". Is that correct and/or can you tell me more?
I also read this on the site, can you explain the quote?
Many people say that checked exceptions (i.e. these that you should
explicitly catch or rethrow) should not be used at all.
Java: checked vs unchecked exception explanation
Can I just learn what the definition is? I also read somewhat unexpectedly:
NumberFormatException is unchecked`
But I would think that NumberFormatException is checked since I would handle that at compile-time. Can you please help me understand? I've done some Java programming but I never wrote my own exception class, why would I need that?
Update
A definition is given is the SCJP book by Sierra / Bates:
A checked exception is defined as any subclass of java.lang.Throwable (including Throwable itself) which is not a subclass of java.lang.Error or java.lang.RuntimeException. The guidelines you saw are just that, guidelines, designed to help you understand the intent of runtime exceptions.
See the Java Language Specification, section 11.1.1
The unchecked exception classes are the runtime exception classes and the error
classes.
The checked exception classes are all exception classes other than the unchecked
exception classes. That is, the checked exception classes are all subclasses of
Throwable other than RuntimeException and its subclasses and Error and its
subclasses.
A more broad definition is:
CheckedExceptions are exceptions that you have to deal with explicitly. You either have to declare you can throw it or catch it and deal with it. Cunningham Wiki
As a result RuntimeExceptions are not checked, but NumberFormatException is checked if a method declares that it throws it and you are forced to catch or re-throw.
Checked exceptions allow you to verify at compile time that you are either handling exceptions or declaring them to be thrown.
Some do suggest avoiding checked exceptions. However, this does not eliminate the cost of managing exceptions. It shifts and magnifies it, from compile-time to run time and debug time.
From the Java tutorial:
[P]rogrammers may be tempted to write code that throws only unchecked exceptions or to make all their exception subclasses inherit from RuntimeException. Both of these shortcuts allow programmers to write code without bothering with compiler errors and without bothering to specify or to catch any exceptions. Although this may seem convenient to the programmer, it sidesteps the intent of the catch or specify requirement and can cause problems for others using your classes.
Unchecked exceptions allow you to not have to declare everywhere exceptions that can occur almost anywhere. From the Java tutorial:
Runtime exceptions can occur anywhere in a program, and in a typical one they can be very numerous. Having to add runtime exceptions in every method declaration would reduce a program's clarity. Thus, the compiler does not require that you catch or specify runtime exceptions (although you can).
NumberFormatException is unchecked because it falls within this camp. In many applications, number format exceptions can occur almost anywhere, and be numerous.

No compilation error on Runtime Exceptions. why?

In the Below example if RuntimeException is replaced with some other exception then compiler throws the compilation error. But for Runtime Exception's it is not throwing anything. Why? Please explain.
class A {
public void process() {
System.out.print("A,");
}
}
class B extends A {
public void process() throws RuntimeException {
System.out.print("B,");
throw new RuntimeException();
}
public static void main(String[] args) {
A a = new B();
a.process();
}
}
RuntimeExceptions are what we call "unchecked exceptions".
This means, the compiler does not check whether they're caught in code.
The reason for this is, we have some exceptions that we often prefer to not have to handle or declare. For instance, NullPointerExceptions can potentially be thrown at so many places in the code, that it's more convenient if we only handle them, if we explicitly decide to.
See also:
In Java, when should I create a checked exception, and when should it be a runtime exception?
Unchecked Exceptions — The Controversy
Java unchecked/checked exception clarification
This has to do with checked vs unchecked exceptions. Here is another brief explanation
That's why it's called RuntimeException :)
Seriously, RuntimeException (all all exceptions inheriting from it) are called "unchecked exceptions" and the whole point is that they are NOT checked by the compiler.
This is required of a compiler, due to the following requirement in the Java Language Specification
11.2.5 Why Runtime Exceptions are Not Checked
The runtime exception classes
(RuntimeException and its subclasses)
are exempted from compile-time
checking 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 runtime
exceptions. The information available
to a compiler, and the level of
analysis the 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 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.
Unlike checked exceptions, runtime exceptions (or unchecked exceptions) do not define a contract between the caller and the called method, for they usually indicate an erroneous condition, that is often resolved by the caller if it were to obey the contract.
If a compiler were to be given the task of enforcing such a contract, it would result in additional complexity (in the language itself and in the code that people write). Imagine, enforcing every method to check for null arguments and requiring programmers to throw such exceptions (and also declare such exceptions in the throws clause). The easier way out, is to specify a contract that states that a method will not operate on null arguments and that a caller should expect to catch NullPointerExceptions; if the caller wants to avoid this scenario, it must check the arguments before invoking the method.
The reason for that is the fact that checked exceptions declared for the overriding method must match with the signature of the method overridden. Otherwise the code won't compile due to the method signature mismatch. It is fine when you declare unchecked exceptions in overriding method, because these exceptions as the name suggest are not checked by the compiler.

do checked exceptions happen at run-time?

I am confused with the naming of runtime exception of java.
Those checked exceptions, like SQLexception, also happen during the execution of a program.
Why only those unchecked ones called runtime exception?
It is probably I have misunderstanding of "runtime".
Thank you for any advices.
I can understand your confusion. All exceptions occur at runtime!
The only reason I can come up with for naming the class that way, is that it clarifies that it is an exception that doesn't have to be dealt with at compile time.
As opposed to all other so called "checked" exceptions, RuntimeExceptions doesn't require the programmer to declare the exception to be thrown using a throws clause.
RuntimeException is a subclass of java.lang.Exception. RunTimeExceptions are almost always the result of a programming error or/and invariants not being met (Nulls being passed when they shouldn't), so you do not have to catch them like java.lang.Exception (which is Checked Exceptions). You don't catch them because there's little the Run Time system could do to recover.
I think the phrase runtime just means they happen when the program is running (obviously!!) and crucially the compiler doesn't force checks to be built into the code as with Checked Exceptions. I think it's an example of where it's difficult to name a class appropriately e.g. I guess they could have Exceptions unchecked by default and called it Exception. Then subclassed it to provide CheckedException - everyone calls java.lang.Exception a Checked Exception, but it's not clear from the Class Name. But they didn't and we have:
> java.lang.Exception is referred to as "Checked Exception"
> java.lang.RuntimeException is referred to as "Unchecked Exception"
Yes, the naming is a bit confusing but it reflects the nature of an Exception being handled, not its time of occurrence.
All the exceptions occur at runtime. However, you are forced to handle the behavior of your program yourself for a specific type of exceptions i.e. CheckedExceptions. The reason is that these types of exceptions are more likely to occur. Example FileNotFoundException.
On the other hand, UnchekedExceptions[aka RuntimeExcetions] are less likely to occur and the programmer is not forced to handle those while writing the program. Ex: ArithmeticException.

How to identify checked and unchecked exceptions in java?

While reading about exception, I will always come across checked exceptions and unchecked exceptions, So wanted to know how to distinguish that which is what?
Edit: I want to know if i create any exception class then how can i create as a checked or as an unchecked?
and what is the significance of each?
All Throwables except subclasses of java.lang.RuntimeException or java.lang.Error are checked. Properly, in Java, "exceptions" are subclasses of java.lang.Exception, "errors" are subclasses of java.lang.Error and java.lang.Throwable is not usually subclassed directly.
Programs are not supposed to create their own Error subclasses (though the documentation is rather ambiguous on that) so generally you always create Exceptions, using a RuntimeException if you don't want it to be checked.
To know at run-time if you have a checked exception you could use:
if(throwable instanceof Exception && !(throwable instanceof RuntimeException)) {
// this is a checked Exception
}
A checked exception is one which must be either handled in a catch clause, or declared as being thrown in the method signature; the compiler enforces this. Generally, one uses checked exceptions for exceptions which should be handled by the calling code, while unchecked exceptions are for conditions which are the result of a programming error and should be fixed by correcting the code.
That said there is much debate in the Java community about the efficacy of using checked exceptions vs. unchecked exceptions everywhere - a subject way to deep to discuss in this answer.
EDIT 2012-10-23: In response to comments (which are quite valid), to clarify, the following would be what is required to determine if a captured Throwable is a checked Throwable as opposed to a checked Exception:
if(obj instanceof Throwable && !(obj instanceof RuntimeException) && !(obj instanceof Error)) {
// this is a checked Throwable - i.e. Throwable, but not RuntimeException or Error
}
If the object in question is known to be an instance of Throwable (e.g. it was caught), only the second part of the above 'if' is needed (e.g. testing for Throwable is redundant).
See the Java Language Spec, chapter 11:
The unchecked exceptions classes are the class RuntimeException and its subclasses, and the class Error and its subclasses. All other exception classes are checked exception classes. The Java API defines a number of exception classes, both checked and unchecked. Additional exception classes, both checked and unchecked, may be declared by programmers.
You could check this via instanceof at runtime, though I don't really see where this would be useful.
As to the second part of your question:
checked exception represent expected error conditions, which can occur during normal program execution and therefore always have to be handled programatically (which the compiler enforces)
unchecked exception represent unexpected error conditions and signify an abnormal state of your program, due to invalid input, bugs or runtime restrictions (eg memory); the compiler won't force the programmer to handle these, ie you only have to care for them if you know of their occurrence
Java checked vs unchecked exception
Error is internal VM error and usually you can not manage it.
Exception - you are able to catch and handle it
Checked vs Unchecked
checked exception is checked by the compiler and as a programmer you have to handle it using try-catch-finally, throws
unchecked exception is not checked by the compiler but you optionally can manage it explicitly
IntelliJ IDEA's Type Hierarchy tool is useful when you want to find more
If the exception class is a subclass of RuntimeException, it's not checked and does not have to be declared for functions or caught, etc. Error exceptions also do not have to be declared/caught. Is that what you're asking?
Quite sure this will have been asked and answered before, but for the sake of it, it is covered quite nicely here: http://www.javapractices.com/topic/TopicAction.do?Id=129.
Strictly speaking, unchecked exceptions will always extend RuntimeException whereas checked exceptions do not. The mentioned link explains when to use either.
As their name indicates, callers are obliged to deal with checked exceptions, typically handling them (try/catch) or passing them further up the stack. Unchecked exceptions are usually deemed to be caused by elements outside of the caller's control.
package practice;
import java.io.IOException;
class Practice
{
public static void main(String args[])
{
Exception n=new NullPointerException();
if(n instanceof RuntimeException)
{
System.out.println("this is a runtime(unchecked) exception");
}
else
{
System.out.println("this is not a compiletime(checked) exception");
}
}
}

Categories

Resources