Function pointers/delegates in Java?

前端 未结 10 1356
有刺的猬
有刺的猬 2020-12-15 21:06

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.

相关标签:
10条回答
  • 2020-12-15 21:22

    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.

    0 讨论(0)
  • 2020-12-15 21:23

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

    0 讨论(0)
  • 2020-12-15 21:28

    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?

    0 讨论(0)
  • 2020-12-15 21:29

    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

    0 讨论(0)
  • 2020-12-15 21:30

    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.

    0 讨论(0)
  • 2020-12-15 21:30

    You can use things in java.util.function (For Java 8+) to store a function. java.util.function docs

    You have to go through this list and pick an appropriate function-class to use. I'll be using BiConsumer, which says:

    Takes two inputs. Returns no result. Operates through side effects.

    import java.util.function.BiConsumer;
    import java.util.HashMap;
    import java.util.Map;
    
    public void init(){
      //<actionId, function<arg1, arg2>>
      Map<Integer, BiConsumer<String, String>> actionMap = new HashMap<>();
      actionMap.put(123, this::someMethod);
    
      //note (optional): check key first: map.containsKey(someActionId)
      //call someMethod("argument1", "argument2")
      actionMap.get(123).accept("argument1", "argument2");
    }
    
    public void someMethod(String a, String b){
      //do something here
    }
    
    0 讨论(0)
提交回复
热议问题