Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method references in Java 8: is overloading supported?

Is there any way to refer to a group of methods in Java 8, which varies their signature the overloading way?

More precisely, I'd like this code to work:

public class OverloadingMethodRef
{
    public static void foo ( int x ) {
        System.out.println ( "An integer: " + x );
    }

    public static void foo ( String x ) {
        System.out.println ( "A String: " + x );
    }

    /**
     * I want it to work without this
     */
//  public static void foo ( Object x ) {
//      if ( x instanceof Integer ) foo ( (int) x ); else foo ( ( String ) x );
//  }

    public static void main ( String[] args )
    {
        // Compile error, it wants a precise reference to one of them
        Consumer<Object> c = PolymorphicMethodRef::foo; 
        foo ( "bla" ); // despite it could get it
        foo ( 1 ); // and here too
    }
}

I cannot afford to add public static void foo ( Object x ), because I have a lot of methods to pass to another method and I don't want to write wrappers. So far, I could do this only via reflection (which can receive param.getClass()), but the methods I have to call have varying arguments (>=1) and every time I need to put them in an array, plus their types in another.

like image 513
zakmck Avatar asked Feb 01 '17 17:02

zakmck


1 Answers

Method references support overloading using the same rules as with ordinary method invocations. When you have a Consumer<Object>, you can pass arbitrary Object instances to its accept method, i.e. you can write

Consumer<Object> c = /* some expression producing it*/; 
c.accept(new JButton());
// or just
c.accept(new Object());

and since you can’t write

foo(new JButton());
// or
foo(new Object());

when you only have a foo(int) and a foo(String), it’s also impossible to write

Consumer<Object> c = OverloadingMethodRef::foo;

which would construct a Consumer pretending to accept arbitrary Object instances.

If you are willing to accept Reflection overhead, you can use

Consumer<Object> c=o -> {
    try {
        new Statement(OverloadingMethodRef.class, "foo", new Object[]{o}).execute();
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
};
c.accept(42);
c.accept("bla");

(this refers to java.beans.Statement)

Of course, this can fail at runtime when being invoked with an unsupported argument type.

like image 193
Holger Avatar answered Sep 21 '22 18:09

Holger