user3745394
user3745394

Reputation: 37

Storing and calling method in a Map with generics

I am trying to learn a bit of what I consider more complex Java, I got interested in Generics as I noticed it can do amazing things. I thought about doing this: Have a Map that will store a class and some form of method, this would be used so in case of giving a certain class, lets say String.class it would run the code inside the method.

I saw it being done and working on a project called ACF (Aikar command framework).

An example of how it manages to register the new method:

registerContext(char.class, c -> {
    String s = c.popFirstArg();
    if (s.length() > 1) {
        throw new InvalidCommandArgument(MessageKeys.MUST_BE_MAX_LENGTH, "{max}", String.valueOf(1));
    }
    return s.charAt(0);
});

His register method seems simple being just:

// The map
protected final Map<Class<?>, ContextResolver<?, R>> contextMap = new HashMap<>();
// The register class
public <T> void registerContext(Class<T> context, ContextResolver<T, R> supplier) {
    contextMap.put(context, supplier);
}

I tried making something similar but yet I couldn't really understand. I am whiling to do more research, but at this point I don't know what to search for. I don't know what this type of method storage or method declaration is called. I watched a few videos and read a few posts about the generics in Java but mostly stay very basic which I manage to understand, but still can't figure out how this works. The results I expect is to be able to for example call contextMap.get(class).run() and it would invoke the method.

edit:
PS: I'm not asking anyone to write code for me or do this or that, just to point me in the right direction to learn and I'll do the rest myself. Or maybe some small explanations about generics.

Upvotes: 1

Views: 145

Answers (1)

Shadov
Shadov

Reputation: 5591

In Java 8 there are few functional interfaces that help with this kind of functionality: Function, Supplier, Consumer and Runnable (which is older).

Runnable is simply a piece of code to run, no input, no output. You probably have seen it before: to create a new Thread you need to provide a Runnable and then the new Thread invokes that code. Supplier is something similar, but it returns a value. Consumer accepts input, but it does not return anything. Function has both input and output, in your example something similar is used.

So basically, depending on what you want, you can create a map of methods, where key is the name of the method and value is a runnable (piece of code to run) - Map<String, Runnable>.

Map<String, Runnable> methodMap = new HashMap<>();
methodMap.put("say hello", () -> System.out.println("Hello"));
methodMap.put("say goodbye", () -> System.out.println("Goodbye"));

methodMap.get("say hello").run();

All this has a little to do with generics, but imagine you wanted to store methods with input and output, that would become problematic. You would need something like Map<String, Function<?, ?>>.

Upvotes: 1

Related Questions