• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

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

 
Ranch Hand
Posts: 142
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
(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!
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Larry Olson
Ranch Hand
Posts: 142
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 142
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic