Java Reference
In-Depth Information
The third program,
Arcane3
, also looks as though it shouldn't compile. Method
f
is declared to
throw checked exception
CloneNotSupportedException
in interface
Type1
and to throw checked
exception
InterruptedException
in interface
Type2
. Interface
Type3
inherits from
Type1
and
Type2
, so it would seem that invoking
f
on an object whose static type is
Type3
could potentially
throw either of these exceptions. A method must either catch each checked exception its body can
throw, or declare that it throws the exception. The
main
method in
Arcane3
invokes
f
on an object
whose static type is
Type3
but does neither of these things for
CloneNotSupportedException
or
InterruptedException
. Why does the program compile?
The flaw in this analysis is the assumption that
Type3.f
can throw either the exception declared on
Type1.f
or the one declared on
Type2.f
. This simply isn't true. Each interface limits the set of
checked exceptions that method
f
can throw.
The set of checked exceptions that a method can
throw is the intersection of the sets of checked exceptions that it is declared to throw in all
applicable types
, not the union. As a result, the
f
method on an object whose static type is
Type3
can't throw any checked exceptions at all. Therefore,
Arcane3
compiles without error and prints
Hello world
.
In summary, the first program illustrates the basic requirement that
catch
clauses for checked
exceptions are permitted only when the corresponding
try
clause can throw the exception in
question. The second program illustrates a corner case where this requirement does not apply. The
third program illustrates the interaction of multiple inherited
tHRows
clauses, which reduces rather
than increases the number of exceptions that a method is permitted to throw. The behaviors
illustrated by this puzzle don't generally cause subtle bugs, but they can be a bit surprising the first
time you see them.
< Day Day Up >
Search WWH ::
Custom Search