泛型中?的使用

泛型中?的作用

概念

无边界通配符?

可以直接定义变量的

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

  1. 其中Map中的value是Function接口,但是因为Function中参数类型不固定,就写?
  2. 因为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

  1. converter返回结果即使object了,因为泛型方法兼容各种形式
CodeProviderPlatform platformType = CodeProviderPlatform.Dongboot;
// 获取转换器并指定类型
Function<JobContext, ?> converter = CodeParamConvertManager.getConverter(platformType);
Object param = converter.apply(context);

posted @ 2023-08-29 17:09  SpecialSpeculator  阅读(50)  评论(0编辑  收藏  举报