2016-04-15 13 views
12

Ich habe mehrere predifined statische "Prozessoren" das gleiche Verfahren implementiert, zum Beispiel:Static Referenz (mit ::) auf ein Verfahren zurückkehr eine Schnittstelle

default double process(double num){ 

Probe:

public class Test { 
    public static void main(String[] args) { 
     test(Test::processor1, 1d); 
     test(Test::processor2, 1d); 
    } 

    static double processor1(double num){ 
     return num * 10; 
    } 

    static double processor2(double num){ 
     return num * 20; 
    } 
    //... 

    static void test(Function<Double, Double> f, double d){ 
     // Do something util here 
     System.out.println(f.apply(d)); 
    } 
    ... 

Jetzt vorstellen dass ich einige Objekte habe, die eine Liste von zusätzlichen "Prozessoren" bereitstellen können.

Ich versuche eine interface zu verwenden, um diese zusätzlichen "Prozessoren" zu definieren.

static interface IProcessor{ 
     double process(double num); 
    } 

Implementierung eines Objekts mit zusätzlichen "Prozessoren":

static class SomeObject{ 
     // Just return one but should be a list... 
     static IProcessor getExtraProccessors(){ 
      return new IProcessor(){ 
       public double process(double num){ 
        return num * 30; 
       } 
      }; 
     } 
    } 

Bis hier alles kompiliert und funktioniert einwandfrei. Aber jetzt stecke ich fest.

Mit SomeObject::getExtraProccessors Ich habe einen Verweis auf eine statische Methode, die eine Schnittstelle zurückgibt, wie kann ich die Methode der Schnittstelle aufrufen?

Mein erster Versuch war mit

test(SomeObject::getExtraProccessors::process, 1d); 

Aber das kompiliert keinen So The target type of this expression must be a functional interface

geben Sie bitte könnten Sie mir sagen, ob es möglich, diese und wenn ja, wie ? Und wenn es nicht möglich ist, wie soll ich es tun?

+2

Sie könnten 'DoubleUnaryOperator' anstelle von' Funktion 'und anstelle von' verwenden IP-Prozessor ". –

+1

Sie müssen keine anonyme innere Klasseninstanz von 'IPprocessor 'erstellen, sondern geben ein Lambda zurück:' return n -> n * 30; '. Und wenn Sie eine Liste benötigen: return 'Arrays.asList (n -> n * 30, n -> n/2, ...)'. Wie auch @PaulBoddington sagte, ist 'DoubleUnaryOperator' die Schnittstelle, die von Java zur Verfügung gestellt wird, um an einem einzelnen' doppelten' Operanden zu arbeiten. –

Antwort

7
test(SomeObject.getExtraProccessors()::process, 1); 
  • SomeObject.getExtraProccessors() gibt eine Instanz der funktionellen Schnittstelle IProcessor.
  • SomeObject::getExtraProccessors ist eine Methodenreferenz auf die statische Methode getExtraProccessor der SomeObject Klasse.
3

Wie wäre es ein Lambda-Ausdruck statt Methode Referenz verwendet:

test(d-> SomeObject.getExtraProccessors().process(d), 1d); 
2

Ich glaube, Sie brauchen nicht eine anonyme innere Klasse Instanz zu erstellen, die IProcessor implementiert. Eigentlich, wenn Sie mit einer double arbeiten, benötigen Sie die IProcessor Schnittstelle überhaupt nicht. Java bietet die DoubleUnaryOperator Schnittstelle, die genau dafür gedacht ist.

Wenn Sie eine Liste von „Prozessoren“ zurückkehren wollen, dann könnte man es auf diese Weise tun:

static class SomeObject { 

    static List<DoubleUnaryOperator> getExtraProccessors() { 
     return new ArrayList<>(Arrays.asList(Test::processor1, Test::processor2)); 
    } 
} 

Dann gegeben Sie Ihre test Methode ändern:

static void test(DoubleUnaryOperator f, double d) { 
    // Do something util here 
    System.out.println(f.applyAsDouble(d)); 
} 

Sie könnten Verwenden Sie es wie folgt:

test(SomeObject.getExtraProcessors().get(0), 1);