views:

123

answers:

3

Assume InvalidResourceException is a subclass of ResourceException. Define two methods:

void handleException(ResourceException e) {
  System.out.println("ResourceException " + e.toString());
}
void handleException(InvalidResourceException e) {
  System.out.println("InvalidResourceException " + e.toString());
}

Now the following code:

try {
  throw new InvalidResourceException("invalid resource");
} catch (ResourceException e) {
  handleException(e);
}

prints this:

ResourceException: com.myPackage.InvalidResourceException: invalid resource

But the following code:

   try {
     throw new InvalidResourceException("invalid resource");
   } catch (InvalidResourceException e) {
     handleException(e);
   } catch (ResourceException e) {
     handleException(e);
   }

prints this:

InvalidResourceException:  com.myPackage.InvalidResourceException: invalid resource

This is with Sun's JDK 1.5.0_15.

Is this consistent with the Java standard?

What should this code do?

Exception e = new InvalidResourceException("invalid resource");
handleException(e);

What should this code do?

Exception e = new InvalidResourceException("invalid resource");
if (e instanceOf ResourceException) {
  handleException(e);
} else if (e instanceOf InvalidResourceException) {
  handleException(e);
} else {
  handleException(e):
}
+11  A: 

Yes. It's correct. Overloads are always resolved statically.

Neither of your latter 2 examples will compile as e's static type is Exception, and neither of your overloads accept that type.

Edit:

Note that your final example isn't really a direct analog to the try/catch block. In the try/catch you have two variables called e: one for each catch, and their static types are InvalidResourceException and ResourceException respectively. In your final example you have a single variable named e, and its static type is Exception. If you added new variables and assigned to them with a cast then you'd get the same behavior as your try/catch (though you'd have to lose the final else branch).

Laurence Gonsalves
Resolving overloads is a bit more complicated than simply being "static" -- there's a dynamic aspect as well. See <http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12> for the details.
Steve Emmerson
There is a dynamic aspect to *method invocation* (the section of the JLS you linked to), but *overload resolution* is a strictly static (ie: compile-time) operation. In fact, the part of the JLS you linked to backs this up: the only part that mentions overloads (other that the overview at the beginning) is §15.12.2, "Compile-Time Step 2: Determine Method Signature".
Laurence Gonsalves
+1  A: 

Regarding the first part of your question, the correct method to call is determined at compile time based on the type the variable is declared as. E.g. if you changed the catch statement to catch InvalidResourceException, then the handleException(InvalidResourceException) overload would be called instead.

Regarding the second part of your question, the JVM simply finds the first catch statement that is capable of handling the exception thrown. If you were to throw a ResourceException instead, then the second catch block would be executed.

The third part wont compile, as no suitable handleException() method exists to handle a plain Exception.

The last part will also fail to compile for the same reason as the third part.

Jared Russell
A: 

You are expecting something called "double dispatch" which is not supported by java.

irreputable