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

基于枚举实现接口的泛型类,如何设置ID枚举默认值?

解决方案分析

首先说原代码报错的根本原因:泛型类型擦除。运行时T.class会被擦除为SortColumnType.class,而这是个接口不是枚举类,所以Enum.valueOf必然抛出异常。

要在无参构造下给sortColumn设置默认的ID枚举值,有两种可行方案,且都能通过创建公共类实现:

方案1:创建泛型子类 + 反射查找枚举常量

  1. 原接口和枚举类保持不变。
  2. 修改SortColumn类,通过初始化块配合反射获取实际泛型类型,再定位到ID枚举:
@Setter
@NoArgsConstructor
public class SortColumn<T extends SortColumnType> {

    private T sortColumn;
    private SortType sortDirection = SortType.ASC;

    @SuppressWarnings("unchecked")
    {
        try {
            Type genericSuperclass = getClass().getGenericSuperclass();
            // 只有通过指定具体泛型的子类实例化,才能获取到实际泛型类型
            if (!(genericSuperclass instanceof ParameterizedType)) {
                throw new IllegalStateException("请使用指定具体泛型的子类创建实例,例如OneSortColumn");
            }
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            Class<T> enumClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
            
            // 遍历枚举常量,筛选出名为"ID"的实例
            for (T constant : enumClass.getEnumConstants()) {
                if (constant.name().equals("ID")) {
                    sortColumn = constant;
                    break;
                }
            }
            
            if (sortColumn == null) {
                throw new IllegalArgumentException("枚举类 " + enumClass.getName() + " 中不存在名为ID的常量");
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化默认排序字段失败", e);
        }
    }
}
  1. 为每个枚举类创建对应的公共子类:
// 对应OneSortColumnType的子类
public class OneSortColumn extends SortColumn<OneSortColumnType> {}

// 对应SecondSortColumnType的子类
public class SecondSortColumn extends SortColumn<SecondSortColumnType> {}
  1. 使用时直接调用无参构造:
SortColumn<OneSortColumnType> sortCol = new OneSortColumn();
// 此时sortCol的sortColumn即为OneSortColumnType.ID

方案2:给枚举类添加统一静态方法 + 反射调用

  1. 给每个实现SortColumnType的枚举类添加getDefault()静态方法,返回ID实例:
public enum OneSortColumnType implements SortColumnType {
    ID("id"), NAME("name");

    private final String name;

    OneSortColumnType(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    public static OneSortColumnType getDefault() {
        return ID;
    }
}

public enum SecondSortColumnType implements SortColumnType {
    ID("id"), DATE("date");

    private final String name;

    SecondSortColumnType(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    public static SecondSortColumnType getDefault() {
        return ID;
    }
}
  1. 修改SortColumn类,通过反射调用枚举的getDefault()方法:
@Setter
@NoArgsConstructor
public class SortColumn<T extends SortColumnType> {

    private T sortColumn;
    private SortType sortDirection = SortType.ASC;

    @SuppressWarnings("unchecked")
    {
        try {
            Type genericSuperclass = getClass().getGenericSuperclass();
            if (!(genericSuperclass instanceof ParameterizedType)) {
                throw new IllegalStateException("请使用指定具体泛型的子类创建实例");
            }
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            Class<T> enumClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
            
            Method getDefaultMethod = enumClass.getMethod("getDefault");
            sortColumn = (T) getDefaultMethod.invoke(null);
        } catch (Exception e) {
            throw new RuntimeException("初始化默认排序字段失败", e);
        }
    }
}
  1. 同样通过对应公共子类的无参构造实例化即可。

关于公共类的可行性

当然可以通过公共类实现需求。上述两种方案中的OneSortColumn、SecondSortColumn就是公共类,它们明确指定了泛型的实际类型,让反射能够获取到枚举类的Class对象,从而正确初始化默认的ID枚举值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:20:44