You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Java方法使其返回Map<Class<? super C>, A>类型注解结果

解决方案:优化方法签名以返回Map<Class<? super C>, A>

首先明确:你对返回类型的逻辑判断是完全正确的——遍历过程中收集到的所有类(当前类、父类、实现的接口及其父接口)都是C的泛型超类型,即Class<? super C>,因此可以安全地将结果转换为这个类型。

下面提供两种合理的实现方案,避免硬hack的同时满足类型约束:


方案1:保持核心方法不变,仅修改便捷方法

核心方法继续使用Map<Class<?>, A>作为累加器(兼容递归时的任意超类型),在便捷方法中基于业务逻辑进行安全的类型转换:

修改后的代码

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Objects;

// 核心方法保持原有逻辑,仅泛型参数适配
private static <A extends Annotation> Map<Class<?>, A> getAnnotationsByClassAnnotatedWith(
    Class<?> clazz, Class<A> annotationClass, Map<Class<?>, A> annotationsByClass,
    Set<Class<?>> encounteredClasses) {
  Class<?> nonNullClazz = Objects.requireNonNull(clazz);
  if (!encounteredClasses.contains(nonNullClazz)) {
    encounteredClasses.add(nonNullClazz);
    A classAnnotation = nonNullClazz.getAnnotation(annotationClass);
    if (classAnnotation != null) {
      annotationsByClass.put(nonNullClazz, classAnnotation);
    }
    // 遍历所有实现的接口
    for (Class<?> classInterface : nonNullClazz.getInterfaces()) {
      getAnnotationsByClassAnnotatedWith(classInterface, annotationClass, annotationsByClass, encounteredClasses);
    }
    // 遍历父类
    final Class<?> superClass = nonNullClazz.getSuperclass();
    if (superClass != null) {
      getAnnotationsByClassAnnotatedWith(superClass, annotationClass, annotationsByClass, encounteredClasses);
    }
  }
  return annotationsByClass;
}

// 便捷方法修改签名并添加安全转换
@SuppressWarnings({"unchecked", "rawtypes"})
public static <C, A extends Annotation> Map<Class<? super C>, A> getAnnotationsByClassAnnotatedWith(
    Class<C> clazz, Class<A> annotationClass) {
  // 基于业务逻辑,所有收集到的Class都是C的超类型,转换安全
  return (Map) getAnnotationsByClassAnnotatedWith(
      clazz, annotationClass, new HashMap<>(), new HashSet<>());
}

方案说明

  • 核心方法无需修改,递归调用时可以自由处理任意类型的超类/接口;
  • 便捷方法的类型转换是安全的:因为我们的遍历逻辑严格限制在C的继承/接口层级内,所有Map的键必然是C的超类型;
  • 使用@SuppressWarnings抑制警告是合理的,因为编译器无法理解业务逻辑的约束,但我们可以保证转换的安全性。

方案2:修改核心方法泛型,适配超类型递归

让核心方法的泛型直接支持? super C,递归时显式转换超类/接口的类型:

修改后的代码

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Objects;

private static <C, A extends Annotation> Map<Class<? super C>, A> getAnnotationsByClassAnnotatedWith(
    Class<C> clazz, Class<A> annotationClass, Map<Class<? super C>, A> annotationsByClass,
    Set<Class<?>> encounteredClasses) {
  Class<C> nonNullClazz = Objects.requireNonNull(clazz);
  if (!encounteredClasses.contains(nonNullClazz)) {
    encounteredClasses.add(nonNullClazz);
    A classAnnotation = nonNullClazz.getAnnotation(annotationClass);
    if (classAnnotation != null) {
      annotationsByClass.put(nonNullClazz, classAnnotation);
    }
    // 遍历接口:接口是C的超类型,安全转换
    for (Class<?> iface : nonNullClazz.getInterfaces()) {
      getAnnotationsByClassAnnotatedWith((Class<? super C>) iface, annotationClass, annotationsByClass, encounteredClasses);
    }
    // 遍历父类:父类是C的超类型,安全转换
    final Class<?> superClass = nonNullClazz.getSuperclass();
    if (superClass != null) {
      getAnnotationsByClassAnnotatedWith((Class<? super C>) superClass, annotationClass, annotationsByClass, encounteredClasses);
    }
  }
  return annotationsByClass;
}

@SuppressWarnings("unchecked")
public static <C, A extends Annotation> Map<Class<? super C>, A> getAnnotationsByClassAnnotatedWith(
    Class<C> clazz, Class<A> annotationClass) {
  return getAnnotationsByClassAnnotatedWith(clazz, annotationClass, new HashMap<>(), new HashSet<>());
}

方案说明

  • 核心方法的签名直接体现了返回值的类型约束;
  • 递归时的类型转换同样是安全的,因为接口和父类必然是C的超类型;
  • 仅需在递归调用处添加一次类型转换,整体代码的类型语义更清晰。

内容的提问来源于stack exchange,提问作者Garret Wilson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:28:16