aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes try {} body vs method body - inconsistency in compiler check for Exception being thrown Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "try {} body vs method body - inconsistency in compiler check for Exception being thrown" Watch "try {} body vs method body - inconsistency in compiler check for Exception being thrown" New topic
Author

try {} body vs method body - inconsistency in compiler check for Exception being thrown

Larry Olson
Ranch Hand

Joined: Feb 03, 2009
Posts: 142
(1)
public void go() throws IOException {}
compiles fine, even though there is nothing in the method that will throw an IOException.

But
(2)
try {} catch(IOException e) {}
results in a compile error saying that "java.io.IOException is never thrown in body of corresponding try statement"

So why at (1) the compiler allows the method to declare "throws IOException", even though IOException isn't thrown anywhere in the body of the method,
whereas at (2) it does care about if IOException is thrown in the body of the try statement ?

This doesn't seem consistent. Shouldn't at (1) the compiler complain something like "java.io.IOException is never thrown in the body of the go() method" ? Why the partiality?

I am looking for a logical explanation on why it was designed this way (it was designed that way or this is how it is in the Java Language Specification, isn't the answer I am looking for). Thanks!
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40


Case 2 is not allowed because the catch is not reachable. There are no non-reachable issues with case 1.

Furthermore, the method may be overridden. So, even though the base class doesn't throw the exception, there may be a sub class that does -- and defining it in the base class enforces the interface requirement (to catch the IO exception).

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Larry Olson
Ranch Hand

Joined: Feb 03, 2009
Posts: 142
Thanks for the quick feedback.

But your explanation of NON-reachability doesn't seem to hold water. For example take the case below:

(3)
try {} catch(Exception e) {}

In the case above, obviously there is no Exception being thrown inside the body of try and the catch clause will never be reached. So it is logically non-reachable. But now the compiler doesn't complain. Why? I am confused.

Your explanation about the public interface requirement does make sense though. For example the designer of the method might decide to add something later that will thrown an IOException and at that time he doesn't want all clients to make changes to their code.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40

Larry Olson wrote:
(3)
try {} catch(Exception e) {}

In the case above, obviously there is no Exception being thrown inside the body of try and the catch clause will never be reached. So it is logically non-reachable. But now the compiler doesn't complain. Why? I am confused.


This is allowed because Exception is a super class of RuntimeException, which is used for unchecked exceptions. No checking is done for these exceptions, hence, the compiler assumes reachability.

Henry
Larry Olson
Ranch Hand

Joined: Feb 03, 2009
Posts: 142

This is allowed because Exception is a super class of RuntimeException, which is used for unchecked exceptions. No checking is done for these exceptions, hence, the compiler assumes reachability.


But Exception is a catch all, right? It includes both checked and unchecked exceptions. I do understand that it includes RuntimeException. But how can you assume that only RuntimeException will be thrown? I do understand no checking is done for RuntimeException, but again Exception also includes checked ones for which the compiler has to do the check. How can the compiler assume that only RuntimeException will be thrown if we have Exception in the catch clause? Shouldn't the compiler err on the side of safety?

Also look at the case of where you extend the Exception class to create a new Exception. But look at how differently the compiler now treats this exception It assumes that it is a checked exception, though logically Exception includes RuntimeException, right? .

So in one case the compiler errs on the side of checked while creating new exceptions, whereas on the other hand it errs on the side of unchecked when you have it in a catch clause. Shouldn't it always error on the side of safety i.e. checked in both cases? Why the inconsistency?

Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40

Larry Olson wrote:
But Exception is a catch all, right? It includes both checked and unchecked exceptions. I do understand that it includes RuntimeException. But how can you assume that only RuntimeException will be thrown? I do understand no checking is done for RuntimeException, but again Exception also includes unchecked ones in which compiler has to do the check. How can the compiler assume that only RuntimeException will be thrown if we have Exception in the catch clause? Shouldn't the compiler err on the side of safety?


That is how it is defined in the specification. If you throw an exception, the compiler must check that it is declared or is a runtime exception. Hence, if you try to throw an Exception instance, it is not allowed (assuming that no checked exceptions are declared). On the other hand, if you catch an Exception, it is allowed because it is possible that exception of that type can be thrown.

In other words, all RuntimeExceptions are Exceptions (hence, catch is allowed), but not all Exceptions are RuntimeExceptions (hence, throw is not allowed).

This may initially sound confusing, but it makes sense. Catching the superclass Exception, or the superclass Throwable, for default (last) cases, is pretty common.

Larry Olson wrote:
Also look at the case of where you extend the Exception class to create a new Exception. But look at how differently the compiler now treats this exception It assumes that it is a checked exception, though logically Exception includes RuntimeException, right? .


No. When you inherit from the Exception class, you are not inheriting from RuntimeException -- this the compiler can easily confirm.

Henry
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: try {} body vs method body - inconsistency in compiler check for Exception being thrown