• Java Overloading rules confusion

    From Wayne@21:1/5 to All on Thu Oct 8 22:47:19 2020
    I have a question on overloading in Java. I find the language
    specifications confusing on this issue.

    Why will this:

    class Foo {
    public static void main ( String[] args ) {
    m(3, 4);
    }
    static void m (double d1, int i2) {
    System.out.println( "m(d,i)" );
    }
    static void m (float f1, int i2) {
    System.out.println( "m(f,i)" );
    }
    }

    Compile and run, producing "m(f,i)", but this:
    class Foo {
    public static void main ( String[] args ) {
    m(3, 4);
    }
    static void m (double d1, int i2) {
    System.out.println( "m(d,i)" );
    }
    static void m (int i1, float f2) {
    System.out.println( "m(i,f)" );
    }
    }

    does not compile and gives this error:
    Foo.java:3: error: reference to m is ambiguous
    m(3, 4);
    ^
    both method m(double,int) in Foo and method m(int,float) in Foo match

    Shouldn't "m(int,float)" be more specific than "m(double,int)"?

    (This works IF you change the first m(double,int) to m(int,double).)

    --
    Wayne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Fri Oct 9 09:01:32 2020
    Am 09.10.20 um 04:47 schrieb Wayne:
    Why will this:

    class Foo {
        public static void main ( String[] args ) {
            m(3, 4);
        }
        static void m (double d1, int i2) {
            System.out.println( "m(d,i)" );
        }
        static void m (float f1, int i2) {
            System.out.println( "m(f,i)" );
        }
    }

    Compile and run, producing "m(f,i)", but this:
    class Foo {
        public static void main ( String[] args ) {
            m(3, 4);
        }
        static void m (double d1, int i2) {
            System.out.println( "m(d,i)" );
        }
        static void m (int i1, float f2) {
            System.out.println( "m(i,f)" );
        }
    }

    does not compile and gives this error:
    Foo.java:3: error: reference to m is ambiguous

    Very interesting!

    From my point of view this is a bug. But probably it is conformant to
    the rules.

    Different widening conversions (float vs. double) do not have different priorities when searching for the most specific method during overload resolution. So both methods in example 2 have one parameter that
    requires a widening conversion.

    But on the other side, widening conversions follow the sequence byte,
    short, int, long, float, double. So int -> float is preferred over int
    double. (This is curious anyways because the first can cause loss of
    precision while the latter does not.)
    So the call is /not/ ambiguous when the different widening conversions
    apply to the /same/ parameter. Then the priority applies.

    Not intuitive, not very helpful, but this seems to be the rules.


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=c3=b8j?=@21:1/5 to Wayne on Fri Oct 9 09:59:47 2020
    On 10/8/2020 10:47 PM, Wayne wrote:
    I have a question on overloading in Java.  I find the language specifications confusing on this issue.

    Why will this:

    class Foo {
        public static void main ( String[] args ) {
            m(3, 4);
        }
        static void m (double d1, int i2) {
            System.out.println( "m(d,i)" );
        }
        static void m (float f1, int i2) {
            System.out.println( "m(f,i)" );
        }
    }

    Compile and run, producing "m(f,i)", but this:
    class Foo {
        public static void main ( String[] args ) {
            m(3, 4);
        }
        static void m (double d1, int i2) {
            System.out.println( "m(d,i)" );
        }
        static void m (int i1, float f2) {
            System.out.println( "m(i,f)" );
        }
    }

    does not compile and gives this error:
    Foo.java:3: error: reference to m is ambiguous
            m(3, 4);
            ^
      both method m(double,int) in Foo and method m(int,float) in Foo match

    Shouldn't "m(int,float)" be more specific than "m(double,int)"?

    (This works IF you change the first m(double,int) to m(int,double).)

    There are some explanation in JLS (other have already elaborated
    on that).

    But I would like to point out the obvious: the first code
    may compile, but it is still bad code.

    Code where the reader needs to remember some subtle
    language rules to understand why the code does what
    it does is bad code.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eric Sosman@21:1/5 to Wayne on Fri Oct 9 09:21:55 2020
    On 10/8/2020 10:47 PM, Wayne wrote:
    I have a question on overloading in Java.  [...]

    Shouldn't "m(int,float)" be more specific than "m(double,int)"?

    Had to spend some time studying JLS 15.12.2.5 to find that the
    answer is "No." There's a lot if niggly detail in the JLS, but for
    me the easiest explanation comes in the introductory section:

    "The informal intuition is that one method is more specific
    than another if any invocation handled by the first method
    could be passed on to the other one without a compile-time
    error."

    Let's try this out with your two versions of m(). Clearly, both
    versions could (in isolation) handle m(3,4) or m('3',4) and many
    other invocations. However, m(3,4.0f) would work only with the
    (int,float) version, but only (double,int) could handle m(3.0,4).
    That is, for each version there is an invocation that it could
    accept but would not work with the other. So (says "informal
    intuition") neither is "more specific" than the other, because
    each has valid invocations the other could not accept.

    Interesting query. Thanks!

    --
    esosman@comcast-dot-net.invalid
    If he's so rich, why ain't he smart?
    One hundred three days to go.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Wayne@21:1/5 to All on Fri Oct 9 22:51:41 2020
    On 10/9/2020 9:59 AM, Arne Vajhøj wrote:
    ...
    But I would like to point out the obvious: the first code
    may compile, but it is still bad code.

    Code where the reader needs to remember some subtle
    language rules to understand why the code does what
    it does is bad code.

    Arne

    I agree. I was trying to post a minimal example that shows
    the issue. It is indeed poor code for any real project.

    --
    Wayne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Wayne@21:1/5 to Eric Sosman on Fri Oct 9 22:51:36 2020
    On 10/9/2020 9:21 AM, Eric Sosman wrote:
    On 10/8/2020 10:47 PM, Wayne wrote:
    I have a question on overloading in Java.  [...]

    Shouldn't "m(int,float)" be more specific than "m(double,int)"?

        Had to spend some time studying JLS 15.12.2.5 to find that the
    answer is "No."  There's a lot if niggly detail in the JLS, but for
    me the easiest explanation comes in the introductory section:

        "The informal intuition is that one method is more specific
        than another if any invocation handled by the first method
        could be passed on to the other one without a compile-time
        error."

    Let's try this out with your two versions of m().  Clearly, both
    versions could (in isolation) handle m(3,4) or m('3',4) and many
    other invocations.  However, m(3,4.0f) would work only with the
    (int,float) version, but only (double,int) could handle m(3.0,4).
    That is, for each version there is an invocation that it could
    accept but would not work with the other.  So (says "informal
    intuition") neither is "more specific" than the other, because
    each has valid invocations the other could not accept.

        Interesting query.  Thanks!


    I appreciate your reply, it does help. Thanks!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)