Function pointers/delegates in Java?

2019-02-06 12:12发布

For my Java game server I send the Action ID of the packet which basically tells the server what the packet is for. I want to map each Action ID (an integer) to a function. Is there a way of doing this without using a switch?

9条回答
Lonely孤独者°
2楼-- · 2019-02-06 12:32

Another similar aproach could be using Java 8's Suppliers:

Map<Integer, Supplier<T> suppliers = new HashMap();
suppliers.put(1, () -> methodOne());
suppliers.put(2, () -> methodTwo());

// ...

public T methodOne() { ... }
public T methodTwo() { ... }

// ...

T obj = suppliers.get(id).run();
查看更多
我想做一个坏孩纸
3楼-- · 2019-02-06 12:41

Yeah, but using an interface mean you have to create an interface for each callback which means every function you want to pass it set. Creating a delegate class to handle this gives you (not a true function pointer) but the function to be passed and if you abuse a generic to be the return type, you don't have to cast which cuts the bottleneck down to almost nothing.

The c# delegate (MultiCastDelegate to be correct) gets the info from using method MethodInfo which is the same thing you would need to do for the Delegate class using java.lang.reflect.method. I posted my code for the Delegate(T) class on another form of this site dealing with this extact issue. I make it because (yes) being from C++ I need a better way for passing functions (especially Void) then having to create an interface for on function or more. Now I can choose the function filling in the parameter information for it. Voila`! Nice and usable with no noticeable lose in speed from JIT or JVM. And if I did having only learning java programming for only a week, any java programmer can do it.

Also, it serves very well when creating a base listener and a base interface to pass in the listener. No more having to write another listener because the name of the function has changed. Creating a delegate class has great advantages as is very useable and passable.

查看更多
爷的心禁止访问
4楼-- · 2019-02-06 12:42

Have you ever used Swing/AWT? Their Event hierarchy solves a similar problem. The way Java passes functions around is with an interface, for example

public interface ActionHandler {
    public void actionPerformed(ActionArgs e);
}

Then, if you want to map integers onto these objects, you could use something like a java.util.HashMap<Integer,ActionHandler> to manage that. The actual implementations can either go in anonymous classes (Java's best approximation of "lambda") or in proper classes somewhere. Here's the anonymous class way:

HashMap<Integer,ActionHandler> handlers;
handlers.put(ACTION_FROB, new ActionHandler() {
    public void actionPerformed(ActionArgs e) {
        // Do stuff
        // Note that any outer variables you intend to close over must be final.
    }
});
handlers.get(ACTION_FROB).actionPerformed(foo);

(edit) If you want to be even more abusive, you can initialize the HashMap like so:

HashMap<Integer,String> m = new HashMap<Integer,String>() {{
    put(0,"hello");
    put(1,"world");
}};
查看更多
登录 后发表回答