繁体   English   中英

任何扩展的通用枚举类型

[英]Generic Enum Type for anything extended

我喜欢制作一个可以接受任何东西的通用枚举。

对于这个例子,我使用 TaskStatus,但在未来,我更喜欢使用 Generic Enum; StudentStatus,这个学生身份可以自己带一个id和描述,它会自动转换。 而且,迭代每一个object,最后自动返回。 我有机会成功吗?

 @Getter
 @AllArgsConstructor(access = AccessLevel.PRIVATE)
  public enum TaskStatusEnum{
    
        READY(1, "Ready"),
        ON_GOING (2,"On going");
        
        private final long id;
        private final String description;
        
        
        public static TaskStatusEnum get (long id)
        {
            for (TaskStatusEnum status : TaskStatusEnum.values()) {
                if (status.id == id) {
                    return id;
                }
            }
            return null;
        }

我不确定你到底想要什么。 您可以在枚举上使用接口,然后您可以将接口用作状态,而不必关心 class 究竟是什么状态。

public interface Status<E extends Enum<E> & Status<E>> {

    public long getId();
    public String getDescription();

}

学生身份:

public enum StudentStatus implements Status<StudentStatus>{

    NEW(0, "new");

    ;

    private long id;
    private String description;

    private StudentStatus(long id, String description) {
        this.id=id;
        this.description = description;
    }

    @Override
    public long getId() {
        return id;
    }

    @Override
    public String getDescription() {
        return description;
    }

}

任务状态:

public enum TaskStatus implements Status<TaskStatus>{

    OPEN(0, "open");

    ;

    private long id;
    private String description;

    private TaskStatus(long id, String description) {
        this.id=id;
        this.description = description;
    }

    @Override
    public long getId() {
        return id;
    }

    @Override
    public String getDescription() {
        return description;
    }
}

通过 id 查找状态的通用方法

public abstract class StatusUtil {

public static <E extends Enum<E> & Status<E>> E get(Class<E> statusClass, long id) {
        return Arrays.asList((E[]) statusClass.getEnumConstants())
            .stream()
            .filter(item -> item.getId() == id)
            .findAny()
            .orElse(null);
    }
}

示例如何使用:

public class Test {

    public static void main(String... args) {
        StudentStatus studentStatus = StatusUtil.get(StudentStatus.class, 0);
        TaskStatus taskStatus = StatusUtil.get(TaskStatus.class, 0);
    
        List<Status> statusList = Arrays.asList(studentStatus, taskStatus);
        statusList.forEach(status -> System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription()));
    }
}

如果您使用低于 8 的 JAVA:

public interface Status<E extends Enum<E>> {

    public long getId();
    public String getDescription();

} 

状态工具:

public abstract class StatusUtil {

    public static <E extends Enum<E>> E get(Class<E> statusClass, long id) {
    for(E item: (E[]) statusClass.getEnumConstants()) {
        if(item.getId() == id) {
            return item;
        }
    }
    return null;
}

} 测试:

    public static void main(String... args) {
    StudentStatus studentStatus = StatusUtil.get(StudentStatus.class, 0);
    TaskStatus taskStatus = StatusUtil.get(TaskStatus.class, 0);
    
    List<Status> statusList = Arrays.asList(studentStatus, taskStatus);
    for(Status status: statusList) {
        System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription());
    }
}

当枚举具有相同的方法并且您需要通用接口时,您可以使用它

您的枚举实际上是final的(不允许子类)

显然你在问是否可以对TaskStatus枚举进行子类化。 例如制作一个继承自StudentStatusTaskStatus

➥ 不,Java 中的枚举不能被子类化。

您的 enum 定义实际上是Enum的子类。 这发生在后台,由编译器神奇地处理 inheritance 停在那里。 您的枚举定义实际上是final ,不允许进一步的子类。

枚举定义可以实现接口 来自多个枚举定义的实例可以被视为同一个接口的所有对象。 请参阅Victor1125 的回答

Java 中的枚举是自动实例化一个或多个名称对象的便捷方式,以表示在编译时已知的一组有限值。 当它们的定义 class 由Java 类加载器加载时,这些实例都会出现。 这些对象保留在 memory 中。

您不能在运行时动态添加更多实例。 枚举对象的整个域是在编译时定义的。 (例外:一些疯狂的扭曲反射/内省代码可能能够创建更多实例,但我不会 go 那里。)

如果您想要 inheritance 或动态创建的实例,请不要使用枚举。 使用常规类和子类,收集到集合或列表中。 集合或列表可以用 generics 标记 ( < … > ) 以允许其包含元素的超类。 例如Set< Animal >可以包含子类DogCatBird的对象。

By the way, you can now define an enum in 3 places: its own class, nested within another class, and now in Java 16 (previewed in Java 15), locally inside a method.

提示:无需在您的枚举名称中添加“枚举”。 努力为您的枚举 class 和自然读取的枚举对象发明名称。 他们碰巧是一个枚举的事实应该消失在背景中。 例如:参见Month ( Month.JANUARY ) 和DayOfWeek ( DayOfWeek.MONDAY )。

如何处理 StatusUtil.class 上的 null 点

状态工具:

公共抽象 class StatusUtil {

 public static <E extends Enum<E>> E get(Class<E> statusClass, long id) {
    for(E item: (E[]) statusClass.getEnumConstants()) {
        if(item.getId() == id) {
            return item;
        }
    }
    return null;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM