8

このパフォーマンスベースの問題に対する答えを見つけるために、私は何日も探し回っています。
これまでインターネットを掘り下げた後、Javaで列挙型を使用する方法がいくつかあることを知りまし。確かに、スターターとして、switch-caseステートメントで列挙型を使用したいと思うでしょう。これにより、コードが明確になり、理解が深まります。しかし一方で、Enum のVisitor パターンスタイルの実装もあり、これにより型の安全性と拡張性が保証されます

そうは言っても、この質問の背後にある元のアイデアに戻ると、これまでのところ、switch-case コンストラクトが Enum を使用して適切に設計されている場合、ケースの値がスパースではなく、Enum 宣言が同じであることを学びました。コンパイル ユニットを switch-case ステートメントとして使用する場合、Java コンパイラは、ジャンプ テーブルなどの構造を実装することにより、生成されたバイトコードに対して何らかの最適化を実行します(リンクを失った Sun の Web サイトで、ここや他の場所で説明されています)。現在、これにより、複数/ネストされた if-else 構造と比較して、パフォーマンスが確実に向上します。

私の質問は、Java が結果のバイトコードで Enums のビジター パターン ベースの実装をどのように実装するか、およびスイッチケースベースの実装と比較してパフォーマンスがどの程度向上するかということです。

また、列挙型が将来的に成長する可能性があり、パフォーマンスにも熱心であることを考慮して、どのタイプの実装を優先する必要がありますか。現在、Enum には 19 と奇数の定数があります。


編集
ゲームの変数に関する情報を格納するクラスがあります。Enum型 の変数の 1 つ。

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;
        }
    }

}

後で、ロジックから情報を分離することに気付き、別のクラスを作成し、Enum ShapeGameObjectからこの新しいクラスGraphicModelに移動し、そこにswitch-caseを配置する代わりに、定数固有のメソッドを実装しました。はい、この変更の後、どちらのクラスにも適切なインポートステートメントを入れました。

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() {
                // 
            }
        };
    }
}

後で、ここで提案されているように、訪問者パターンに基づいてこれを実装しました

それで、私が知る必要があるのは、どの実装方法がより効率的かということです? 確かに、コンパイル時にswitch-caseをジャンプ テーブルに変換するには、Javaで同じコンパイル ユニット内にenum宣言とswitchステートメントの両方が必要です。GraphicModelクラスでスイッチベースの実装または定数固有のメソッド実装を使用する必要がありますか? むしろ、明確にするために、パフォーマンスの違いは何ですか?

4

1 に答える 1

6

列挙型は、 switchステートメント ( 1 ) で使用された場合、一般的に言えば、int定数に匹敵するパフォーマンスを発揮します。

たぶん、定数固有のメソッドの実装に沿って何かを検討する必要がありますか? 例えば

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ステートメントの代わりに?!

ただし、「色だけを取得する」場合は、メソッドはまったく必要ないのではないかと思います。

一般的に、本棚にはEffective Javaを強くお勧めします。第 6 章は、Enums と Annotationsについて説明するものです。

于 2010-01-29T19:03:58.010 に答える