我正在寻找一种通过引用传递方法的方法。我知道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中,您现在可以使用Lambda表达式和方法引用更容易地传递方法。首先介绍一些背景知识:函数式接口是具有且仅有一个抽象方法的接口,尽管它可以包含任意数量的默认方法(Java 8新增)和静态方法。lambda表达式可以快速实现抽象方法,如果不使用lambda表达式,则无需使用所有不必要的语法。

没有lambda表达式:

obj.aMethod(new AFunctionalInterface() {
    @Override
    public boolean anotherMethod(int i)
    {
        return i == 982
    }
});

使用lambda表达式:

obj.aMethod(i -> i == 982);

以下是Java Lambda表达式教程的节选:

Syntax of Lambda Expressions A lambda expression consists of the following: A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p, which represents an instance of the Person class.Note: You can omit the data type of the parameters in a lambda expression. In addition, you can omit the parentheses if there is only one parameter. For example, the following lambda expression is also valid: p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 The arrow token, -> A body, which consists of a single expression or a statement block. This example uses the following expression: p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively, you can use a return statement: p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have to enclose a void method invocation in braces. For example, the following is a valid lambda expression: email -> System.out.println(email) Note that a lambda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.


下面是如何使用lambda表达式“传递一个方法”:

interface I {
    public void myMethod(Component component);
}

class A {
    public void changeColor(Component component) {
        // code here
    }

    public void changeSize(Component component) {
        // code here
    }
}
class B {
    public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
        for(Component leaf : myComponentArray) {
            if(leaf instanceof Container) { // recursive call if Container
                Container node = (Container)leaf;
                setAllComponents(node.getComponents(), myMethodInterface);
            } // end if node
            myMethodsInterface.myMethod(leaf);
        } // end looping through components
    }
}
class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
        b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
    }
}

类C可以通过使用类似这样的方法引用来进一步缩短:

class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), a::changeColor);
        b.setAllComponents(this.getComponents(), a::changeSize);
    }
}

其他回答

Java有一种机制来传递名称和调用它。这是反射机制的一部分。 你的函数应该附加类Method的参数。

public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}

使用观察者模式(有时也称为监听者模式):

interface ComponentDelegate {
    void doSomething(Component component);
}

public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
    // ...
    delegate.doSomething(leaf);
}

setAllComponents(this.getComponents(), new ComponentDelegate() {
                                            void doSomething(Component component) {
                                                changeColor(component); // or do directly what you want
                                            }
                                       });

新的ComponentDelegate()……声明实现接口的匿名类型。

我不是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());
          }
        })

我没有找到任何解决方案,在这里,显示如何传递方法与参数绑定到它作为一个方法的参数。下面的例子演示了如何传递一个已经绑定了参数值的方法。

步骤1:创建两个接口,一个有返回类型,另一个没有。Java也有类似的接口,但它们没有什么实际用途,因为它们不支持异常抛出。



    public interface Do {
    void run() throws Exception;
    }


    public interface Return {
        R run() throws Exception;
    }

我们如何使用两个接口在事务中封装方法调用的示例。注意,我们传递方法时带有实际参数。



    //example - when passed method does not return any value
    public void tx(final Do func) throws Exception {
        connectionScope.beginTransaction();
        try {
            func.run();
            connectionScope.commit();
        } catch (Exception e) {
            connectionScope.rollback();
            throw e;
        } finally {
            connectionScope.close();
        }
    }

    //Invoke code above by 
    tx(() -> api.delete(6));

另一个例子展示了如何传递一个实际返回值的方法



        public  R tx(final Return func) throws Exception {
    R r=null;
    connectionScope.beginTransaction();
    try {
                r=func.run();
                connectionScope.commit();
            } catch (Exception e) {
                connectionScope.rollback();
                throw e;
            } finally {
                connectionScope.close();
            }
        return r;
        }
        //Invoke code above by 
        Object x= tx(() -> api.get(id));

在Java 8中,您现在可以使用Lambda表达式和方法引用更容易地传递方法。首先介绍一些背景知识:函数式接口是具有且仅有一个抽象方法的接口,尽管它可以包含任意数量的默认方法(Java 8新增)和静态方法。lambda表达式可以快速实现抽象方法,如果不使用lambda表达式,则无需使用所有不必要的语法。

没有lambda表达式:

obj.aMethod(new AFunctionalInterface() {
    @Override
    public boolean anotherMethod(int i)
    {
        return i == 982
    }
});

使用lambda表达式:

obj.aMethod(i -> i == 982);

以下是Java Lambda表达式教程的节选:

Syntax of Lambda Expressions A lambda expression consists of the following: A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p, which represents an instance of the Person class.Note: You can omit the data type of the parameters in a lambda expression. In addition, you can omit the parentheses if there is only one parameter. For example, the following lambda expression is also valid: p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 The arrow token, -> A body, which consists of a single expression or a statement block. This example uses the following expression: p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively, you can use a return statement: p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have to enclose a void method invocation in braces. For example, the following is a valid lambda expression: email -> System.out.println(email) Note that a lambda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.


下面是如何使用lambda表达式“传递一个方法”:

interface I {
    public void myMethod(Component component);
}

class A {
    public void changeColor(Component component) {
        // code here
    }

    public void changeSize(Component component) {
        // code here
    }
}
class B {
    public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
        for(Component leaf : myComponentArray) {
            if(leaf instanceof Container) { // recursive call if Container
                Container node = (Container)leaf;
                setAllComponents(node.getComponents(), myMethodInterface);
            } // end if node
            myMethodsInterface.myMethod(leaf);
        } // end looping through components
    }
}
class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
        b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
    }
}

类C可以通过使用类似这样的方法引用来进一步缩短:

class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), a::changeColor);
        b.setAllComponents(this.getComponents(), a::changeSize);
    }
}