-1

So I ran across this situation today while writing some unit tests. Its somewhat an esoteric question, but I don't understand why this code functions this way. Here's the code:

public class Test {
    public static void main(String[] args) {
        doSomething(null);
    }

    public static void doSomething(Class<?> c) {
        System.out.println("Parameterized with Class<?>");
    }

    public static void doSomething(Object o) {
        System.out.println("Parameterized with Obejct");
    }
}

In the above example, the call to doSomething will resolve to the method parameterized with Class, but null doesn't contain any of the methods within Class. Why does this happen? The behavior is the same if parameterized with the raw type.

Mark W
  • 2,791
  • 1
  • 21
  • 44
  • 4
    Null is `instanceof` everything (at least from the standpoint that `null instanceof AnyClass` returns true, seee @yshavits answer). Since `Class` is more specific than `Object`, null will identify as instance of `Class`. If you make another method with a parameter "on the same level", i.e. `String`, you'll get a compile error since it can't determine a more specific one. – Kayaman May 20 '14 at 19:44
  • 2
    @Kayaman null is `instanceof` _nothing_, but it's implicitly-castable to anything. instanceof actually doesn't factor in here, as it's a runtime check while method resolution happens at compile time. – yshavit May 20 '14 at 19:45
  • Are you sure about "`null` doesn't contain any of the methods within Class"? Assigning `null` to a `Class>` variable should be possible and then it should have all the methods as well. – Niklas B. May 20 '14 at 19:46
  • @NiklasB. what I mean by that is you cant invoke anything on a null reference, but Kayaman was certainly right. Adding another overload which accept some other reference type results in ambiguity. – Mark W May 20 '14 at 19:47
  • @yshavit True, my comment was poorly worded. – Kayaman May 20 '14 at 19:47
  • @MarkW Well you *can* invoke any method on it, you just get a runtime exception (not a type error though) – Niklas B. May 20 '14 at 19:48

1 Answers1

3

This has to do with method resolution, as defined in JLS 15.12.2. This happens at compile-time, and the compiler basically picks the most specific method that's applicable. In your case, both methods are applicable (since null can be cast to either Class<?> or Object), but the Class<?> version is more specific.

The bit about null being applicable comes from JLS 4.1:

The null reference can always be assigned or cast to any reference type (§5.2, §5.3, §5.5).

Specificity is defined in JLS 15.12.2.5. It can be a bit overwhelming, but basically works as you'd expect: Class<?> is a more specific type than Object (it's a subtype of Object), and so works to make that method overload more specific.

yshavit
  • 42,327
  • 7
  • 87
  • 124
  • I feel bad about accepting your answer, but only for want of a posted answer from kayaman. Considering its absence, I'll accept under direst. Good answer none the less. – Mark W May 20 '14 at 19:52