Devo estar tentando criar um enum reversível em Java ou há uma maneira melhor?

Eu pareço ter enfrentado esse problema muitas vezes e queria perguntar à comunidade se estou apenas latindo na árvore errada. Basicamente, minha pergunta pode ser resumida a isto: se eu tenho um enum (em Java) para o qual os valores são importantes, devo estar usando um enum ou existe uma maneira melhor, e se eu usar um enum, então o que é a melhor maneira de reverter a pesquisa?

Aqui está um exemplo. Suponha que eu queira criar um bean representando um mês e ano específicos. Eu poderia criar algo como o seguinte:

public interface MonthAndYear {
    Month getMonth();
    void setMonth(Month month);
    int getYear();
    void setYear(int year);
}

Aqui estou armazenando meu mês como uma classe separada chamada Mês, para que seja seguro para o tipo. Se eu apenas colocar int, então qualquer um poderia passar em 13 ou 5.643 ou -100 como um número, e não haveria maneira de verificar isso em tempo de compilação. Estou restringindo-os a colocar um mês que eu implementarei como um enum:

public enum Month {
    JANUARY,
    FEBRUARY,
    MARCH,
    APRIL,
    MAY,
    JUNE,
    JULY,
    AUGUST,
    SEPTEMBER,
    OCTOBER,
    NOVEMBER,
    DECEMBER;
}

Agora suponha que eu tenha algum banco de dados de backend para o qual eu queira escrever, que aceita apenas o formato inteiro. Bem, a maneira padrão de fazer isso parece ser:

public enum Month {
    JANUARY(1),
    FEBRUARY(2),
    MARCH(3),
    APRIL(4),
    MAY(5),
    JUNE(6),
    JULY(7),
    AUGUST(8),
    SEPTEMBER(9),
    OCTOBER(10),
    NOVEMBER(11),
    DECEMBER(12);

    private int monthNum;
    public Month(int monthNum) {
        this.monthNum = monthNum;
    }

    public getMonthNum() {
        return monthNum;
    }
}

Bastante direto, mas o que acontece se eu quiser ler esses valores do banco de dados e também escrevê-los? Eu poderia apenas implementar uma função estática usando uma instrução case dentro do enum que pega um int e retorna o respectivo objeto Month. Mas isso significa que se eu mudei alguma coisa, então eu teria que mudar essa função, assim como os argumentos do construtor - mude em dois lugares. Então aqui está o que eu tenho feito. Primeiro, criei uma classe de mapa reversível da seguinte forma:

public class ReversibleHashMap<K,V> extends java.util.HashMap<K,V> {
    private java.util.HashMap<V,K> reverseMap;

    public ReversibleHashMap() {
        super();
        reverseMap = new java.util.HashMap<V,K>();
    }

    @Override
    public V put(K k, V v) {
        reverseMap.put(v, k);
        return super.put(k,v);
    }

    public K reverseGet(V v) {
        return reverseMap.get(v);
    }
}

Então eu implementei isso dentro do meu enum em vez do método construtor:

public enum Month {
    JANUARY,
    FEBRUARY,
    MARCH,
    APRIL,
    MAY,
    JUNE,
    JULY,
    AUGUST,
    SEPTEMBER,
    OCTOBER,
    NOVEMBER,
    DECEMBER;

    private static ReversibleHashMap<java.lang.Integer,Month> monthNumMap;

    static {
        monthNumMap = new ReversibleHashMap<java.lang.Integer,Month>();
        monthNumMap.put(new java.lang.Integer(1),JANUARY);
        monthNumMap.put(new java.lang.Integer(2),FEBRUARY);
        monthNumMap.put(new java.lang.Integer(3),MARCH);
        monthNumMap.put(new java.lang.Integer(4),APRIL);
        monthNumMap.put(new java.lang.Integer(5),MAY);
        monthNumMap.put(new java.lang.Integer(6),JUNE);
        monthNumMap.put(new java.lang.Integer(7),JULY);
        monthNumMap.put(new java.lang.Integer(8),AUGUST);
        monthNumMap.put(new java.lang.Integer(9),SEPTEMBER);
        monthNumMap.put(new java.lang.Integer(10),OCTOBER);
        monthNumMap.put(new java.lang.Integer(11),NOVEMBER);
        monthNumMap.put(new java.lang.Integer(12),DECEMBER);
    }

    public int getMonthNum() {
        return monthNumMap.reverseGet(this);
    }

    public static Month fromInt(int monthNum) {
        return monthNumMap.get(new java.lang.Integer(monthNum));
    }
}

Agora isso faz tudo o que eu quero, mas ainda parece errado. As pessoas sugeriram para mim "se a enumeração tiver um valor interno significativo, você deveria estar usando constantes". No entanto, não sei como essa abordagem me daria o tipo de segurança que estou procurando. O caminho que desenvolvi parece muito complicado. Existe alguma maneira padrão de fazer esse tipo de coisa?

PS: Eu sei que a probabilidade do governo adicionar um novo mês é ... bastante improvável, mas pense no quadro maior - há muitos usos para enums.

questionAnswers(4)

yourAnswerToTheQuestion