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条回答
The star\"
2楼-- · 2019-02-06 12:16

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

查看更多
够拽才男人
3楼-- · 2019-02-06 12:16

You could interface static methods. This method allows you to specify parameters too. Declare your interface...

public interface RouteHandler {
    void handleRequest(HttpExchange t) throws IOException;
}

And your map...

private Map<String, RouteHandler> routes = new HashMap<>();

Then implement static methods that match the interface/params...

public static void notFound(HttpExchange t) throws IOException {
    String response = "Not Found";

    t.sendResponseHeaders(404, response.length());
    OutputStream os = t.getResponseBody();
    os.write(response.getBytes());
    os.close();
}

You can then add those methods into your map...

routes.put("/foo", CoreRoutes::notFound);

and call them as follows...

RouteHandler handler = routes.get("/foo");
handler.handleRequest(exchange);
查看更多
虎瘦雄心在
4楼-- · 2019-02-06 12:21

Java does not have first-class function pointers. In order to achieve similar functionality, you have to define and implement an interface. You can make it easier using anonymous inner classes, but it's still not very pretty. Here's an example:

public interface PacketProcessor
{
    public void processPacket(Packet packet);
}

...

PacketProcessor doThing1 = new PacketProcessor()
{
    public void processPacket(Packet packet)
    {
        // do thing 1
    }
};
// etc.

// Now doThing1, doThing2 can be used like function pointers for a function taking a
// Packet and returning void
查看更多
等我变得足够好
5楼-- · 2019-02-06 12:22

What about this one?

HashMap<Integer, Runnable> map = new HashMap<Integer, Runnable>();
map.put(Register.ID, new Runnable() { 
    public void run() { functionA(); }
});
map.put(NotifyMessage.ID, new Runnable() { 
    public void run() { functionB(); }
});
// ...
map.get(id).run();

(If you need to pass some arguments, define your own interface with a function having a suitable parameter, and use that instead of Runnable).

查看更多
混吃等死
6楼-- · 2019-02-06 12:28

You can do this through the use of the chain of responsibility pattern.

It is a pattern that links different objects to together kind of like a linked list. i.e. Each object has a reference to next in the chain. The objects in the chain usually handles one specific behavior. The flow between the objects is very similar to the switch-case statement.

There are some gotchas, such as, it spreads your logic out, an excessively long chain can cause performance problems. But along with these gotchas you have the benefit of increased testability, and stronger cohesion. Also you are not limited to the using enum, byte, int short, and char expressions as the trigger for branching.

查看更多
Luminary・发光体
7楼-- · 2019-02-06 12:29

Java doesn't really have function pointers (we got anonymous inner classes instead). There's really nothing wrong with using a switch, though, as long as you're switching on value and not on type. Is there some reason you don't want to use a switch? It seems like you'll have to do a mapping between Action IDs and actions somewhere in your code, so why not keep it simple?

查看更多
登录 后发表回答