现在有这样一个场景:有一个按钮监听器类ButtonListener
:
ButtonListener.java1 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.java1 2 3 4 5 6 7 8 9 10 11
| import me.lolico.demo.button.Button; import me.lolico.demo.button.ButtonListener; import me.lolico.demo.button.event.ButtonNameHasChangedEvent;
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()
方法不是递归获取所有接口类型,只获取当前类实现的接口的类型。