Java中的回调函数

Oma*_*eji 170 java function-pointers callback

有没有办法在Java方法中传递回调函数?

我试图模仿的行为是传递给函数的.Net委托.

我见过人们建议创建一个单独的对象,但这似乎有些过分,但我知道有时矫枉过正是唯一的做法.

Gan*_*ant 153

如果你的意思是.NET匿名委托,我认为Java的匿名类也可以使用.

public class Main {

    public interface Visitor{
        int doJob(int a, int b);
    }


    public static void main(String[] args) {
        Visitor adder = new Visitor(){
            public int doJob(int a, int b) {
                return a + b;
            }
        };

        Visitor multiplier = new Visitor(){
            public int doJob(int a, int b) {
                return a*b;
            }
        };

        System.out.println(adder.doJob(10, 20));
        System.out.println(multiplier.doJob(10, 20));

    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Omar同意了.经过C#的长期工作后我回到了Java,真的很想念lambdas/delegates.来吧Java! (23认同)
  • @DrewNoakes,好消息是,[Java 8](http://www.techempower.com/blog/2013/03/26/everything-about-java-8/)有lambdas(大多数)...... (4认同)
  • 这是自Java 1.0以来的规范方法. (3认同)
  • 我一直在使用这个,它比我想要的要冗长一些,但它有效。 (2认同)
  • 既然您已使用单个方法定义了接口Visitor,则可以传递匹配的lambdas而不是它. (2认同)

Juh*_*uh_ 33

从Java 8开始,有lambda和方法引用:

例如,让我们定义:

import java.util.function.Function;

public MyClass {
    public static String applyFunction(String name, Function<String,String> function){
        return function.apply(name);
    }
}
Run Code Online (Sandbox Code Playgroud)

MyClass.applyFunction("42", str -> "the answer is: " + str);
// returns "the answer is: 42"
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

@Value // lombok
public class PrefixAppender {
    private String prefix;

    public String addPrefix(String suffix){
        return prefix +":"+suffix;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以在github上找到一个例子,这里是:julien-diener/MethodReference.

  • 我的结论是,大多数时候,您都需要编写自己的功能接口,因为java.util.function中提供的默认接口是不够的。 (2认同)

cpr*_*ack 26

为简单起见,您可以使用Runnable:

private void runCallback(Runnable callback)
{
    // Run callback
    callback.run();
}
Run Code Online (Sandbox Code Playgroud)

用法:

runCallback(new Runnable()
{
    @Override
    public void run()
    {
        // Running callback
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个,因为我不需要创建一个新的接口或类只是为了做一个简单的回调.谢谢你的提示! (2认同)

Mic*_*rdt 16

有点挑剔:

我似乎有人建议创建一个单独的对象,但这似乎有点过分

传递回调包括用几乎任何OO语言创建一个单独的对象,因此很难被认为是过度杀伤.你可能意味着在Java中,它需要你创建一个单独的类,它比具有显式的第一类函数或闭包的语言更冗长(并且更加资源密集).但是,匿名类至少可以减少冗长,并且可以内联使用.

  • 是的,这就是我的意思.有30个左右的活动,你最终会有30个课程. (12认同)

Bis*_*mad 14

然而我看到最优选的方式是我正在寻找的......它基本上来自这些答案,但我不得不操纵它更多余和高效.. 我想每个人都在寻找我想出的东西

到了这一点::

首先使界面变得简单

public interface myCallback {
    void onSuccess();
    void onError(String err);
}
Run Code Online (Sandbox Code Playgroud)

现在要在你希望处理结果的时候运行这个回调 - 更有可能在异步调用之后运行并且你想运行一些依赖于这些重新组合的东西

// import the Interface class here

public class App {

    public static void main(String[] args) {
        // call your method
        doSomething("list your Params", new myCallback(){
            @Override
            public void onSuccess() {
                // no errors
                System.out.println("Done");
            }

            @Override
            public void onError(String err) {
                // error happen
                System.out.println(err);
            }
        });
    }

    private void doSomething(String param, // some params..
                             myCallback callback) {
        // now call onSuccess whenever you want if results are ready
        if(results_success)
            callback.onSuccess();
        else
            callback.onError(someError);
    }

}
Run Code Online (Sandbox Code Playgroud)

doSomething 是一个函数需要一些时间你想要添加一个回调来通知你结果来了,将回调接口添加为此方法的参数

希望我的观点清楚,享受;)


小智 9

在Java 8中使用lambdas非常容易.

public interface Callback {
    void callback();
}

public class Main {
    public static void main(String[] args) {
        methodThatExpectsACallback(() -> System.out.println("I am the callback."));
    }
    private static void methodThatExpectsACallback(Callback callback){
        System.out.println("I am the method.");
        callback.callback();
    }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*son 7

我发现使用反射库实现的想法很有趣,并提出了我认为非常有效的.唯一的缺点是丢失编译时检查您是否传递了有效参数.

public class CallBack {
    private String methodName;
    private Object scope;

    public CallBack(Object scope, String methodName) {
        this.methodName = methodName;
        this.scope = scope;
    }

    public Object invoke(Object... parameters) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Method method = scope.getClass().getMethod(methodName, getParameterClasses(parameters));
        return method.invoke(scope, parameters);
    }

    private Class[] getParameterClasses(Object... parameters) {
        Class[] classes = new Class[parameters.length];
        for (int i=0; i < classes.length; i++) {
            classes[i] = parameters[i].getClass();
        }
        return classes;
    }
}
Run Code Online (Sandbox Code Playgroud)

你这样使用它

public class CallBackTest {
    @Test
    public void testCallBack() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        TestClass testClass = new TestClass();
        CallBack callBack = new CallBack(testClass, "hello");
        callBack.invoke();
        callBack.invoke("Fred");
    }

    public class TestClass {
        public void hello() {
            System.out.println("Hello World");
        }

        public void hello(String name) {
            System.out.println("Hello " + name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


eri*_*son 5

方法不是(还)Java中的第一类对象; 你不能将函数指针作为回调传递.相反,创建一个包含所需方法并传递的对象(通常实现一个接口).

已经提出了Java中的闭包建议 - 这将提供您正在寻找的行为 - 但是没有一个将包含在即将发布的Java 7版本中.