Save a method into a variable, java 8

2019-01-25 04:09发布

问题:

Is it possible to save a method into a variable?
I have a class which is called MyFilter and it filters Items on different fields.
The constructor of MyFilter should ask 2 things:

  1. String, for example filter Items by language, "English"
  2. This should be a method

for example:

I have an Item and I want to check if the language == String given to the filter
So I need to get the language of that Item, so Item.getLanguage()...
I also need it for Item.getTitle(), Item.getId() and so on.

I think this is possible with lambda's but I don't know how.

回答1:

Yes, you can have a variable reference to any method. For simple methods it's usually enough to use java.util.function. classes. For complex methods you have to define your @FunctionalInterface with this method. Here's working example:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class Main {

    public static void main(String[] args) {
        final Consumer<Integer> simpleReference = Main::someMethod;
        simpleReference.accept(1);
        simpleReference.accept(2);
        simpleReference.accept(3);

        final ComplexInterface complexReference = Main::complexMethod;
        final String complexResult = complexReference.someMethod("888", 321, new ArrayList<>());
        System.out.println(complexResult);
    }

    private static void someMethod(int value) {
        System.out.println(value);
    }

    private static String complexMethod(String stringValue, int intValue, List<Long> longList) {
        final StringBuilder builder = new StringBuilder();
        builder.append(stringValue).append(" : ").append(intValue);
        for (Long longValue : longList) {
            builder.append(longValue);
        }
        return builder.toString();
    }

    @FunctionalInterface
    public static interface ComplexInterface{
        String someMethod(String stringValue, int intValue, List<Long> longList);
    }
}


回答2:

You can use Java 8 method references. You can use the :: 'operator' to grab a method reference from an object.

import java.util.function.IntConsumer;

class Test {
    private int i;
    public Test() { this.i = 0; }
    public void inc(int x) { this.i += x; }
    public int get() { return this.i; }

    public static void main(String[] args) {
        Test t = new Test();
        IntConsumer c = t::inc;
        c.accept(3);
        System.out.println(t.get());
        // prints 3
    }
}

You just need a @FunctionalInterface that matches the signature of the method you want to store. java.util.function contains a selection of the most commonly used ones.



回答3:

You can use method reference like -

System.out::println  

Which is equivalent to the lambda expression -

x -> System.out.println(x).  

Moreover you can user reflection to store method and it will works for the earlier version of java too.