现在有这样一个场景:有一个按钮监听器类ButtonListener

ButtonListener.java
1
2
3
4
5
6
import me.lolico.demo.button.event.ButtonEvent;
import java.util.EventListener;

public interface ButtonListener<E extends ButtonEvent> extends EventListener {
void onButtonEvent(E event);
}

以及一个监听按钮name是否改变即ButtonNameHasChangedEvent事件的实现类ButtonNameListener

ButtonNameListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import me.lolico.demo.button.Button;
import me.lolico.demo.button.ButtonListener;
import me.lolico.demo.button.event.ButtonNameHasChangedEvent;

/**
* @author Lolico li
*/
public class ButtonNameListener implements ButtonListener<ButtonNameHasChangedEvent> {
@Override
public void onButtonEvent(ButtonNameHasChangedEvent event) {
Button button = (Button) event.getSource();
System.out.println(button + "name has changed!");
}
}

当我们调用设置按钮setName方法时需要发布ButtonNameHasChangedEvent事件,我们需要怎么去通知监听这个事件的监听器呢?

我们需要获取到所有的按钮监听器,然后遍历,获取泛型类型,如果类型匹配,那么则通知这个监听器

所以现在问题变成了如何获取按钮监听器的泛型类型,如果我们百度一下,清一色的答案都是下面这种:

获取某个类的泛型参数的类型
1
((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()

对于这种场景,那么就是一个异常抛出:

1
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

为什么呢,因为Class#getGenericSuperclass()方法返回的是超类的Type,所以说这种方法只能用于获取超类上面的泛型类型,而我们上面的案例明显是要获取接口上的的泛型类型,所以我们应该使用的是Class#getGenericInterfaces()方法。

获取一个类上的所有泛型类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
public Set<Type> resolveGenericType(Class<?> clazz) {
Set<Type> genericSet = new HashSet<>();
Type superclass = clazz.getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
genericSet.addAll(Arrays.asList(((ParameterizedType) superclass).getActualTypeArguments()));
}
Type[] interfaces = clazz.getGenericInterfaces();
for (Type type : interfaces) {
Type[] genericType = ((ParameterizedType) type).getActualTypeArguments();
genericSet.addAll(Arrays.asList(genericType));
}
return genericSet;
}

注意:获取的泛型类型不包括实现的接口继承的接口上的泛型类型,因为Class#getGenericInterfaces()方法不是递归获取所有接口类型,只获取当前类实现的接口的类型。