我正在寻找一种通过引用传递方法的方法。我知道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());

当前回答

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

步骤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.lang.reflect.Method对象并调用invoke

上次我检查的时候,Java不能在本地做你想做的事情;你必须使用“变通方法”来绕过这些限制。在我看来,接口是一种选择,但不是一个好的选择。也许告诉你这句话的人的意思是这样的:

public interface ComponentMethod {
  public abstract void PerfromMethod(Container c);
}

public class ChangeColor implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public class ChangeSize implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public void setAllComponents(Component[] myComponentArray, ComponentMethod 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.PerfromMethod(leaf);
    } //end looping through components
}

然后你可以调用:

setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());

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

步骤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专家,但我可以这样解决你的问题:

@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中,lambda表达式是一个很好的解决方案,正如其他答案所指出的那样。下面的答案是为Java 7和更早的版本编写的…


看一下命令模式。

// NOTE: code not tested, but I believe this is valid java...
public class CommandExample 
{
    public interface Command 
    {
        public void execute(Object data);
    }

    public class PrintCommand implements Command 
    {
        public void execute(Object data) 
        {
            System.out.println(data.toString());
        }    
    }

    public static void callCommand(Command command, Object data) 
    {
        command.execute(data);
    }

    public static void main(String... args) 
    {
        callCommand(new PrintCommand(), "hello world");
    }
}

编辑:正如Pete Kirkham所指出的,还有另一种使用访问者的方法。访问者方法稍微复杂一些——您的节点都需要使用acceptVisitor()方法来感知访问者——但如果您需要遍历一个更复杂的对象图,那么它就值得研究。