Java の enum 使用でよく列挙名と共にコード値を定義して使用したりする設計は
常套手段の1つである。
public enum Frame { Gold(101), Silver(101), Bronz(102); private int value; private Frame(int value) { this.value = value; } public int getValue(){ return value; } }
よくあるパターンである。
列挙型の並び、( 0始まり、つまり序数=0)は、ordinal() で取得するが、上のように
抱えるコード値取得メソッドは各 enum定義によるもので普遍的ではない。
汎用的な enumタイプハンドラを作ろうと思ってもこのままではできない。
そこで、コード値の取得メソッドを縛ったインターフェースを用意をする。
また、使いそうなメソッドも用意する。
enum で抱えるコード値のが、int でも String でも許容させるので、
Object getValue(); で取得するものとしている。
循環参照する総称型である。
import java.util.Arrays; import java.util.Optional; /** * Generic enum Interface */ public interface EnumBase<E extends Enum<E>>{ public Object getValue(); static <E> E[] getArray(Class<E> clz) { return clz.getEnumConstants(); } @SuppressWarnings("unchecked") static <E extends Enum<E>> E valueOf(Class<? extends Enum<E>> cls, String value) { return (E)Arrays.stream(cls.getEnumConstants()) .filter(e->e.name().equals(value)) .findAny() .orElse(null); } @SuppressWarnings("unchecked") static <E extends Enum<E>> Optional<E> parseOf(Class<? extends Enum<E>> cls, String value) { return (Optional<E>) Arrays.stream(cls.getEnumConstants()) .filter(e->e.name().equals(value)) .findAny(); } @SuppressWarnings("unchecked") static <E extends Enum<E>> Optional<E> parseCode(Class<? extends EnumBase<E>> cls, Object code) { return (Optional<E>) Arrays.stream(cls.getEnumConstants()) .filter(e->e.getValue().equals(code)) .findAny(); } @SuppressWarnings("unchecked") static <E extends Enum<E>> E codeOf(Class<? extends EnumBase<E>> cls, Object code) { return (E) Arrays.stream(cls.getEnumConstants()) .filter(e->e.getValue().equals(code)) .findAny().orElse(null); } }
使用例
public enum Frame implements EnumBase<Frame>{ Gold(100), Silver(101), Bronz(102); private int value; private Frame(int value) { this.value = value; } @Override public Object getValue(){ return value; } }
System.out.println("Frame.Gold getCode() : " + Frame.Gold.getValue() ); // enum values() と同じ結果を求める Frame[] frames = EnumBase.getArray(Frame.class); System.out.println("--- Arrays.stream(frames).forEach(System.out::println); ---"); Arrays.stream(frames).forEach(System.out::println); System.out.println("---------"); Frame g = Frame.valueOf("Gold"); System.out.println( g +" "+g.getValue() ); System.out.println("--- Frame v = EnumBase.valueOf(Frame.class, \"Silver\"); ---"); Frame v = EnumBase.valueOf(Frame.class, "Silver"); Frame v2 = EnumBase.parseOf(Frame.class, "Silver").orElse(null); System.out.println("EnumBase<Frame> v : "+v.name() ); System.out.println("v.equlas(v2) : "+v.equals(v2) ); Optional<Frame> v102 = EnumBase.parseCode(Frame.class, 102); System.out.println("EnumBase<Frame> v102 : "+v102.map(o ->o.name()).orElse(null) ); Frame b = EnumBase.codeOf(Frame.class, 101); System.out.println(b.name());
実行して標準出力されるもの。。。
Frame.Gold getCode() : 100 --- Arrays.stream(frames).forEach(System.out::println); --- Gold Silver Bronz --------- Gold 100 --- Frame v = EnumBase.valueOf(Frame.class, "Silver"); --- EnumBase<Frame> v : Silver v.equlas(v2) : true EnumBase<Frame> v102 : Bronz Silver
この EnumBase を使って enum用タイプハンドラは、
https://oboe2uran.hatenablog.com/entry/2021/03/14/003000