如何实现跨多个枚举类的MyEnum属性匹配查找工具方法?
问题:实现多枚举类的attribute匹配查找工具方法
现有代码定义
MyEnum接口
interface MyEnum<E extends Enum<E> & MyEnum<E, T>, T> { static <E extends Enum<E> & MyEnum<E, T>, T> E valueOfAttribute( Class<E> enumClass, T attributeValue) { for (final E enumConstant : enumClass.getEnumConstants()) { if (Objects.equals(enumConstant.attribute(), attributeValue)) { return enumConstant; } } throw new IllegalArgumentException( "no enum constant, from " + enumClass + ", for " + attributeValue); } T attribute(); }
相关枚举接口与实现类
interface YourEnum<E extends Enum<E> & YourEnum<E>> extends MyEnum<E, String> { @Override default String attribute() { return ((Enum<?>) this).name(); } } enum HisEnum implements YourEnum<HisEnum> { HIS } enum HerEnum implements YourEnum<HerEnum> { HER }
注:原代码中
YourEnum的泛型约束存在冗余,已修正为E extends Enum<E> & YourEnum<E>,同时将attribute()改为默认方法(接口中直接实现方法需加default)
需求描述
需要新增一个静态工具方法,从一个或多个实现MyEnum同一子接口的枚举类中,找到第一个attribute()返回值与指定值匹配的枚举常量。示例调用如下:
// 应返回HisEnum.HIS MyEnum.valueOfAttribute("HIS", HisEnum.class, HerEnum.class);
尝试的代码(编译失败)
以下是尝试实现的方法,但无法通过编译:
// 编译失败 static <T extends MyEnum<? extends Enum<?>, U>, U> T valueOfAttribute( U attributeValue, Class<? extends T> enumClass, Class<? extends T>... otherEnumClasses) { return Stream.concat(Stream.of(enumClass), Stream.of(otherEnumClasses)) .map(t -> { try { return valueOfAttribute(t, attributeValue); // 编译错误:类型不匹配 } catch (IllegalArgumentException iae) { return null; } }) .filter(Objects::nonNull) .findFirst() .orElseThrow(() -> new IllegalArgumentException( "no enum constant, from " + enumClass + " + and " + Arrays.toString(otherEnumClasses) + ", for " + attributeValue)); }
解决方案
修正后的工具方法
首先调整原MyEnum中的valueOfAttribute方法,将参数类型改为Class<? extends E>以提升灵活性(枚举类本身是final的,此修改无风险):
static <E extends Enum<E> & MyEnum<E, T>, T> E valueOfAttribute( Class<? extends E> enumClass, T attributeValue) { for (final E enumConstant : enumClass.getEnumConstants()) { if (Objects.equals(enumConstant.attribute(), attributeValue)) { return enumConstant; } } throw new IllegalArgumentException( "no enum constant, from " + enumClass + ", for " + attributeValue); }
然后新增多枚举类查找的工具方法:
import java.util.Arrays; import java.util.Objects; import java.util.stream.Stream; // 放在MyEnum接口中 static <U, E extends Enum<E> & MyEnum<E, U>> E valueOfAttribute( U attributeValue, Class<? extends E> firstEnumClass, Class<? extends E>... otherEnumClasses) { return Stream.concat(Stream.of(firstEnumClass), Stream.of(otherEnumClasses)) .map(clazz -> { try { return valueOfAttribute(clazz, attributeValue); } catch (IllegalArgumentException e) { return null; } }) .filter(Objects::nonNull) .findFirst() .orElseThrow(() -> new IllegalArgumentException( "no enum constant, from " + firstEnumClass + " and " + Arrays.toString(otherEnumClasses) + ", for " + attributeValue)); }
关键调整说明
- 泛型约束修正:
- 新增泛型参数
U统一表示attribute()的返回值类型 E同时约束为Enum<E>和MyEnum<E, U>,确保所有传入的枚举类既是枚举类型,又实现了同一MyEnum子接口,满足原valueOfAttribute方法的调用条件
- 新增泛型参数
- 参数类型兼容:
- 将枚举类参数类型改为
Class<? extends E>,既保证类型安全,又允许传入具体的枚举实现类(如HisEnum.class)
- 将枚举类参数类型改为
- 异常处理与返回值:
- 单个枚举类查找失败时返回
null,过滤后取第一个非空结果;若全部失败则抛出统一的异常
- 单个枚举类查找失败时返回
调用示例
// 自动类型推断,无需显式指定泛型 YourEnum<?> result = MyEnum.valueOfAttribute("HIS", HisEnum.class, HerEnum.class); System.out.println(result); // 输出 HIS
内容的提问来源于stack exchange,提问作者Jin Kwon
相关产品推荐
相关产品推荐

