Записи автоинкремента перечисления Java? - PullRequest
7 голосов
/ 13 января 2010

Позволяет ли Java что-то вроде хорошего старого C или даже C # в том смысле, что вы можете определить перечисление с полями, значения которых растут автоматически и начинаются с необязательного заданного значения?

* 1003 Е.Г. *

В C или C #:

enum Foo { A = 10, B, C, D = 5000, E, Fish };

Выход A = 10, B = 11, C = 12, D = 5000, E = 5001, Рыба = 5002.

Ответы [ 2 ]

10 голосов
/ 13 января 2010

Это выбор дизайна Java Enums, который не поддерживает изменение порядковых значений. По сути, они не стабильны достаточно, чтобы зависеть от них. Если вы измените положение B и C в вашем примере, клиенты в зависимости от порядковых значений будут нарушены. Это может произойти непреднамеренно.

Проблема описана в Effective Java Элемент 31: Использовать поле экземпляра вместо ординалов .

Вы можете стабильно эмулировать поведение:

enum X{
    A(10), B(A), C(B), D(5000), E(D), F(E);

    private final int value;

    X(int value){
        this.value = value;
    }

    X(X preceding){
        this.value = preceding.getValue() + 1;
    }

    public int getValue() {
        return value;
    }

    @Override
    public String toString() {
        return this.name() + "(" + this.value + ")";
    }

    static {
        Set<Integer> values = new HashSet<Integer>();
        for(X x : X.values()) values.add(x.value);
        assert(values.size() == X.values().length); //no duplicates
    }
}

С этим определением вы можете изменять порядок значений, не нарушая клиентов.

Вызов for(X x : X.values()) System.out.println(x); возвращает:

A(10)
B(11)
C(12)
D(5000)
E(5001)
F(5002)
10 голосов
/ 13 января 2010

В Java вы не можете явно указать порядковые значения вообще . Они всегда автоинкрементны, с 0, без контроля над ним.

Если вам нужны другие пользовательские значения, вам нужно поместить их в вызовы конструктора и сохранить их самостоятельно. Вы можете получить автоинкремент, но чертовски неприятно:

import java.util.EnumSet;

// Please don't ever use this code. It's here so you can point and laugh.
enum Foo 
{ 
    A(10), B, C, D(5000), E, Fish;

    private static int nextValue;
    private int value;

    private Foo()
    {
        this(Counter.nextValue);
    }

    private Foo(int value)
    {
        this.value = value;
        Counter.nextValue = value + 1;
    }

    public int getValue() 
    {
        return value;
    }

    private static class Counter
    {
        private static int nextValue = 0;
    }
}

public class Test
{
    public static void main(String[] args)
    {
        for (Foo foo : EnumSet.allOf(Foo.class))
        {
            System.out.println(foo.name() + " " + 
                               foo.ordinal() + " " + 
                               foo.getValue());
        }
    }
}

Обратите внимание на необходимость использования вложенного класса, потому что вы не можете получить доступ к статическим полям в конструкторе enum. Ик, Ик, Ик. Пожалуйста, не делайте этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...