使用参数化参数调用方法
Invoking methods with parametrized arguments
我目前正在构建一个事件系统来处理我的应用程序中的一些事件。 EventDispatcher 调用带有参数的方法,这些参数可从事件的 class 分配。这适用于非参数化参数,但我找不到使用参数化参数(具有通用类型的参数)执行此操作的解决方案。
我如何过滤那些?
这是我的 Dispacher 的一小段摘录:
private final Event event; // custom Event-class
private final Map<Object, List<Method>> subscriber;
/* snip */
@Override
public void run() {
subscriber.forEach((sub, methods) -> methods.stream()
// filter for matching event methods
.filter(m -> {
// returns true, even if generic types do not match
return m.getParameters()[0].getType().isAssignableFrom(event.getClass());
})
.forEach(m -> {
try {
m.invoke(sub, event);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} catch (Exception e) {
LOGGER.error("...", e);
}
})
);
}
注意:订阅者映射中的给定方法已经具有所需的 return 类型、1 参数和标识事件方法的注解。
编辑: 来自评论:
问题是,当我检查 Event<Integer> isAssignableFrom( Event<String> )
时,Java return 是真的
经过一些测试和进一步阅读后,我想出了一个测试,看看我是否可以通过 Types:
来匹配泛型
private static boolean test(Type type1, Type type2) {
if (type1 == type2) return true;
if (type1.getTypeName().equals(type2.getTypeName())) {
if (type1 instanceof ParameterizedType || type2 instanceof ParameterizedType) {
if (type1 instanceof ParameterizedType && type2 instanceof ParameterizedType) {
Type[] type1Params = ((ParameterizedType) type1).getActualTypeArguments();
Type[] type2Params = ((ParameterizedType) type2).getActualTypeArguments();
if (type1Params.length != type2Params.length) return false;
for (int i = 0; i < type1Params.length; i++) {
if (!test(type1Params[i], type2Params[i])) return false;
}
return true; // all generic types in both types are equal pairwise
}
return false; // one with generic type and one without
}
return true; // both no generic types
}
return false; // not equal by name
}
我的结果:
- 您可以将方法的两个参数与此匹配,因为 Method can return a Type[] with getGenericParameterTypes.
- 您无法检查两个实例是否具有相同的通用类型。因为您通过 getClass 获得类型,所以只有您拥有实例的 Class 的类型将在没有通用类型的情况下返回。
见Type Erasure
我目前正在构建一个事件系统来处理我的应用程序中的一些事件。 EventDispatcher 调用带有参数的方法,这些参数可从事件的 class 分配。这适用于非参数化参数,但我找不到使用参数化参数(具有通用类型的参数)执行此操作的解决方案。
我如何过滤那些?
这是我的 Dispacher 的一小段摘录:
private final Event event; // custom Event-class
private final Map<Object, List<Method>> subscriber;
/* snip */
@Override
public void run() {
subscriber.forEach((sub, methods) -> methods.stream()
// filter for matching event methods
.filter(m -> {
// returns true, even if generic types do not match
return m.getParameters()[0].getType().isAssignableFrom(event.getClass());
})
.forEach(m -> {
try {
m.invoke(sub, event);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} catch (Exception e) {
LOGGER.error("...", e);
}
})
);
}
注意:订阅者映射中的给定方法已经具有所需的 return 类型、1 参数和标识事件方法的注解。
编辑: 来自评论:
问题是,当我检查 Event<Integer> isAssignableFrom( Event<String> )
经过一些测试和进一步阅读后,我想出了一个测试,看看我是否可以通过 Types:
来匹配泛型private static boolean test(Type type1, Type type2) {
if (type1 == type2) return true;
if (type1.getTypeName().equals(type2.getTypeName())) {
if (type1 instanceof ParameterizedType || type2 instanceof ParameterizedType) {
if (type1 instanceof ParameterizedType && type2 instanceof ParameterizedType) {
Type[] type1Params = ((ParameterizedType) type1).getActualTypeArguments();
Type[] type2Params = ((ParameterizedType) type2).getActualTypeArguments();
if (type1Params.length != type2Params.length) return false;
for (int i = 0; i < type1Params.length; i++) {
if (!test(type1Params[i], type2Params[i])) return false;
}
return true; // all generic types in both types are equal pairwise
}
return false; // one with generic type and one without
}
return true; // both no generic types
}
return false; // not equal by name
}
我的结果:
- 您可以将方法的两个参数与此匹配,因为 Method can return a Type[] with getGenericParameterTypes.
- 您无法检查两个实例是否具有相同的通用类型。因为您通过 getClass 获得类型,所以只有您拥有实例的 Class 的类型将在没有通用类型的情况下返回。
见Type Erasure