By Omar Kooheji


2009-01-14 16:40:16 8 Comments

Is there a way to pass a call back function in a Java method?

The behavior I'm trying to mimic is a .Net Delegate being passed to a function.

I've seen people suggesting creating a separate object but that seems overkill, however I am aware that sometimes overkill is the only way to do things.

17 comments

@Juh_ 2014-11-06 10:02:29

Since Java 8, there are lambda and method references:

For example, if you want a functional interface A -> B such as:

import java.util.function.Function;

public MyClass {
    public static String applyFunction(String name, Function<String,String> function){
        return function.apply(name);
    }
}

then you can call it like so

MyClass.applyFunction("42", str -> "the answer is: " + str);
// returns "the answer is: 42"

Also you can pass class method. Say you have:

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

    public String addPrefix(String suffix){
        return prefix +":"+suffix;
    }
}

Then you can do:

PrefixAppender prefixAppender= new PrefixAppender("prefix");
MyClass.applyFunction("some text", prefixAppender::addPrefix);
// returns "prefix:some text"

Note:

Here I used the functional interface Function<A,B>, but there are many others in the package java.util.function. Most notable ones are

  • Supplier: void -> A
  • Consumer: A -> void
  • BiConsumer: (A,B) -> void
  • Function: A -> B
  • BiFunction: (A,B) -> C

and many others that specialize on some of the input/output type. Then, if it doesn't provide the one you need, you can create your own functional interface like so:

@FunctionalInterface
interface Function3<In1, In2, In3, Out> { // (In1,In2,In3) -> Out
    public Out apply(In1 in1, In2 in2, In3 in3);
}

Example of use:

String computeAnswer(Function3<String, Integer, Integer, String> f){
    return f.apply("6x9=", 6, 9);
}

computeAnswer((question, a, b) -> question + "42");
// "6*9=42"

@Sri Harsha Chilakapati 2014-12-10 13:39:40

For CallBacks, it would be better to write your own functional interface since each callback type would usually have multiple syntaxes.

@Juh_ 2014-12-10 14:10:13

I am not sure to understand. If one of the classes in java.util.function is what you are looking for, then you're good to go. Then you can play with generics for the I/O. (?)

@Sri Harsha Chilakapati 2014-12-10 15:00:56

You didn't get me, what I said is about translating C++ code which uses callback functions to Java 8, There, for each unique function pointer, you have to create a Functional interface in Java, since there will be more parameters in the real production code.

@Sri Harsha Chilakapati 2014-12-10 15:02:09

My conclusion is that most of the time, you are required to write your own functional interfaces since the default provided ones, in java.util.function aren't sufficient.

@Juh_ 2019-07-18 13:01:46

Then use scala, much simpler for functional interface :-)

@Juh_ 2019-10-31 10:04:42

I added a note on existing functional interfaces and how to create new ones

@Balu mallisetty 2019-06-10 16:14:12

Create an Interface, and Create the Same Interface Property in Callback Class.

interface dataFetchDelegate {
    void didFetchdata(String data);
}
//callback class
public class BackendManager{
   public dataFetchDelegate Delegate;

   public void getData() {
       //Do something, Http calls/ Any other work
       Delegate.didFetchdata("this is callbackdata");
   }

}

Now in the class where you want to get called back implement the above Created Interface. and Also Pass "this" Object/Reference of your class to be called back.

public class Main implements dataFetchDelegate
{       
    public static void main( String[] args )
    {
        new Main().getDatafromBackend();
    }

    public void getDatafromBackend() {
        BackendManager inc = new BackendManager();
        //Pass this object as reference.in this Scenario this is Main Object            
        inc.Delegate = this;
        //make call
        inc.getData();
    }

    //This method is called after task/Code Completion
    public void didFetchdata(String callbackData) {
        // TODO Auto-generated method stub
        System.out.println(callbackData);
    }
}

@Biskrem Muhammad 2017-12-18 22:47:56

yet i see there is most preferred way which was what i was looking for.. it's basically derived from these answers but i had to manipulate it to more more redundant and efficient.. and i think everybody looking for what i come up with

To the point::

first make an Interface that simple

public interface myCallback {
    void onSuccess();
    void onError(String err);
}

now to make this callback run when ever you wish to do to handle the results - more likely after async call and you wanna run some stuff which depends on these reuslts

// 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);
    }

}

doSomething is the function that takes some time you wanna add a callback to it to notify you when the results came, add the call back interface as a parameter to this method

hope my point is clear, enjoy ;)

@gk bwg rhb mbreafteahbtehnb 2017-04-03 19:27:03

This is very easy in Java 8 with 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();
    }
}

@Nashev 2017-06-19 15:53:36

Will it be like this in case with argument? pastebin.com/KFFtXPNA

@gk bwg rhb mbreafteahbtehnb 2017-06-19 16:14:24

Yep. Any amount of arguments (or none) will work as long as proper lambda syntax is maintained.

@Sébastien 2016-07-06 18:19:27

You also can do theCallback using the Delegate pattern:

Callback.java

public interface Callback {
    void onItemSelected(int position);
}

PagerActivity.java

public class PagerActivity implements Callback {

    CustomPagerAdapter mPagerAdapter;

    public PagerActivity() {
        mPagerAdapter = new CustomPagerAdapter(this);
    }

    @Override
    public void onItemSelected(int position) {
        // Do something
        System.out.println("Item " + postion + " selected")
    }
}

CustomPagerAdapter.java

public class CustomPagerAdapter {
    private static final int DEFAULT_POSITION = 1;
    public CustomPagerAdapter(Callback callback) {
        callback.onItemSelected(DEFAULT_POSITION);
    }
}

@monnoo 2011-09-20 20:49:58

it's a bit old, but nevertheless... I found the answer of Peter Wilkinson nice except for the fact that it does not work for primitive types like int/Integer. The problem is the .getClass() for the parameters[i], which returns for instance java.lang.Integer, which on the other hand will not be correctly interpreted by getMethod(methodName,parameters[]) (Java's fault) ...

I combined it with the suggestion of Daniel Spiewak (in his answer to this); steps to success included: catching NoSuchMethodException -> getMethods() -> looking for the matching one by method.getName() -> and then explicitly looping through the list of parameters and applying Daniels solution, such identifying the type matches and the signature matches.

@Abhishek Abhyankar 2015-05-01 08:01:54

public class HelloWorldAnonymousClasses {

    //this is an interface with only one method
    interface HelloWorld {
        public void printSomething(String something);
    }

    //this is a simple function called from main()
    public void sayHello() {

    //this is an object with interface reference followed by the definition of the interface itself

        new HelloWorld() {
            public void printSomething(String something) {
                System.out.println("Hello " + something);
            }
        }.printSomething("Abhi");

     //imagine this as an object which is calling the function'printSomething()"
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp =
                new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }
}
//Output is "Hello Abhi"

Basically if you want to make the object of an interface it is not possible, because interface cannot have objects.

The option is to let some class implement the interface and then call that function using the object of that class. But this approach is really verbose.

Alternatively, write new HelloWorld() (*oberserve this is an interface not a class) and then follow it up with the defination of the interface methods itself. (*This defination is in reality the anonymous class). Then you get the object reference through which you can call the method itself.

@joey baruch 2015-10-14 08:03:02

I've recently started doing something like this:

public class Main {
    @FunctionalInterface
    public interface NotDotNetDelegate {
        int doSomething(int a, int b);
    }

    public static void main(String[] args) {
        // in java 8 (lambdas):
        System.out.println(functionThatTakesDelegate((a, b) -> {return a*b;} , 10, 20));

    }

    public static int functionThatTakesDelegate(NotDotNetDelegate del, int a, int b) {
        // ...
        return del.doSomething(a, b);
    }
}

@avatar1337 2015-01-20 23:44:49

I think using an abstract class is more elegant, like this:

// Something.java

public abstract class Something {   
    public abstract void test();        
    public void usingCallback() {
        System.out.println("This is before callback method");
        test();
        System.out.println("This is after callback method");
    }
}

// CallbackTest.java

public class CallbackTest extends Something {
    @Override
    public void test() {
        System.out.println("This is inside CallbackTest!");
    }

    public static void main(String[] args) {
        CallbackTest myTest = new CallbackTest();
        myTest.usingCallback();
    }    
}

/*
Output:
This is before callback method
This is inside CallbackTest!
This is after callback method
*/

@simo.37920 2015-01-20 23:59:49

This is polymorphism, not a callback. You need to check the callback pattern.

@avatar1337 2015-01-21 05:30:01

Yes I am using polymorphism to callback from the super class. You don't get this functionality simply by polymorphism. I am calling usingCallback() which is in class Something, then it calls back to the subclass where the user has written its function test().

@simo.37920 2015-01-21 06:46:46

Callbacks are designed for one object to "notify" another object when something significant has occurred, so the second object can handle the event. Your abstract class is never a separate object, it is only a separate class. You are only using one object and getting different classes to perform different functions, which is the essence of polymorphism, not the callback pattern.

@Gant 2009-01-14 16:48:13

If you mean somthing like .NET anonymous delegate, I think Java's anonymous class can be used as well.

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));

    }
}

@Charlie Martin 2009-01-14 17:05:43

This is the canonical method since Java 1.0.

@Omar Kooheji 2009-10-01 16:02:09

I've been usign this, it's slioghtly more verbose than what I'd like, but it works.

@Drew Noakes 2011-05-02 14:56:43

@Omar, agreed. I've come back to Java after a long stint with C# and really miss lambdas/delegates. Come on Java!

@Lucas 2013-04-01 15:29:57

@DrewNoakes, good news is, Java 8 has lambdas (mostly)...

@joey baruch 2015-10-13 16:41:37

since you've defined the interface Visitor with a single method, you can pass lambdas that match instead of it.

@cprcrack 2013-12-13 16:41:00

For simplicity, you can use a Runnable:

private void runCallback(Runnable callback)
{
    // Run callback
    callback.run();
}

Usage:

runCallback(new Runnable()
{
    @Override
    public void run()
    {
        // Running callback
    }
});

@Bruce 2015-09-13 09:09:16

I like this because I don't need to create a new interface or class just to do a simple callback. Thanks for the tip!

@Marco C. 2015-11-04 15:45:26

public interface SimpleCallback { void callback(Object... objects); } This is quite straightforward and could be useful you need to pass some params too.

@Chris Chevalier 2017-02-23 17:22:05

@cprcrack no way to pass a value in the run() function?

@LiuYan 刘研 2011-03-25 04:41:25

I tried using java.lang.reflect to implement 'callback', here's a sample:

package StackOverflowQ443708_JavaCallBackTest;

import java.lang.reflect.*;
import java.util.concurrent.*;

class MyTimer
{
    ExecutorService EXE =
        //Executors.newCachedThreadPool ();
        Executors.newSingleThreadExecutor ();

    public static void PrintLine ()
    {
        System.out.println ("--------------------------------------------------------------------------------");
    }

    public void SetTimer (final int timeout, final Object obj, final String methodName, final Object... args)
    {
        SetTimer (timeout, obj, false, methodName, args);
    }
    public void SetTimer (final int timeout, final Object obj, final boolean isStatic, final String methodName, final Object... args)
    {
        Class<?>[] argTypes = null;
        if (args != null)
        {
            argTypes = new Class<?> [args.length];
            for (int i=0; i<args.length; i++)
            {
                argTypes[i] = args[i].getClass ();
            }
        }

        SetTimer (timeout, obj, isStatic, methodName, argTypes, args);
    }
    public void SetTimer (final int timeout, final Object obj, final String methodName, final Class<?>[] argTypes, final Object... args)
    {
        SetTimer (timeout, obj, false, methodName, argTypes, args);
    }
    public void SetTimer (final int timeout, final Object obj, final boolean isStatic, final String methodName, final Class<?>[] argTypes, final Object... args)
    {
        EXE.execute (
            new Runnable()
            {
                public void run ()
                {
                    Class<?> c;
                    Method method;
                    try
                    {
                        if (isStatic) c = (Class<?>)obj;
                        else c = obj.getClass ();

                        System.out.println ("Wait for " + timeout + " seconds to invoke " + c.getSimpleName () + "::[" + methodName + "]");
                        TimeUnit.SECONDS.sleep (timeout);
                        System.out.println ();
                        System.out.println ("invoking " + c.getSimpleName () + "::[" + methodName + "]...");
                        PrintLine ();
                        method = c.getDeclaredMethod (methodName, argTypes);
                        method.invoke (obj, args);
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                    finally
                    {
                        PrintLine ();
                    }
                }
            }
        );
    }
    public void ShutdownTimer ()
    {
        EXE.shutdown ();
    }
}

public class CallBackTest
{
    public void onUserTimeout ()
    {
        System.out.println ("onUserTimeout");
    }
    public void onTestEnd ()
    {
        System.out.println ("onTestEnd");
    }
    public void NullParameterTest (String sParam, int iParam)
    {
        System.out.println ("NullParameterTest: String parameter=" + sParam + ", int parameter=" + iParam);
    }
    public static void main (String[] args)
    {
        CallBackTest test = new CallBackTest ();
        MyTimer timer = new MyTimer ();

        timer.SetTimer ((int)(Math.random ()*10), test, "onUserTimeout");
        timer.SetTimer ((int)(Math.random ()*10), test, "onTestEnd");
        timer.SetTimer ((int)(Math.random ()*10), test, "A-Method-Which-Is-Not-Exists");    // java.lang.NoSuchMethodException

        timer.SetTimer ((int)(Math.random ()*10), System.out, "println", "this is an argument of System.out.println() which is called by timer");
        timer.SetTimer ((int)(Math.random ()*10), System.class, true, "currentTimeMillis");
        timer.SetTimer ((int)(Math.random ()*10), System.class, true, "currentTimeMillis", "Should-Not-Pass-Arguments");    // java.lang.NoSuchMethodException

        timer.SetTimer ((int)(Math.random ()*10), String.class, true, "format", "%d %X", 100, 200); // java.lang.NoSuchMethodException
        timer.SetTimer ((int)(Math.random ()*10), String.class, true, "format", "%d %X", new Object[]{100, 200});

        timer.SetTimer ((int)(Math.random ()*10), test, "NullParameterTest", new Class<?>[]{String.class, int.class}, null, 888);

        timer.ShutdownTimer ();
    }
}

@TWiStErRob 2013-02-17 10:05:49

How do you pass null as an arg?

@LiuYan 刘研 2013-02-17 17:10:30

@TWiStErRob, in this sample, it would be like timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});. output will be null test: [null]

@TWiStErRob 2013-02-17 17:23:33

Wouldn't it NPE on args[i].getClass()? My point is that it doesn't work if you select method based on argument types. It works with String.format, but may not work with something else which accepts null.

@LiuYan 刘研 2013-02-17 18:59:43

@TWiStErRob, Good point! I've added a function which can manually pass argTypes array, so now we can pass null argument/parameter without NullPointerException occured. Sample output: NullParameterTest: String parameter=null, int parameter=888

@Peter Wilkinson 2011-07-15 04:18:47

I found the idea of implementing using the reflect library interesting and came up with this which I think works quite well. The only down side is losing the compile time check that you are passing valid parameters.

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;
    }
}

You use it like this

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);
        }
    }
}

@Diederik 2012-03-15 13:25:12

Looks a bit like overkill (/me ducks)

@Juh_ 2014-11-06 09:56:03

depends on the number of use and the size of the project: overkill for a few-class project, practical on a large one.

@Juh_ 2014-11-06 09:58:59

Also, take a look at the answer of @monnoo

@Mario Fusco 2009-09-12 13:32:51

Check the closures how they have been implemented in the lambdaj library. They actually have a behavior very similar to C# delegates:

http://code.google.com/p/lambdaj/wiki/Closures

@Michael Borgwardt 2009-06-22 10:13:57

A little nitpicking:

I've seem people suggesting creating a separate object but that seems overkill

Passing a callback includes creating a separate object in pretty much any OO language, so it can hardly be considered overkill. What you probably mean is that in Java, it requires you to create a separate class, which is more verbose (and more resource-intensive) than in languages with explicit first-class functions or closures. However, anonymous classes at least reduce the verbosity and can be used inline.

@Omar Kooheji 2009-10-01 15:46:14

Yes that is what i meant. With 30 or so events you end up with 30 classes.

@MattK 2009-01-14 16:50:49

When I need this kind of functionality in Java, I usually use the Observer pattern. It does imply an extra object, but I think it's a clean way to go, and is a widely understood pattern, which helps with code readability.

@erickson 2009-01-14 16:48:53

A method is not (yet) a first-class object in Java; you can't pass a function pointer as a callback. Instead, create an object (which usually implements an interface) that contains the method you need and pass that.

Proposals for closures in Java—which would provide the behavior you are looking for—have been made, but none will be included in the upcoming Java 7 release.

@Jonas Kölker 2009-05-17 10:34:56

"A method is not (yet) a first-class object in Java" -- well, there's the method class[1], of which you can certainly pass around instances. It's not the clean, idiomatic, OO code that you'd expect from java, but it might be expedient. Certainly something to consider, though. [1] java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.ht‌​ml

Related Questions

Sponsored Content

58 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

55 Answered Questions

[SOLVED] How to create a memory leak in Java

65 Answered Questions

[SOLVED] How do I generate random integers within a specific range in Java?

  • 2008-12-12 18:20:57
  • user42155
  • 3921141 View
  • 3379 Score
  • 65 Answer
  • Tags:   java random integer

86 Answered Questions

[SOLVED] Is Java "pass-by-reference" or "pass-by-value"?

42 Answered Questions

[SOLVED] How do I convert a String to an int in Java?

36 Answered Questions

41 Answered Questions

[SOLVED] How do I efficiently iterate over each entry in a Java Map?

32 Answered Questions

[SOLVED] When to use LinkedList over ArrayList in Java?

7 Answered Questions

[SOLVED] Find first element by predicate

10 Answered Questions

[SOLVED] How to access the correct `this` inside a callback?

Sponsored Content