泛型获取

父类想获取子类上的泛型,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class AbsFileHandle<T> {
public void start(String filepath){
//文件转对象
//preview(t);
}
protected abstract void preview(T t);
}

public class File1Handle extends AbsFileHandle<DemoFile1>{
@Override
protected void preview(DemoFile1 demoFile1) {

}
}

public class DemoFile1 {
}

解决办法有多种:

  • 写个抽象方法,返回具体类型
  • 写个构造方法,参数是具体类型
  • 通过反射获取

采用反射获取如下

1
2
3
4
5
6
public AbsFileHandle() {
Type type = this.getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) type).getActualTypeArguments();
//noinspection unchecked
childClazz = (Class<T>) params[0];
}

上面代码就可以获取到子类的泛型。

Spring泛型消息处理

在Spring中如果需要监听消息,消息又是泛型时,因为泛型擦除导致不符合预期。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//泛型事件
public class BaseEvent<T>extends ApplicationEvent {
private T data;
private int times;

public BaseEvent(T source) {
super(source);
}
public void handle(){
times += 1;
}

public int getTimes() {
return times;
}

public T getData() {
return data;
}
}
//消息处理
@EventListener
public void listener(BaseEvent<String> event) {
event.handle();
}
@EventListener
public void listener2(BaseEvent<Integer> event) {
event.handle();
}
//消息测试
@SpringBootTest(classes = Application.class)
public class EventTest {
@Autowired
private ApplicationContext context;
@Test
public void event(){
BaseEvent<String> event1 = new BaseEvent<>("123");
context.publishEvent(event1);
assertEquals(event1.getTimes(), 1);
BaseEvent<Integer> event2 = new BaseEvent<>(123);
context.publishEvent(event2);
assertEquals(event1.getTimes(), 1);
}
}

上述消息测试中,发送消息后,会被处理2次,也就是两个消息监听器都做了处理。

如果需要对应泛型指处理一次,需要改进如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

public class BaseEvent<T>extends ApplicationEvent implements ResolvableTypeProvider {
private T data;
private int times;

public BaseEvent(T source) {
super(source);
}
public void handle(){
times += 1;
}

public int getTimes() {
return times;
}

public T getData() {
return data;
}

@Override
public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getSource()));
}
}

实现ResolvableTypeProvider接口。原理应该是消息监听推送时如果是ResolvableTypeProvider子类,那就调用方法获取对应泛型类型。

参考:
context-functionality-events-generics