Search code examples
javaclassconstructorvariable-length-array

Multiple constructors with variable argument parameters


Given these two constructors:

SomeClass(int... params)
{
   // Do things
}

SomeClass(long... otherParams)
{
   // Do other things
}

What happens when an object foo is instantiated?

SomeClass foo = new SomeClass();

Is the undefined default constructor somehow called? Or is one of those constructors with an empty array called? If so, what’s the precedent?

I’ve done some basic testing and found that if a constructor without parameters is defined then that will be called. Otherwise, it appears that an ambiguous one is called.


Solution

  • As per this very good answer in "Varargs in method overloading in Java" question below are the rules used by Java compiler for selecting the method signature to invoke. They are based on JLS 5.3. Method Invocation Conversion docs.

    1. Primitive widening uses the smallest method argument possible
    2. Wrapper type cannot be widened to another Wrapper type
    3. You can Box from int to Integer and widen to Object but no to Long
    4. Widening beats Boxing, Boxing beats Var-args.
    5. You can Box and then Widen (An int can become Object via Integer)
    6. You cannot Widen and then Box (An int cannot become Long)
    7. You cannot combine var-args, with either widening or boxing

    Because both constructors are var-args (rule 7) the compiler will fall back to other rules and select the method that uses the smallest type (rule 1).

    You can confirm this behaviour with following code:

    static class SomeClass {
      SomeClass(long... value) { System.out.println("Long"); }
      SomeClass(int... value) { System.out.println("Int"); }
      SomeClass(byte... value) { System.out.println("Byte"); }
    }
    
    public static void main(String[] args) throws Exception {
      SomeClass o = new SomeClass(); // Byte
    }
    

    The precise subtype relation between primitives types used in rule 1 is explained in JLS 4.10.1. Subtyping among Primitive Types.

    The following rules define the direct supertype relation among the primitive types:

    • double >1 float

    • float >1 long

    • long >1 int

    • int >1 char

    • int >1 short

    • short >1 byte