Перечисления Java - Операторы переключения по сравнению с Шаблоном "посетитель" на Перечислениях - Выигрыши в производительности?

Я искал вокруг в течение многих дней для нахождения ответа на эту основанную на производительности проблему.
После рытья Интернета до сих пор я узнал, что существует несколько способов использовать Перечисления в Java, хорошо зарегистрированном в здесь. Ну, определенно как начинающий можно было бы хотеть Перечисления использования в операторе case оператора switch, который обеспечивает ясность и лучшее понимание кода. Но с другой стороны у нас есть реализация стиля Шаблона "посетитель" Перечислений также, которая гарантирует безопасность типов и расширяемость, Обсужденную здесь.

Однако и возвращаясь к исходной идее позади этого вопроса, до сих пор я узнал, что, если конструкция случая переключателя правильно разработана с помощью Перечислений, который гарантирует, что значения случая не редки, и что Перечислимое объявление находится в той же единице компиляции как оператор case оператора switch, компилятор Java выполняет некоторую оптимизацию на произведенном байт-коде путем реализации такой конструкции как Таблица переходов (обсужденный в здесь и в другом месте также на веб-сайте Sun, которому я потерял ссылку). Теперь, это определенно окрыляет производительность по сравнению с несколькими/вкладывать если еще конструкция.

Мой вопрос, как Java реализует основанную на шаблоне "посетитель" реализацию Перечислений в получающемся байт-коде и каково повышение производительности в то время как по сравнению с основанной на случае переключателя реализацией, если таковые имеются?

И какой тип реализации должен, я предпочитаю, полагая, что мои Перечисления могут вырасти в будущем, и я увлечен производительностью также. В настоящее время у меня есть приблизительно 19 и нечетные константы в моем Перечислении.


Править
У меня есть класс, который хранит некоторую информацию о переменных игры. Одна из переменных, являющихся Перечислимым типом.

public class GameObject {
    private Shape mShape;

    public Shape getShape() {
        return mShape;
    }
    .
    .
    .

    public static enum Shape {
        SHAPE1, SHAPE2, SHAPE3, SHAPE4, ..., SHAPE20
    };

    public void drawShape() {
        switch (this.mShape) {
        case SHAPE1:
            drawShape1();
            break;
        case SHAPE2:
            drawShape2();
            break;
        case SHAPE3:
            drawShape3();
            break;
        case SHAPE4:
            drawShape4();
            break;
        .
        .
        .
        .
        .
        case SHAPE20:
            drawShape20();
            break;
        default:
            drawUnknown();
            break;
        }
    }

}

Позже я понял разделения информации от логики, и следовательно создал другой класс и переместил Перечислимую Форму от GameObject до этого нового класса GraphicModel, и вместо того, чтобы иметь случай переключателя там, я реализовал постоянно-определенные методы. И да я действительно помещал надлежащих операторов импорта в любой класс после этой модификации.

public class GraphicModel {
    public void drawGraphicFromObject(GameObject gameObject) {
        gameObject.getShape().draw();
    }

    public static enum Shape {
        // This method is not public, instead is only called by GraphicModel
        abstract void draw();

        SHAPE1 {
            @Override
            void draw() {
                // some transformations
            }
        },
        SHAPE2 {
            @Override
            void draw() {
                // Some different transformation
            }
        },
        SHAPE3 {
            @Override
            void draw() {
                // Yet another transform
            }
        },
        .
        .
        .
        .
        UNKNOWN {
            @Override
            void draw() {
                // 
            }
        };
    }
}

Позже я даже реализовал это на основе шаблона "посетитель", как предложено здесь

Так, что я должен знать, это, какой способ реализации более эффективен? Определенно, чтобы случай переключателя был преобразован в таблицы переходов на компиляции, Java требует и перечислимого объявления и операторов переключения в той же единице компиляции. Я должен использовать основанную на переключателе реализацию или постоянно-определенную реализацию метода в моем классе GraphicModel? Скорее чтобы быть ясным, какова разница в производительности?

7
задан Community 23 May 2017 в 12:32
поделиться

1 ответ

Enums, вообще говоря, сопоставимы по производительности с int константами, если они используются в выражении switch (1).

Может быть, Вам лучше рассмотреть что-нибудь по аналогии с реализацией констант конкретного метода , например,

public enum Mode {

  ON { Color color() {return Color.GREEN;}},
  OFF { Color color() {return Color.RED;}},
  STANDBY { Color color() {return Color.YELLOW;}},
  DEFAULT { Color color() {return Color.BLACK;}};

  abstract Color color();

}//enum Mode

, а затем использовать

getMode().color();

вместо оператора switch?!

Однако, я думаю, что для "получить только цветной случай", возможно, методы вообще не нужны.

В общем, я настоятельно рекомендую вам Эффективную Java для вашей книжной полки. В главе 6 будет обсуждаться Enums and Annotations.

4
ответ дан 7 December 2019 в 14:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: