2017-02-01 3 views
2

Gibt es eine Möglichkeit, auf eine Gruppe von Methoden in Java 8 zu verweisen, die ihre Signatur überladen?Methodenreferenzen in Java 8: wird das Überladen unterstützt?

Genauer gesagt, würde ich diesen Code mag arbeiten:

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 
    } 
} 

Ich kann nicht leisten public static void foo (Object x) hinzuzufügen, weil ich eine Menge von Methoden muß eine andere Methode zu übergeben und ich will nicht schreiben Wrapper. Bisher konnte ich dies nur über Reflektion tun (die param.getClass() empfangen kann), aber die Methoden, die ich aufrufen muss, haben unterschiedliche Argumente (> = 1) und jedes Mal, wenn ich sie in ein Array einfügen muss, plus ihre Typen in einem anderen.

+3

Ja Polymorphie wird unterstützt. Und auch nein - das ist kein Polymorphismus, das ist Überlastung **. Und nein, es gibt keine Java-Wires-Methode ruft zur Compilierungszeit bestimmte Methodenüberladungen auf. –

+0

Whops! Ja, ich meine überladen, ich habe die Frage behoben, danke. – zakmck

+1

Es ist tatsächlich nicht möglich, eine Methodenreferenz zu erhalten, die so wirkt, als ob sie auf eine überladene Methode zeigt. Am besten können Sie eine andere Methode wie 'void foo (Object x)' hinzufügen und einen Verbraucher daraus herausholen, aber es wird immer noch diese exakte Methode aufrufen (mit Object-Parameter) und wird niemals zu etwas anderem aufgelöst werden. –

Antwort

5

Methodenreferenzen unterstützen das Überladen mit denselben Regeln wie bei normalen Methodenaufrufen. Wenn Sie eine Consumer<Object> haben, können Sie beliebige Object Instanzen seiner accept-Methode übergeben, das heißt Sie

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

schreiben kann und da Sie

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

nicht schreiben kann, wenn man nur eine foo(int) haben und ein foo(String), es ist auch unmöglich

Consumer<Object> c = OverloadingMethodRef::foo; 

zu schreiben, die einekonstruieren würde 0 vorgibt, willkürliche Object Instanzen zu akzeptieren.

Wenn Sie bereit sind Reflection-Overhead zu akzeptieren, Sie

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"); 

(dies bezieht sich auf java.beans.Statement)

Natürlich können diese zur Laufzeit fehlschlagen kann, wenn sie mit einem nicht unterstützten Argument aufgerufen wird Art.

+0

Danke @Holger. In der Praxis fehlt dies in Java :-) Ich verstehe, dass es mit der statischen Typüberprüfung übereinstimmt, aber immer noch nicht sehr gut (willkürliches Objekt akzeptieren, zur Laufzeit binden und zur Kompilierungszeit eine Warnung ausgeben). Re: Reflexion, verwende ich 'org.apache.commons.lang3.reflect.MethodUtils', einfachere Syntax. – zakmck

Verwandte Themen