Array of function pointers in Java

28,369

Solution 1

Java doesn't have a function pointer per se (or "delegate" in C# parlance). This sort of thing tends to be done with anonymous subclasses.

public interface Worker {
  void work();
}

class A {
  void foo() { System.out.println("A"); }
}

class B {
  void bar() { System.out.println("B"); }
}

A a = new A();
B b = new B();

Worker[] workers = new Worker[] {
  new Worker() { public void work() { a.foo(); } },
  new Worker() { public void work() { b.bar(); } }
};

for (Worker worker : workers) {
  worker.work();
}

Solution 2

You can achieve the same result with the functor pattern. For instance, having an abstract class:

abstract class Functor
{
  public abstract void execute();
}

Your "functions" would be in fact the execute method in the derived classes. Then you create an array of functors and populate it with the apropriated derived classes:

class DoSomething extends Functor
{
  public void execute()
  {
    System.out.println("blah blah blah");
  }
}

Functor [] myArray = new Functor[10];
myArray[5] = new DoSomething();

And then you can invoke:

myArray[5].execute();

Solution 3

It is possible, you can use an array of Method. Grab them using the Reflection API (edit: they're not functions since they're not standalone and have to be associated with a class instance, but they'd do the job -- just don't expect something like closures)

Solution 4

I found the reflection approach the cleanest -- I added a twist to this solution since most production classes have nested classes and I didn't see any examples that demonstrates this (but I didn't look for very long either). My reason for using reflection is that my "updateUser()" method below had a bunch of redundant code and just one line that changed (for every field in the user object) in the middle that updated the user object:

NameDTO.java

public class NameDTO {

    String first, last;

    public String getFirst() {
        return first;
    }

    public void setFirst(String first) {
        this.first = first;
    }

    public String getLast() {
        return last;
    }

    public void setLast(String last) {
        this.last = last;
    }   
}

UserDTO.java

public class UserDTO {

    private NameDTO name;
    private Boolean honest;

    public UserDTO() {
        name = new NameDTO();
        honest = new Boolean(false);
    }

    public NameDTO getName() {
        return name;
    }

    public void setName(NameDTO name) {
        this.name = name;
    }

    public Boolean getHonest() {
        return honest;
    }

    public void setHonest(Boolean honest) {
        this.honest = honest;
    }
}

Example.java

import java.lang.reflect.Method;

public class Example {

    public Example ()  {
        UserDTO dto = new UserDTO();

        try {
            Method m1 = dto.getClass().getMethod("getName", null);
            NameDTO nameDTO = (NameDTO) m1.invoke(dto, null);

            Method m2 = nameDTO.getClass().getMethod("setFirst", String.class);
            updateUser(m2, nameDTO, "Abe");

            m2 = nameDTO.getClass().getMethod("setLast", String.class);
            updateUser(m2, nameDTO, "Lincoln");

            m1 = dto.getClass().getMethod("setHonest", Boolean.class);
            updateUser(m1, dto, Boolean.TRUE);
            System.out.println (dto.getName().getFirst() + " " + dto.getName().getLast() + ": honest=" + dto.getHonest().toString());

        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

    public  void updateUser(Method m,  Object o, Object v) {
        //  lots of code here
        try {
            m.invoke(o, v);
        } catch (Exception e) {
            e.printStackTrace();
        } 
        // lots of code here -- including a retry loop to make sure the
        // record hadn't been written since my last read
    }

    public static void main(String[] args) {
        Example mp = new Example();
    }
}

Solution 5

Java does not have pointers (only references), nor does it have functions (only methods), so it's doubly impossible for it to have pointers to functions. What you can do is define an interface with a single method in it, have your classes that offer such a method declare they implement said interface, and make a vector with references to such an interface, to be populated with references to the specific objects on which you want to call that method. The only constraint, of course, is that all the methods must have the same signature (number and type of arguments and returned values).

Otherwise, you can use reflection/introspection (e.g. the Method class), but that's not normally the simplest, most natural approach.

Share:
28,369
Waltzy
Author by

Waltzy

Updated on July 15, 2022

Comments

  • Waltzy
    Waltzy almost 2 years

    I have read this question and I'm still not sure whether it is possible to keep pointers to methods in an array in Java. If anyone knows if this is possible (or not), it would be a real help. I'm trying to find an elegant solution of keeping a list of Strings and associated functions without writing a mess of hundreds of if statements.

    Cheers

  • Lordn__n
    Lordn__n about 14 years
    A Method isn't really a function pointer. For one thing, unless you're calling a static method you need to pass an instance to it.
  • Chris Dennett
    Chris Dennett about 14 years
    True, but you can create a wrapper which will do this automatically. This would be called something like InstanceMethod, and implement similar methods to Method, but delegate the calls and pass to these calls the object passed into the constructor. Maybe the Apache libraries have something like this? Otherwise, it'd be trivial to code your own.
  • Waltzy
    Waltzy about 14 years
    cheers cletus, this was what I was looking for, the example helped ;)
  • Fabio Ceconello
    Fabio Ceconello about 13 years
    Also Keep in mind that you have to be careful when using reflection, it has a significant performance penalty.
  • Jarod DY Law
    Jarod DY Law almost 13 years
    is there a mistake? " b.foo(); "