简体   繁体   中英

How to create a generic class in what I can call an Enum.valueOf() in Java?

So I have these classes:

public class DeviceInState implements MyInterface<Device> {

    private List<DeviceState> toStates(String statesString) {
        List<String> states = Lists.newArrayList(statesString.split(","));

        return states.stream().map(DeviceState::valueOf).collect(Collectors.toList());
    }
}

  
public class DeviceHistoryInState implements MyInterface<DeviceHistory> {
    private List<EventType> toStates(String statesString) {
        List<String> states = Lists.newArrayList(statesString.split(","));

        return states.stream().map(EventType::valueOf).collect(Collectors.toList());
    }
}

And these enums:

public enum EventType{
    NEW("N"), ACTIVE("A"), INACTIVE("I");
}
    
public enum DeviceState{
    REGISTRATED("R"), SUSPENDED("S"), DELETED("D");
}

The differences are:

  • DeviceInState implements MyInterface<Device> ; but DeviceHistoryInState implements MyInterface<DeviceHistory>

  • DeviceState::valueOf is called in DeviceInState ; but EventTypes::valueOf is called in DeviceHistoryInState

I have a couple of other classes like these so I would like to make a generic one. But I have no idea whether or not it is possible. How might I parameterize my classes or methods in a way that I can call the ::valueOf method?

Thanks in advance.

This is how I would do it

public interface State< E extends Enum< E > > { … }

Then my enums would implement that…

…
public enum DeviceState implements State< DeviceState > { … }
…
public enum EventType implements State< EventType > { … }
…

…Actually not these methods are overridden. These methods are just called from the overridden method…

Considering that you annotated the methods in your snippet with @Overrides , I found that to be a pretty confusing comment. To make things a little less confusing for myself, my experimental implementation does actually override something…

public class DeviceInState extends ToStateable< DeviceState > implements Specification< Device > {

    @Override
    public List< DeviceState > toStates( String statesString ) {
        
        List< String > states = asList( statesString.split( "," ) );

        return states.stream( ).map( String::trim ).map( DeviceState::valueOf ).collect(Collectors.toList());
    }
}

I was able to call that successfully like…

…
ToStateable< DeviceState > deviceToStateable = new DeviceInState( );
      
List< DeviceState > deviceStates = deviceToStateable.toStates( "SUSPENDED,REGISTERED,DELETED" );
      
ToStateable< EventType > eventToStateable = new DeviceHistoryInState( );
      
List< EventType > eventTypes = eventToStateable.toStates( "INACTIVE, NEW, ACTIVE"  );
…

Printing those objects out I could see…

                                  [SUSPENDED, REGISTERED, DELETED]
                                           [INACTIVE, NEW, ACTIVE]
                                                         SUSPENDED
                                             EXPERIMENT SUCCESSFUL

You can remove your two similar implementations of toState() inside DeviceHistoryInState and DeviceInState and define a single generic method that works with any enumeration type:

static <E extends Enum<E>> List<E> toStates(Class<E> cls, String statesString) {
    List<String> states = Arrays.asList(statesString.split(","));
    return states.stream().map(String::trim).map(s -> Enum.valueOf(cls, s))
                          .collect(Collectors.toList());
}

There is however a small cost: you have to pass in the EnumType.class as a parameter, but this is fairly straightforward:

List< DeviceState > devStates = toStates(DeviceState.class, "SUSPENDED,REGISTRATED,DELETED");
=> [SUSPENDED, REGISTRATED, DELETED]
List< EventType > evTypes = toStates(EventType.class, "INACTIVE,NEW,ACTIVE");
=>  [INACTIVE, NEW, ACTIVE]

Alternatively you can make simple definition of EventType.toState(String) which calls the above.

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