Function Pointers in Java

Feb 20, 2011 16:30



http://stackoverflow.com/questions/1073358/function-pointers-in-java



You can substitue a function pointer with an interface. Lets say you want to run through a collection and do something with each element.

public interface IFunction {
  public void execute(Object o);
}

This is the interface we could pass to some say CollectionUtils2.doFunc(Collection c, IFunction f).

public static void doFunc(Collection c, IFunction f) {
   for (Object o : c) {
      f.execute(o);
   }
}

As an example say we have a collection of numbers and you would like to add 1 to every element.

CollectionUtils2.doFunc(List numbers, new IFunction() {
    public void execute(Object o) {
       Integer anInt = (Integer) o;
       anInt++;
    }
});

===================================

There is no such thing in Java. You will need to wrap your function into some object and pass the reference to that object in order to pass the reference to the method on that object.

Syntactically, this can be eased to a certain extend by using anonymous classes defined in-place or anonymous classes defined as member variables of the class.

Example:

class MyComponent extends JPanel {
    private JButton button;
    public MyComponent() {
        button = new JButton("click me");
        button.addActinListener(buttonAction);
        add(button);
    }

private ActionListener buttonAction = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // handle the event...
            // note how the handler instance can access
            // members of the surrounding class
            button.setText("you clicked me");
        }
    }
}

===================================
You can use reflection to do it. Pass as parameter the object and the method name (as a string) and then invoke the method. For example: Object methodCaller(Object theObject, String methodName) {
   return theObject.getClass().getMethod(methodName).invoke(theObject);
   // Catch the exceptions
}

And then use it as in:
String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");
Of course, check all exceptions and add the needed casts.

===================================

To achieve similar functionality you could use anonymous inner classes.

If you were to define a interface Foo:

interface Foo {
    Object myFunc(Object arg);
}

Create a method bar which will receive a 'function pointer' as an argument:

public void bar(Foo foo) {
    // .....
    Object object = foo.myFunc(argValue);
    // .....
}

Finally call the method as follows:

bar(new Foo() {
    public Object myFunc(Object arg) {
        // Function code.
    }
}

===================================
public Function(java.lang.reflect.Method m)
    {
        object = null;
        method = m;
    }

public Function(Class c, String methodName, Class... methodParameterTypes) throws NoSuchMethodException
    {
        object = null;
        method = c.getMethod(methodName, methodParameterTypes);
    }

public Function(Object o, java.lang.reflect.Method m)
    {
        object = o;
        method = m;
    }

public Function(Object o, String methodName, Class... methodParameterTypes) throws NoSuchMethodException
    {
        object = o;
        method = o.getClass().getMethod(methodName, methodParameterTypes);
    }

public Object getObject()
    {
        return object;
    }

public java.lang.reflect.Method getMethod()
    {
        return method;
    }

public Object invoke(Object... args) throws IllegalAccessException, java.lang.reflect.InvocationTargetException
    {
        return method.invoke(object, args);
    }

private Object object;
    private java.lang.reflect.Method method;
};

public class Bind
{
    public static class Arg
    {
        public Arg(int index)
        {
            i = index;
        }

public int getIndex()
        {
            return i;
        }

private int i;
    }

public Bind(Function f, Object... args)
    {
        function = f;
        arguments = args;
    }

public Function getFunction()
    {
        return function;
    }

public Object[] getArguments()
    {
        return arguments;
    }

public Object invoke(Object... args) throws IllegalAccessException, java.lang.reflect.InvocationTargetException
    {
        if (args == null)
            return function.invoke(arguments);

if (arguments == null)
            return function.invoke(args);

Object[] finalArgs = new Object[arguments.length];

for (int i = 0; i < arguments.length; ++i)
        {
            Object o = arguments[i];

if (o.getClass() == Arg.class)
                finalArgs[i] = args[((Arg)o).getIndex()];
            else
                finalArgs[i] = o;
        }

return function.invoke((Object[])finalArgs);
    }

private Function function;
    private Object[] arguments;
}

программирование, java

Previous post Next post
Up