12

I have several predifined static "processors" implementing the same method, for example:

default double process(double num){

Sample :

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

Now imagine that I have some objects which can provide a list of additional "processors".

I'm trying to use an interface to define those additional "processors".

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

Implementation of an object with additional "processors":

    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 here everything compiles and works fine. But now I'm stuck.

Using SomeObject::getExtraProccessors I have a reference on a static method returning an interface, how can I invoke the interface's method?

My first try was with

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

But this doesn't compile giving a The target type of this expression must be a functional interface

So please could you tell me if it possible to do this and if yes how? And if it's not possible how should I do it?

Guillaume Barré
  • 4,168
  • 2
  • 27
  • 50
  • 2
    You could use `DoubleUnaryOperator` instead of `Function` and instead of `IProcessor`. – Paul Boddington Apr 15 '16 at 11:10
  • 1
    You don't need to create an anonymous inner class instance of `IProcessor`, instead return a lambda: `return n -> n * 30;`. And if you need a list: return `Arrays.asList(n -> n * 30, n -> n / 2, ...)`. Also, as @PaulBoddington said, `DoubleUnaryOperator` is the interface provided by Java to operate on a single `double` operand. – fps Apr 15 '16 at 12:27

3 Answers3

7
test(SomeObject.getExtraProccessors()::process, 1);
  • SomeObject.getExtraProccessors() returns an instance of functional interface IProcessor.
  • SomeObject::getExtraProccessors is a method reference to the static method getExtraProccessor of the SomeObject class.
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
3

How about using a lambda expression instead of method reference :

test(d-> SomeObject.getExtraProccessors().process(d), 1d);
Eran
  • 387,369
  • 54
  • 702
  • 768
2

I think you don't need to create an anonymous inner class instance that implements IProcessor. Actually, if you're going to operate with a double, you don't need the IProcessor interface at all. Java provides the DoubleUnaryOperator interface that is meant exactly for that.

If you want to return a list of "processors", then you could do it this way:

static class SomeObject {

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

Then, given you change your test method to:

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

You could use it as follows:

test(SomeObject.getExtraProcessors().get(0), 1);
fps
  • 33,623
  • 8
  • 55
  • 110