我正在寻找一种通过引用传递方法的方法。我知道Java不传递方法作为参数,但是,我想要一个替代方案。

我被告知接口是作为参数传递方法的替代方案,但我不理解接口如何通过引用充当方法。如果我理解正确的话,接口只是一组没有定义的抽象方法。我不想发送一个每次都需要定义的接口,因为几个不同的方法可以用相同的参数调用相同的方法。

我想要完成的是类似这样的事情:

public void setAllComponents(Component[] myComponentArray, Method myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod(leaf);
    } //end looping through components
}

调用方法如下:

setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());

当前回答

java 8起

Java 8以后,您可以使用lambda表达式提供函数接口(只有一个抽象方法的接口)的抽象方法的实现,并将其作为参数传递给方法。

@FunctionalInterface
interface ArithmeticFunction {
    public int calcualate(int a, int b);
}

public class Main {
    public static void main(String args[]) {
        ArithmeticFunction addition = (a, b) -> a + b;
        ArithmeticFunction subtraction = (a, b) -> a - b;

        int a = 20, b = 5;

        System.out.println(perform(addition, a, b));
        // or
        System.out.println(perform((x, y) -> x + y, a, b));

        System.out.println(perform(subtraction, a, b));
        // or
        System.out.println(perform((x, y) -> x - y, a, b));
    }

    static int perform(ArithmeticFunction function, int a, int b) {
        return function.calcualate(a, b);
    }
}

输出:

25
25
15
15

在线演示

从方法参考中了解更多信息。

其他回答

虽然这还不适用于Java 7及以下版本,但我相信我们应该展望未来,至少认识到Java 8等新版本中会出现的变化。

也就是说,这个新版本为Java带来了lambda和方法引用(以及新的api,这是这个问题的另一个有效解决方案)。虽然它们仍然需要一个接口,但不会创建新的对象,并且额外的类文件不会因为JVM的不同处理而污染输出目录。

这两种风格(lambda和方法引用)都需要一个具有单一方法的可用接口,该方法的签名被使用:

public interface NewVersionTest{
    String returnAString(Object oIn, String str);
}

从这里开始,方法的名称不再重要。在接受lambda的地方,也接受方法引用。例如,在这里使用我们的签名:

public static void printOutput(NewVersionTest t, Object o, String s){
    System.out.println(t.returnAString(o, s));
}

这只是一个简单的接口调用,直到传递lambda1:

public static void main(String[] args){
    printOutput( (Object oIn, String sIn) -> {
        System.out.println("Lambda reached!");
        return "lambda return";
    }
    );
}

这将输出:

Lambda reached!
lambda return

方法引用类似。考虑到:

public class HelperClass{
    public static String testOtherSig(Object o, String s){
        return "real static method";
    }
}

和主要:

public static void main(String[] args){
    printOutput(HelperClass::testOtherSig);
}

输出将是真正的静态方法。方法引用可以是静态的、实例的、带有任意实例的非静态的,甚至是构造函数。对于构造函数,将使用类似ClassName::new的东西。

1有些人不认为这是lambda,因为它有副作用。不过,它确实以一种更直观的方式说明了如何使用。

使用java.lang.reflect.Method对象并调用invoke

我不是java专家,但我可以这样解决你的问题:

@FunctionalInterface
public interface AutoCompleteCallable<T> {
  String call(T model) throws Exception;
}

我在我的特殊接口中定义了参数

public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}

最后,我实现getSearchText方法,同时调用初始化方法。

initialize(getMessageContactModelList(), new AutoCompleteCallable() {
          @Override
          public String call(Object model) throws Exception {
            return "custom string" + ((xxxModel)model.getTitle());
          }
        })

java 8起

Java 8以后,您可以使用lambda表达式提供函数接口(只有一个抽象方法的接口)的抽象方法的实现,并将其作为参数传递给方法。

@FunctionalInterface
interface ArithmeticFunction {
    public int calcualate(int a, int b);
}

public class Main {
    public static void main(String args[]) {
        ArithmeticFunction addition = (a, b) -> a + b;
        ArithmeticFunction subtraction = (a, b) -> a - b;

        int a = 20, b = 5;

        System.out.println(perform(addition, a, b));
        // or
        System.out.println(perform((x, y) -> x + y, a, b));

        System.out.println(perform(subtraction, a, b));
        // or
        System.out.println(perform((x, y) -> x - y, a, b));
    }

    static int perform(ArithmeticFunction function, int a, int b) {
        return function.calcualate(a, b);
    }
}

输出:

25
25
15
15

在线演示

从方法参考中了解更多信息。

首先用要作为参数传递的方法定义一个Interface

public interface Callable {
  public void call(int param);
}

使用该方法实现一个类

class Test implements Callable {
  public void call(int param) {
    System.out.println( param );
  }
}

//像这样调用

Callable cmd = new Test();

这允许您将cmd作为参数传递,并调用接口中定义的方法调用

public invoke( Callable callable ) {
  callable.call( 5 );
}