Reputation: 614
I've made my own EventExecutor
class, which has the type <T extends Event>
.
public interface EventExecutor<T extends Event> {
...
public abstract void execute(Event event);
}
and I know right now that this up here is wrong, because I'm wanting to pass in:
public abstract void execute(T event);
I've been working on an Event Management System
, and when an Event
isn't cancelled after all other events have ran, certain code will run from the EventExecutor
as shown:
// event parameter should be of type T.
EventManager.call(event -> {
// code here.
}, Class<? extends Event>, Object... eventParameters);
The problem here is since the EventExecutor
method execute
has the parameter of Event
, that means event ->
is of type Event
, and not the wanted class that extends Event
, so that means I have to do some casting, which isn't what I want to do.
The problem that keeps me from using the generic type of T
is my EventManager
class's method call
:
public static void call(EventExecutor<? extends Event> eventExecutor, Class<? extends Event> eventClass, Object... eventArgs) {
synchronized (LOCK) {
if (!checkIsEventClassRegistered(eventClass)) return;
try {
Event event = null;
Class<?>[] constructorParameters = EventUtilities.getArrayOfClasses(eventArgs);
Constructor<?> constructor = eventClass.getDeclaredConstructor(constructorParameters);
event = (Event) constructor.newInstance(eventArgs);
// HERE:
if (!callAllRegisteredMethods(event)) eventExecutor.execute(event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'll admit, I'm new to generics, and I don't see what's so wrong with everything. I've tried casting event
(in the eventExecutor.execute(...)
method) to T
, but it tells me to create the method in EventExecutor
called eventExecutor.execute(T)
, but then EventExecutor
throws an error, because it wants T
to be a class that I create in the same package.
What am I doing wrong?
Edit
So basically, in the end I want to be able to not have to cast to my wanted Event
class:
EventManager.call(event -> {
// Have this automatically be recognized as an instance of MyEventClass?
System.out.println(event.getText());
}, MyEventClass.class, new String("text"));
Upvotes: 0
Views: 458
Reputation: 24286
Can you make call
a generic method?
public static <T extends Event> void call(
EventExecutor<T> eventExecutor, Class<T> eventClass, Object... eventArgs) {
synchronized (LOCK) {
if (!checkIsEventClassRegistered(eventClass)) return;
try {
Class<?>[] constructorParameters = EventUtilities.getArrayOfClasses(
eventArgs);
Constructor<?> constructor = eventClass.getDeclaredConstructor(
constructorParameters);
T event = eventClass.cast(constructor.newInstance(eventArgs));
if (!callAllRegisteredMethods(event)) eventExecutor.execute(event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Note I replaced the cast to a call to Class.cast()
.
Edit: The only reason why EventExecutor
has to be generic is because you want to pass in an anonymous function/class to do the execution, and you want that function/class to depend on the actual type of the event. To avoid confusion, I would call it an EventCallback
, since EventExecutor
sounds similar to java.util.concurrent.Executor
, so I was left wondering why you would want more than one.
Incidentally, it's probably not a good idea to call so much code that isn't under your control while you are in a synchronized block.
Upvotes: 1