JavaのEnum型はフィールドを定義することができて、コード値に変換したりするのに便利ですが、コード値からEnum型への変換は標準では用意されていないため、各Enum型に取得用のstaticメソッドが乱立しがちです。
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum Pokemon {
PIKACHU("025", "ピカチュウ"),
RAICHU("026", "ライチュウ"),
PICHU("172", "ピチュー"),
;
private final String no;
private final String jName;
public static Pokemon getByNo(String no) {
Optional<Pokemon> result = Stream.of(values())
.filter(p -> p.no.equals(no))
.findFirst();
return result.orElse(null);
}
}
Apache Commons辺りに良い感じのメソッドが無いかと調べたところ、EnumUtils#getEnum()
というそれっぽいメソッドが、見つかりました。
// 使い方
Pokemon p = EnumUtils.getEnum(Pokemon.class, "PIKACHU");
・・・違う、そうじゃない。。。
という訳で、コード値からEnum型へ変換するユーティリティクラスを自作しました。
可変長引数をごにょごにょしてdummy
からClass<E>
を取得しているのがポイントです。
(あと、警告がたくさん出ます。。。)
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
public class MyEnumUtils {
public static <E extends Enum<E>, T> E getEnum(T value, Function<E, T> getter, E... dummy) {
Class<E> clazz = (Class<E>) dummy.getClass().getComponentType();
Optional<E> result = Stream.of(clazz.getEnumConstants())
.filter(e -> Objects.equals(getter.apply(e), value))
.findFirst();
return result.orElse(null);
}
}
以下のように使用します。
第3引数のdummy
は名前の通りダミーなので何も渡しません。
// 使い方
Pokemon pika = MyEnumUtils.getEnum("025", Pokemon::getNo);
Pokemon pich = MyEnumUtils.getEnum("ピチュー", Pokemon::getJName);
なお、このコードはJava8以降でしか動作しません。
第3引数のdummy
が、格好悪いなぁと思って、
privateメソッドに隠してしまいたかったですが、がうまく動きませんでした。
public class MyEnumUtils {
// このメソッドは正常に機能しません。
public static <E extends Enum<E>, T> E getEnum(T value, Function<E, T> getter) {
return getEnumInternal(value, getter);
}
private static <E extends Enum<E>, T> E getEnumInternal(T value, Function<E, T> getter, E... dummy) {
Class<E> clazz = (Class<E>) dummy.getClass().getComponentType();
Optional<E> result = Stream.of(clazz.getEnumConstants())
.filter(e -> Objects.equals(getter.apply(e), value))
.findFirst();
return result.orElse(null);
}
}
なんでやろなぁ。。。
参考にしたサイト