10 Replies Latest reply: Jun 18, 2008 3:19 PM by 796440 RSS

    Variable arguments and overloading methods

    807591
      If I have overloaded methods, say:

      double foo(int... args) and double foo(double... args)

      I can do:

      int[] val = {1,2,3,4,5};
      double dd = foo(val);

      I don't get a compiler error, but if I do:

      int a=1, b=2, c=3, d=4, e=5;
      double dd = foo(a,b,c,d,e);

      java complains that foo(int..) and foo(double...) are ambiguous.

      Why?
        • 1. Re: Variable arguments and overloading methods
          807591
          The rules for disambiguating a call to an overloaded method are complicated. I would just accept this as "that's how the ball bounces", but if you want to plow through the details, be my guest: [http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html]
          • 2. Re: Variable arguments and overloading methods
            796440
            >

            [JLS 15.12.2.4 Phase 3: Identify Applicable Variable Arity Methods|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.4]
            and
            [JLS 15.12.2.5 Choosing the Most Specific Method|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.5]
            • 3. Re: Variable arguments and overloading methods
              807591
              This code compiles:
              public class Vararg {
                  public static void main(String[] args) {
                   int a = 1, b = 2, c = 3;
                   foo(a,b,c);
                  }
              
                  private static void foo(double... args) {
              
                  }
              }
              Which tells you that ints being passed as parameters can be treated as doubles as arguments to the method. Thus, when you overload the foo() method with an int version, both versions apply, making it ambiguous.
              • 4. Re: Variable arguments and overloading methods
                796440
                jverd wrote:
                >

                [JLS 15.12.2.4 Phase 3: Identify Applicable Variable Arity Methods|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.4]
                and
                [JLS 15.12.2.5 Choosing the Most Specific Method|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.5]
                I don't feel like unravelling those in detail right now, but I think it's that an int[] cannot be promoted to a double[], so there's no ambiguity there, but an int can be promoted to a double, so that's ambiguous.
                • 5. Re: Variable arguments and overloading methods
                  807591
                  jverd wrote:
                  jverd wrote:
                  >

                  [JLS 15.12.2.4 Phase 3: Identify Applicable Variable Arity Methods|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.4]
                  and
                  [JLS 15.12.2.5 Choosing the Most Specific Method|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.5]
                  I don't feel like unravelling those in detail right now, but I think it's that an int[] cannot be promoted to a double[], so there's no ambiguity there, but an int can be promoted to a double, so that's ambiguous.
                  Just because two versions apply doesn't make it ambiguous. It's ambiguous when there isn't a "most specific method" demo:
                  public class Example {
                      static void f(String x, Object y) {} //version 1
                      static void f(Object x, String y) {} //version 2
                      static void f(Object x, Object y) {} //version 3
                  
                      public static void main(String[] args) {
                          String s = "string";
                          Object o = "object";
                  
                          f(s, o);
                          f(0, s);
                          f(s, s); //ambiguous!
                      }
                  }
                  I define three versions of f. In the first invocation, versions 1 and 3 apply but 1 is the most specific.
                  In the second invocation versions 2 and 3 apply but 2 is the most specific.
                  In the third invocation versions 1 and 2 apply but neither is the more specific than the other, so the call is ambiguous.
                  • 6. Re: Variable arguments and overloading methods
                    807591
                    Thanks for your responses. But I'm a simple person.

                    I take that what you're all saying in your own way is that overloading methods with variable arguments is not a very good idea when the argument list is composed of scalar types, which kind of nullifies the benefit of having the feature in the first place, eh?

                    Regards, perplexed.
                    • 7. Re: Variable arguments and overloading methods
                      807591
                      carentrica wrote:
                      Thanks for your responses. But I'm a simple person.

                      I take that what you're all saying in your own way is that overloading methods with variable arguments is not a very good idea when the argument list is composed of scalar types, which kind of nullifies the benefit of having the feature in the first place, eh?

                      Regards, perplexed.
                      I'm the simple, old-fashioned type, too. But I know that some parts of a language's specification are going to be so complicated that on occasion surprising parsing results will pop out. My advice is that varargs are fine, if not abused, but that there's no payoff from deliberately overloading method names. Why not do this?
                      import java.text.*;
                      
                      public class Example {
                         void crunchInts(int... v) {}
                         void crunchDoubs(double... v) {}
                         void f() {
                             crunchInts(1, 2, 3);
                             crunchDoubs(1.0, 2.0, 3.0);
                             crunchDoubs(1, 2, 3); //works, too!
                         }
                      }
                      • 8. Re: Variable arguments and overloading methods
                        807591
                        carentrica wrote:
                        Thanks for your responses. But I'm a simple person.

                        I take that what you're all saying in your own way is that overloading methods with variable arguments is not a very good idea when the argument list is composed of scalar types, which kind of nullifies the benefit of having the feature in the first place, eh?

                        Regards, perplexed.
                        Nothing says you have to use ints and doubles. Try using objects instead. Test if you get the same results using Integers and Doubles.
                        • 9. Re: Variable arguments and overloading methods
                          796440
                          DrLaszloJamf wrote:
                          Just because two versions apply doesn't make it ambiguous. It's ambiguous when there isn't a "most specific method" demo:
                          Right.

                          I skipped over that part, but I assume the rules on "most specific" will lead to neither one being the winner. IIRC, all the args of one method have to be subtypes of the corresponding args of the other method (roughly).
                          • 10. Re: Variable arguments and overloading methods
                            796440
                            carentrica wrote:
                            Thanks for your responses. But I'm a simple person.
                            I don't know that there is an explanation for this that is both simple and accurate. So if you're unwilling or unable to decipher the relevant part of the JLS, you'll just have to accept the explanation, "Because that's how Java defines it."
                            I take that what you're all saying in your own way is that overloading methods with variable arguments is not a very good idea when the argument list is composed of scalar types,
                            I'm not saying that at all.
                            which kind of nullifies the benefit of having the feature in the first place, eh?
                            Even if your previous statement were true, it wouldn't negate the value of varargs.