13
public class test {
    test(double[] a)
    {
        System.out.println("in double");
    }
    test(Object a)
    {
        System.out.println("in object");
    }
    public static void main(String args[])
    {
        new test(null);
    }
}

In the above code, I pass null as the constructor argument. As null can be anything, the above code compiles fine. When I run the code I expected it to print in object but it prints in double What is the reason behind this?

NOTE the linked question may not be duplicate because this question is related with primitive datatype vs Object

Eric Alberson
  • 1,116
  • 1
  • 11
  • 23
rocking
  • 4,729
  • 9
  • 30
  • 45
  • It seems like it is using the `double` because it is the first defined constructor. Have you tried defining the constructor with the `Object` parameter first? – Matt Rowland Jun 15 '15 at 16:55
  • 1
    @KErlandsson sorry I dont think its a duplicate of the linked question – rocking Jun 15 '15 at 17:09
  • 4
    @rocking a double[] is not a a primitive. Arrays are objects. `double[] instanceof Object == true`. – K Erlandsson Jun 15 '15 at 17:14
  • @KErlandsson yes true as per the link given by rgettman. my question also fits doube vs object but i can not change as accepted answer is as per double[] vs object – rocking Jun 15 '15 at 17:28

2 Answers2

21

The reason is that Java interprets null as any type, and when choosing the method to invoke, it will choose the most specific method that first the argument types. Because null can be of the type double[] and a double[] is an Object, the compiler will choose the method that takes a double[]. If the choices involved equally possible yet unrelated types, e.g. double[] and String, then the compiler would not be able to choose a method, and that would result in an ambiguous method call error.

The JLS, Section 4.1, states:

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

In practice, the programmer can ignore the null type and just pretend that null is merely a special literal that can be of any reference type.

Community
  • 1
  • 1
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • If I create another constructor which accepts double[] and Number then it does not compile.whats the reason?Do I have to modify my question? – rocking Jun 15 '15 at 16:59
  • @rocking The reason is that neither `double[]` nor `Number` are more specific than each other. `double[]` isn't a subclass of `Number`, and `Number` isn't a subclass of `double[]`. There is no "most specific method", even though both methods are applicable. That is where the ambiguity arises; the compiler doesn't know which one to choose, so it generates an error instead. – rgettman Jun 15 '15 at 17:01
  • double[] is also not related to object i mean its not subclass of object because double is primitive type. so as per your answer is there was `Double` vs `Object' then it will choose for most specific types,isnt? – rocking Jun 15 '15 at 17:07
  • 4
    @rocking Actually, [`double[]` is related to `Object`](https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.10.3). – rgettman Jun 15 '15 at 17:12
  • Every class in java is a sub class to Object class. – Anil Reddy Yarragonda Jun 15 '15 at 17:18
  • 1
    @rocking it's not a `double`, though, it's an array of `double`, and arrays are objects (or, more precisely, `Object`s). – Louis Wasserman Jun 15 '15 at 18:59
9

Both constructors are applicable, because null is convertible to both Object and double[] - so the compiler needs to use overload resolution to determine which constructor to call.

JLS 15.9.3 uses JLS 15.12.2 to determine the "most specific" constructor signature to use, based on which constructor has the most specific parameter types, according to JLS 15.12.2.5. The exact details are slightly obscure (IMO) but in this case the basic rule of thumb of "if you can convert from T1 to T2, but not T2 to T1, then T1 is more specific" is good enough.

double[] is a more specific type than Object, because there's an implicit conversion from double[] to Object, but not vice versa.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • can you tell me how to determine which is most specific type? – rocking Jun 15 '15 at 17:00
  • 2
    @rocking: I've given you a rule of thumb and specification links... I'm not sure what else you would want. – Jon Skeet Jun 15 '15 at 17:04
  • @AnilReddy: Yes, it does. – Jon Skeet Jun 15 '15 at 17:24
  • I am confused,in case of Long vs int, why long constructor is called. As per your thum rule int constructor should be called because long can converted to int but not vice versa – rocking Jun 15 '15 at 17:34
  • 1
    @rocking: that's more complicated due to the primitive vs wrapper part. If you had int and long, it would call the int overload. – Jon Skeet Jun 15 '15 at 17:41
  • int vs long does not compile but int vs Long compiles but constructor calling is done from Long ,shall I post a diiferent question for this or you can answer here? – rocking Jun 15 '15 at 17:45
  • @rocking: Are you passing null as the argument still? If so, that wouldn't work when you've got primitive parameters, quite aside from overloading. – Jon Skeet Jun 15 '15 at 17:49
  • @rocking: Okay, that wasn't at all clear - I assumed you were making a call which would at least be *valid* for both constructors. If you call `new Ideone(1)` then it calls the `int` overload. – Jon Skeet Jun 15 '15 at 17:54
  • @JonSkeet As we are discussing about null so I passed null. if we pass 1 in int vs long then it will call int because by default 1 is of int(hope i am right because in case byte vs int if you pass 1 then also int is called) – rocking Jun 15 '15 at 18:01
  • @rocking: Well, I thought you were talking about constructor overloading, with `null` just being one example. If you're unclear as to why the `int` overload wasn't chosen in that case, you should look up primitives and reference types. But `int` is implicitly convertible to `long` (and thus can be boxed to `Long`). If you had a value of type `byte` but overloads of `int` and `long`, it would still convert to `int` instead of `long`, as `int` is more specific than `long`. – Jon Skeet Jun 15 '15 at 18:41