Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static reference ( with :: ) to a method returning an interface

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?

like image 299
Guillaume Barré Avatar asked Apr 15 '16 10:04

Guillaume Barré


3 Answers

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.
like image 161
Andrew Tobilko Avatar answered Oct 14 '22 21:10

Andrew Tobilko


How about using a lambda expression instead of method reference :

test(d-> SomeObject.getExtraProccessors().process(d), 1d);
like image 24
Eran Avatar answered Oct 14 '22 22:10

Eran


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);
like image 34
fps Avatar answered Oct 14 '22 22:10

fps