2016-04-15 54 views
12

Mam kilka predifined statyczne "procesory" wdrażającego tę samą metodę, na przykład:Static odniesienia (z ::) sposobu powrocie interfejs

default double process(double num){ 

Próbka:

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)); 
    } 
    ... 

Teraz wyobraź że mam obiekty, które mogą dostarczyć listę dodatkowych "procesorów".

Próbuję użyć interface do zdefiniowania tych dodatkowych "procesorów".

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

Realizacja obiektu z dodatkowymi "procesorów":

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

Up tu wszystko kompiluje i działa poprawnie. Ale teraz utknąłem.

Używanie SomeObject::getExtraProccessors Mam odwołanie do statycznej metody zwracającej interfejs, jak mogę wywołać metodę interfejsu?

Moja pierwsza próba była z

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

Ale to nie skompilować podając The target type of this expression must be a functional interface

Więc proszę mógłbyś mi powiedzieć, czy to możliwe, a jeśli tak to w jaki sposób ? A jeśli nie jest to możliwe, jak mam to zrobić?

+2

Możesz użyć 'DoubleUnaryOperator' zamiast' Function 'i zamiast'. IProcessor'. –

+1

Nie musisz tworzyć anonimowej instancji klasy wewnętrznej 'IProcessor', zamiast tego zwracaj wartość lambda:' return n -> n * 30; '. A jeśli potrzebujesz listy: return 'Arrays.asList (n -> n * 30, n -> n/2, ...)'. Ponadto, jak powiedział @PaulBoddington, 'DoubleUnaryOperator' jest interfejsem dostarczonym przez Javę do działania na pojedynczym operandzie' double'. –

Odpowiedz

7
test(SomeObject.getExtraProccessors()::process, 1); 
  • SomeObject.getExtraProccessors() zwraca wystąpienie funkcjonalnego interfejsu IProcessor.
  • SomeObject::getExtraProccessors to odwołanie metody do metody statycznej getExtraProccessor klasy .
3

Jak o użyciu wyrażenia lambda zamiast odniesienia metoda:

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

myślę, że nie ma potrzeby tworzenia anonimowej wewnętrzną instancję klasy, która implementuje IProcessor. W rzeczywistości, jeśli zamierzasz pracować z double, w ogóle nie potrzebujesz interfejsu IProcessor. Java zapewnia interfejs DoubleUnaryOperator, który jest przeznaczony właśnie do tego.

Jeśli chcesz, aby powrócić do listy "procesorów", a następnie można zrobić to w ten sposób:

static class SomeObject { 

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

Następnie podano zmienić metodę test do:

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

Mogłabyś użyj go w następujący sposób:

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