Can I extend enumeration in Java 8?
Just played and proposed a sweet way to add features to @ L_ 502_ Enumeration of 0 @ and this
Some further fixes made it almost possible for me to add a neat (i.e. no exceptions thrown) reverse lookup, but there was a problem presentation:
error: valueOf(String) in X cannot implement valueOf(String) in HasValue public enum X implements PoliteEnum,ReverseLookup { overriding method is static
Is there a way
The goal here is to implement a lookup method of valueof function without throwing an exception through an interface added by default (for example, I added politename in the answer to the link) Is it possible? Obviously, enumeration can now be extended as a major problem in Java until now
This is my failed attempt:
public interface HasName { public String name(); } public interface PoliteEnum extends HasName { default String politeName() { return name().replace("_"," "); } } public interface Lookup<P,Q> { public Q lookup(P p); } public interface HasValue { HasValue valueOf(String name); } public interface ReverseLookup extends HasValue,Lookup<String,HasValue> { @Override default HasValue lookup(String from) { try { return valueOf(from); } catch (IllegalArgumentException e) { return null; } } } public enum X implements PoliteEnum/* NOT ALLOWED :(,ReverseLookuP*/ { A_For_Ism,B_For_Mutton,C_Forth_Highlanders; } public void test() { // Test the politeName for (X x : X.values()) { System.out.println(x.politeName()); } // ToDo: Test lookup }
Solution
Your design is too complicated If you are willing to accept that the default method can only be called on an instance, the entire code may be as follows:
interface ReverseLookupSupport<E extends Enum<E>> { Class<E> getDeclaringClass(); default E lookup(String name) { try { return Enum.valueOf(getDeclaringClass(),name); } catch(IllegalArgumentException ex) { return null; } } } enum Test implements ReverseLookupSupport<Test> { FOO,BAR }
You can test by:
Test foo=Test.FOO; Test bar=foo.lookup("BAR"),baz=foo.lookup("BAZ"); System.out.println(bar+" "+baz);
An alternative to non throwing / catching is:
interface ReverseLookupSupport<E extends Enum<E>> { Class<E> getDeclaringClass(); default Optional<E> lookup(String name) { return Stream.of(getDeclaringClass().getEnumConstants()) .filter(e->e.name().equals(name)).findFirst(); }
Use image:
Test foo=Test.FOO; Test bar=foo.lookup("BAR").orElse(null),baz=foo.lookup("BAZ").orElse(null); System.out.println(bar+" "+baz);