简体   繁体   中英

Generic Enum Type for anything extended

I like to make a generic enum that accepts anything.

For this example I use TaskStatus, but in the future, I like to use Generic Enum for example; StudentStatus, this student status can take an id and description itself and it will convert automatically. Moreover, iterate every object and finally automatically return. Is there any chance I can make it?

 @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;
        }

I'm not sure what exactly you want. You can use interface on enum, then you can use interface as status and dont care what exactly status class is.

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

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

}

student status:

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;
    }

}

task status:

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;
    }
}

generic method to find out status by 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);
    }
}

example how use:

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()));
    }
}

if you use JAVA below 8:

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

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

} 

statusUtil:

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;
}

} 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);
    for(Status status: statusList) {
        System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription());
    }
}

This you can use in cases, when enums has this same methods and you need common interface

Your enum is effectively final (no subclass allowed)

Apparently you are asking if TaskStatus enum can be subclassed. For example making a StudentStatus that inherits from TaskStatus .

➥ No, enums in Java cannot be subclassed.

Your enum definition actually is a subclass of Enum . That happens in the background, magically handled by the compiler . The inheritance stops there. Your enum definition is effectively final , not allowing further subclasses.

An enum definition can implement an interface . Instances from multiple enum definitions can be treated as all being objects of the same interface. See Answer by Victor1125 .

An enum in Java is a convenient way to automatically instantiate one or more name objects, to represent a limited set of values known at compile time. Those instances all pop into existence when their definition class is loaded by the Java classloader . Those objects remain in memory.

You cannot add more instances dynamically at runtime. The entire domain of the enum's objects is defined at compile time. (Exception: Some crazy twisted reflection/introspection code may be able to create more instances, but I would not go there.)

If you want inheritance, or dynamically created instances, do not use enums. Use regular classes and subclasses, collected into sets or lists. The sets or lists can be marked ( < … > ) with generics to allow the superclass of their contained elements. For example Set< Animal > can contain objects of the subclasses Dog , Cat , and Bird .

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.

Tip: No need to put "Enum" within the name of your enum. Endeavor to invent names for your enum class and enum objects that read naturally. The fact that they happen to be an enum should fade into the background. For example: See Month ( Month.JANUARY ) and DayOfWeek ( DayOfWeek.MONDAY ).

How to handle null point on StatusUtil.class

StatusUtil:

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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