Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Можно ли написать “абстрактный” enum?

#java


Есть такой enum:

public enum AlbumPrivacy {

    public_(0),
    friendsOnly(1),
    familyOnly(2),
    friendsAndFamily(3),
    private_(4);

    private final int _value;
    private static AlbumPrivacy[] _values;

    private AlbumPrivacy(int value) {
        _value = value;
    }

    public int getValue() {
        return _value;
    }

    public static AlbumPrivacy fromInt(int i) {
        if (_values == null)
            _values = AlbumPrivacy.values();

        for (AlbumPrivacy b : _values) {
            if (b.getValue() == i) {
                return b;
            }
        }
        return null;
    }
}


Зачем такое нагородил? Удобно, когда пишешь в базу - быстро сохранять в int и назад.

Но очень не удобно для каждого нового enum писать копию кода. А извернуться и убрать
эту дубликацию кода нельзя? 

И второй вопрос - правильно ли я сделал, что храню список values, а не каждый раз
дёргаю при вызове fromInt?

UPD:

Может тогда вот так сделать:

public class EnumUtils {

    private static Map, Object[]> _enums;

    @SuppressWarnings("unchecked")
    public static > T fromInt(Class clazz, int index) {
        if (_enums == null)
            _enums = U2.map();

        Object[] values = _enums.get(clazz);

        if (values == null)
        {
            Enum[] _values = clazz.getEnumConstants();
            values = new Object[_values.length];

            for (int i = 0; i < _values.length; i++)
                values[i] = _values[i];

            _enums.put(clazz, values);
        }

        return (T) values[index];
    }
}


А enum объявлять по простому, без всяких номеров.

UPD2:

public static > T fromInt(Class clazz, int index) {
        return clazz.getEnumConstants()[index];
    }

    


Ответы

Ответ 1



У каждого enum и так есть порядковое значение поля — метод ordinal(). Если у вас все value идут по порядку, посто делайте public enum AlbumPrivacy { public_, // 0 friendsOnly, // 1 familyOnly, // 2 friendsAndFamily, // 3 private_; // 4 } Для определения номера по enum: int n = AlbumPrivacy.friendsOnly.ordinal(); Для определения enum по номеру: AlbumPrivacy value = AlbumPrivacy.values()[3]; Если вас это не устраивает (скажем, номера могут идти с дырками), можно во-первых, реализовать интерфейс, а во-вторых сделать метод fromInt универсальным. interface Ordinal { int getValue(); } public enum AlbumPrivacy implements Ordinal { public_(0), friendsOnly(1), familyOnly(2), friendsAndFamily(3), private_(4); private final int _value; private AlbumPrivacy(int value) { _value = value; } @Override public int getValue() { return _value; } } // Где-нибудь в утилитном классе: public static & Ordinal> T fromInt(Class clazz, int i) { T[] values = clazz.getEnumConstants(); for(T value : values) { if(value.getValue() == i) return value; } throw new IllegalArgumentException(); }

Ответ 2



Отвечаю на вторую часть вопроса. Нет, вы неправильно делаете, что запоминаете values. Метод getEnumConstants уже запоминает результат, нет никакой необходимости запоминать его еще раз.

Комментариев нет:

Отправить комментарий