Если вы всегда используете перечисления вместо констант в Java

В java < 1.5 константы будут реализованы следующим образом:

public class MyClass {
    public static int VERTICAL = 0;
    public static int HORIZONTAL = 1;

    private int orientation;

    public MyClass(int orientation) {
        this.orientation = orientation;
    }
...

и вы будете использовать его следующим образом:

MyClass myClass = new MyClass(MyClass.VERTICAL);

Теперь, в 1.5, очевидно, вы должны использовать перечисления:

public class MyClass {
    public static enum Orientation {
        VERTICAL, HORIZONTAL;
    }

    private Orientation orientation;

    public MyClass(Orientation orientation) {
        this.orientation = orientation;
    }
...

и теперь вы будете использовать его следующим образом:

MyClass myClass = new MyClass(MyClass.Orientation.VERTICAL);

Что я считаю немного уродливым. Теперь я мог бы легко добавить пару статических переменных:

public class MyClass {
    public static Orientation VERTICAL = Orientation.VERTICAL;
    public static Orientation HORIZONTAL = Orientation.HORIZONTAL;

    public static enum Orientation {
        VERTICAL, HORIZONTAL;
    }

    private Orientation orientation;

    public MyClass(Orientation orientation) {
        this.orientation = orientation;
    }
...

И теперь я могу сделать это снова:

MyClass myClass = new MyClass(MyClass.VERTICAL);

Со всем безопасным типом перечислений.

Это хороший стиль, плохой стиль или нет. Можете ли вы придумать лучшее решение?

Обновление

Вилкс был первым, кто подчеркнул, что я чувствую, что мне не хватает - что перечисление должно быть первоклассным гражданином. В java это означает, что он получает свой собственный файл в пакете - у нас нет пространств имен. Я думал, что это будет немного тяжеловесом, но, на самом деле, это действительно правильно.

Ответ Yuval в порядке, но на самом деле это не особо подчеркивало не вложенное перечисление. Кроме того, что касается 1.4 - в JDK есть много мест, которые используют целые числа, и я действительно искал способ разработки такого кода.

Ответ 1

Не знаю о Java, но в .NET хорошая практика заключается в том, чтобы переводить перечисления параллельно классу, который их использует, даже если он используется одним классом. То есть, вы должны написать:

namespace Whatever
{
    enum MyEnum
    {
    }
    class MyClass
    {
    }
}

Таким образом, вы можете использовать:

MyClass c = new MyClass(MyEnum.MyValue);

Ответ 2

Вы слишком много усложнили. Пусть все вместе.

Опубликовать Java 1.5 вы должны использовать класс Java Enum:

public enum Color
{
    BLACK, WHITE;
}

Предварительно Java 1.5 вы должны использовать шаблон Enum, безопасный для типов:

public class Color
{
    public static Color WHITE = new Color("white");
    public static Color BLACK = new Color("black");

    private String color;

    private Color(String s)
    {
        color = s;
    }
}

В обоих случаях вы вызываете его так:

drawBackground(Color.WHITE);

В частности, в отношении вашего вопроса. Это вопрос стиля кода, но я думаю, что предпочтительным способом является сохранение перечислений в их отдельных классах. Особенно, когда они начинают использовать свои собственные методы, такие как getName(), getId() и т.д. Думайте об этом как о той же дилемме, что и обычный класс против анонимного класса, как только класс начинает забиваться, пришло время переместить его в свой собственный файл.

Ответ 3

Знаете ли вы, что можете импортировать Ориентацию и сказать

MyClass myClass = new MyClass(Orientation.VERTICAL);

?

Ответ 4

Это зависит от того, сколько значений может принять перечисление. В вашем примере, только с двумя, я бы просто использовал логическое значение. Если перечисление будет использоваться только кодом, который вы пишете, и вам не придется взаимодействовать с большим количеством другого кода, возможно, вам не нужна безопасность типов. Но если он в "общедоступном" методе, я бы определенно пошел на перечисления и поместил перечисление в свой собственный файл.

Ответ 5

В MyClass также есть два статических метода:

MyClass.Vertical() : MyClass
MyClass.Horizontal() : MyClass

Те возвращают новый экземпляр с соответствующим набором перечислений.

Ответ 6

Я согласен, что вы были творческими, но я думаю, что это не практическое решение, и я думаю, что вы просто переместили "уродство" на другую часть кода. Что произойдет, если в дополнение к VERTICAL и HORIZONTAL вы также получите DIAGONAL, AA, BB, CC и т.д.? Вам придется дублировать, набирая каждую статическую константу? Ваш вкус, который MyClass.Orientation.VERTICAL уродлив, может быть личным?

Ответ 7

Существует важный класс случаев, когда вы должны использовать константы вместо enum s. Это когда вы хотите выполнить арифметику с использованием констант или сравнить их с числовыми значениями. Тогда вам действительно нужна вещь int, long или double.

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