Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable argument constructor _may_ conflict, but compiles

I have two constructors that compile just fine but I'd expect Java to complain about the possibility of ambiguity.

public Foo(int id, Bar bar, String name, String description){
}

public Foo(int id, Bar bar, String... values){
}

What gives?

like image 990
Sean Connolly Avatar asked Oct 14 '13 18:10

Sean Connolly


People also ask

How does the compiler identify constructors in C++?

In C++, the compiler ensures that an appropriate constructor is called for every elaborated object, but the rules it uses to identify constructors and their arguments can sometimes be confusing.

How to handle variable length arguments in a method?

A method that takes a variable number of arguments is a varargs method. Prior to JDK 5, variable-length arguments could be handled two ways. One using overloaded method(one for each) and another put the arguments into an array, and then pass this array to the method.

How to call a function that takes a variable number of arguments?

The parameter that uses ... must be the last parameter in the parameter list. The following example shows how to call from C# a Visual C++ function that takes a variable number of arguments. The function f can be called from C# or Visual Basic, for example, as though it were a function that can take a variable number of arguments.

What is the use of Var creator in C++?

!!var.creator (args) where var is a variable of some class type T and creator is a constructor for T. In the common case, var will be a reference, and the creation operator will allocate space for an object of class T and then call the object's constructor.


1 Answers

Java allows these methods to exist, because it has rules about which one will be called if both apply. Specifically, the fixed arity method (without ...) will be chosen over the variable arity method (with ...).

The JLS, Section 15.12.2, states the following when determining which method is chosen:

The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing. However, the declaration of a variable arity method (§8.4.1) can change the method chosen for a given method method invocation expression, because a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.

The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

This ensures that a method is never chosen through variable arity method invocation if it is applicable through fixed arity method invocation.

The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

(emphasis mine)

Example code:

class Bar{}

public class Foo{
   public static void main (String [] args){
      Foo main = new Foo(1, new Bar(), "name", "description");
      Foo main2 = new Foo(2, new Bar(), "name");
      Foo main3 = new Foo(3, new Bar(), "name", "description", "otherValues");
      Foo main4 = new Foo(4, new Bar());    
   }

   public Foo(int id, Bar bar, String name, String description) {
      System.out.println("name and description!");
   }

   public Foo(int id, Bar bar, String... values) {
      System.out.println("values!");
   }
}

This prints out:

name and description!
values!
values!
values!

... to show that Java will pick the fixed arity method if it can.

like image 72
rgettman Avatar answered Oct 03 '22 01:10

rgettman