Статическая ссылка (с ::) на метод, возвращающий интерфейс

У меня есть несколько предопределенных статических «процессоров», реализующих один и тот же метод, например:

default double process(double num){

Образец :

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

Теперь представьте, что у меня есть объекты, которые могут предоставить список дополнительных «процессоров».

Я пытаюсь использовать interface для определения этих дополнительных «процессоров».

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

Реализация объекта с дополнительными «процессорами»:

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

Здесь все компилируется и работает нормально. Но теперь я застрял.

Используя SomeObject::getExtraProccessors, у меня есть ссылка на статический метод, возвращающий интерфейс, как я могу вызвать метод интерфейса?

Моя первая попытка была с

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

Но это не компилируется, давая The target type of this expression must be a functional interface

Итак, не могли бы вы сказать мне, возможно ли это сделать, и если да, то как? И если это невозможно, как мне это сделать?


person Guillaume Barré    schedule 15.04.2016    source источник
comment
Вы можете использовать DoubleUnaryOperator вместо Function<Double, Double> и вместо IProcessor.   -  person Paul Boddington    schedule 15.04.2016
comment
Вам не нужно создавать экземпляр анонимного внутреннего класса IProcessor, вместо этого возвращайте лямбда: return n -> n * 30;. И если вам нужен список: верните Arrays.asList(n -> n * 30, n -> n / 2, ...). Кроме того, как сказал @PaulBoddington, DoubleUnaryOperator - это интерфейс, предоставляемый Java для работы с одним операндом double.   -  person fps    schedule 15.04.2016


Ответы (3)


test(SomeObject.getExtraProccessors()::process, 1);
  • SomeObject.getExtraProccessors() возвращает экземпляр функционального интерфейса IProcessor.
  • SomeObject::getExtraProccessors — это ссылка на статический метод getExtraProccessor класса SomeObject.
person Andrew Tobilko    schedule 15.04.2016

Как насчет использования лямбда-выражения вместо ссылки на метод:

test(d-> SomeObject.getExtraProccessors().process(d), 1d);
person Eran    schedule 15.04.2016

Я думаю, вам не нужно создавать экземпляр анонимного внутреннего класса, который реализует IProcessor. На самом деле, если вы собираетесь работать с double, вам вообще не нужен интерфейс IProcessor. Java предоставляет интерфейс DoubleUnaryOperator, предназначенный именно для этого.

Если вы хотите вернуть список «процессоров», вы можете сделать это следующим образом:

static class SomeObject {

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

Затем, если вы измените свой метод test на:

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

Вы можете использовать его следующим образом:

test(SomeObject.getExtraProcessors().get(0), 1);
person fps    schedule 15.04.2016