泛型中?的使用
泛型中?的作用
概念
无边界通配符?
可以直接定义变量的
Point的定义
class Point<T> {
private T x;
private T y;
public Point(){
}
public Point(T x,T y){
this.x = x;
this.y = y;
}
public void setX(T x) {
this.x = x;
}
public void setY(T y) {
this.y = y;
}
public T getX() {
return this.x;
}
public T getY() {
return this.y;
}
}
?的使用
Point<?> point;
point = new Point<Integer>(3,3);
point = new Point<Float>(4.3f,4.3f);
point = new Point<Double>(4.3d,4.90d);
point = new Point<Long>(12l,23l);
1.生产中的例子,用于方法传参中的类型限定
Page<T> page = slowLogService.getRecords(param);
completeAppInfo(page.getT());
private void completeAppInfo(List<? extends SlowLogRecord> records) {
records.forEach(record -> appInfoCompleter.convert(record));
}
2.生产中的栗子,用于不固定类型
@Slf4j
@Aspect
@Component
@Order(1)
public class FlushRedisAspect {
private ExecutorService executor = ThreadUtils.newDaemonSingleThreadExecutor("FLUSH-RESGROUP-CONFIG");
@Resource
FlushResGroupConfigService flushResGroupConfigService;
/**
* 雷达屏UMP配置的消费者
*/
private Consumer<RadarScreenUmpConfig> radarScreenConsumer = config -> {
config.getUmpKeys().forEach(umpKey -> {
syncToRedis(config.getResGroupCode(umpKey));
});
};
/**
* 告警描述详情的消费者
*/
private Consumer<AlarmDescDetailsDto> alarmDescDetailsConsumer = alarmDescDetailsDto -> {
String resGroupCode = alarmDescDetailsDto.getDefinition();
syncToRedis(resGroupCode);
};
/**
* 执行器路由表
*/
Map<Class<?>, Consumer<?>> executorRouter = new ImmutableMap.Builder<Class<?>, Consumer<?>>()
.put(RadarScreenUmpConfig.class, radarScreenConsumer)
.put(AlarmDescDetailsDto.class, alarmDescDetailsConsumer)
.build();
/**
* 根据参数类型获取执行器
*
* @param arg1 参数
* @return 执行器
*/
private Consumer<?> getExecutor(Object arg1) {
return executorRouter.getOrDefault(arg1.getClass(), o -> {
}).andThen(o -> log.info("配置实时刷新路由执行完毕: {}", o.getClass().getSimpleName()));
}
/**
* 刷新切入点
*/
@Pointcut("@annotation(delta.service.annotation.FlushRedis)")
public void flushPointCut() {
}
/**
* 切入点之前执行
*/
@Before("flushPointCut()")
private void before() throws Exception {
}
/**
* 切入点之后返回执行
*
* @param joinPoint 切入点
*/
@AfterReturning(pointcut = "flushPointCut()")
private void afterReturning(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
FlushRedis flushAnnotation = method.getAnnotation(FlushRedis.class);
if (flushAnnotation == null) {
return;
}
Object[] args = joinPoint.getArgs();
Object arg1 = args[0];
Consumer executor = getExecutor(arg1);
executor.accept(arg1);
}
/**
* 同步到Redis
*
* @param resGroupCode 资源组代码
*/
public void syncToRedis(String resGroupCode) {
// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
// @Override
// public void afterCommit() {
// executor.submit(new FlushResGroupConfigTask(UUID.randomUUID().toString(), resGroupCode));
// }
// });
flushResGroupConfigService.addResGroupCode(resGroupCode);
//
}
}
3.生产中的例子
我有2个converter,都是实现了Function接口
DongbootRequestConverter.java
public class DongbootRequestConverter implements Function<JobContext, InitializrRequest> {
@Override
public InitializrRequest apply(JobContext context) {return null;}
}
InfrastructureRequestConverter.java
public class InfrastructureRequestConverter implements Function<JobContext, ProjectDetailDto> {
@Override
public ProjectDetailDto apply(JobContext context) {return null;}
}
编写了一个ConverterManager管理者,用于策略模式的方式取到Converter
- 其中Map中的value是Function接口,但是因为Function中参数类型不固定,就写?
- 因为2个Converter的入参类型是一样的,在获取Converter的时候,入参是固定的,出参不一样,可以用泛型方法来标识
public class CodeParamConvertManager {
private static Map<CodeProviderPlatform, Function<?,?>> converters;
static {
converters = new ConcurrentHashMap<>();
converters.put(CodeProviderPlatform.Dongboot,new DongbootRequestConverter());
converters.put(CodeProviderPlatform.Infrastructure,new InfrastructureRequestConverter());
}
public static <T, R> Function<T, R> getConverter(CodeProviderPlatform platform){
@SuppressWarnings("unchecked")
Function<T, R> converter = (Function<T, R>) converters.get(platform);
if (converter == null) {
throw new IllegalArgumentException("Not supported code provider: " + platform);
}
return converter;
}
}
使用CodeParamConvertManager
- converter返回结果即使object了,因为泛型方法兼容各种形式
CodeProviderPlatform platformType = CodeProviderPlatform.Dongboot;
// 获取转换器并指定类型
Function<JobContext, ?> converter = CodeParamConvertManager.getConverter(platformType);
Object param = converter.apply(context);
原创:做时间的朋友