2009-04-07 5 views
11

Javaでは、EnumはEnumが行うすばらしいことを行うことができますが、メソッド(動作とロジック)も持つことができます。列挙型を使用してクラスを使用すると、それはどのような利点がありますか?この点を説明するための簡単な例も歓迎されます。Java Enumは動作しますか?

答えて

14

を受け入れるここで簡単な例です:

enum RoundingMode { 
    UP { 
     public double round(double d) { 
      return Math.ceil(d); 
     } 
    }, 
    DOWN { 
     public double round(double d) { 
      return Math.floor(d); 
     } 
    }; 

    public abstract double round(double d); 
} 
+0

どのようにこれをコードで使用しますか?私はこれをやりますか? double foo = RoundingMode.round(20.3); または、列挙型を子列挙型に拡張しますか?私は抽象メソッドによって投げ捨てられます。 – Dave

+0

抽象メソッドは、UPおよびDOWNによって使用されるネストされたクラスによってオーバーライドされます。 double doMath(RoundMode m、double x、double y){double d;}このようなコードで使用します。 ... d = m。around(d); ... return d; }最初のパラメータとしてRoundingMode.UPまたはRoundingMode.DOWNを渡します。 –

+0

ありがとう!私はそれについてどのように感じるのか分かりませんが、私は今それを理解しています;) – Dave

6

質問のタイトルが他の部分と一致するかどうかはわかりません。はい、Javaの列挙型には動作があります。彼らは実際には、本当に不変の状態にする必要がありますが、状態もすることができます。 (変更可能なenum値の考え方はかなり恐ろしいIMOです。)

Javaの列挙型は基本的にオブジェクトの固定セットです。利点は、あなたがそのタイプのリファレンスを持っているならば、常にnullまたはよく知られているセットのいずれかであることを知っていることです。

個人的に私はJavaのenumを本当に好きで、C#にもそれらがあることを願っています。C#のenumよりもはるかにオブジェクト指向です。初期化の順序にはいくつかの "問題点"がありますが、一般的にはfabです。

+0

あなたはC#クラスでのJavaの列挙型をエミュレートすることができませんか? –

+0

@Vilx:もちろん可能です。 Java 5より前では、独自のクラスを作成して型保証された列挙型オブジェクトを作成することができました。 (まあ、もちろん、まだまだポイントはあまりありません。) – Eddie

+0

Vilx:でも、それはちょっと面倒です。基本的には、プライベートコンストラクタで抽象基本型を使用し、プライベートコンストラクタを呼び出すことができる*入れ子型からそれを派生させます。 –

1

私たちのプロジェクトでは、Enumをいくつか使用していますが、おそらくi18n目的で最も顕著です。それぞれのテキストにEnumが与えられています。 Enumクラスには、使用されているLocaleを検査し、実行時に変換のコレクションから正しい変換を選択するString返すメソッドがあります。

これは、IDEからコード補完を取得し、文字列を翻訳することを忘れることはありません。

使用量は、それは例を与えることはほとんどrendundantだポイントに、非常にシンプルですが、ここではあなたが空想になりたい場合は、1つは、翻訳列挙

System.out.println(Translations.GREET_PERSON.trans()+" "+user.getName()); 

を使用するか、またはかもしれない方法ですが、持っています列挙型は、いくつかの魔法の文字列操作で、翻訳文字列にマークされた位置に挿入された引数、

System.out.println(Translations.GREET_PERSON.trans(user.getName()); 
+0

興味深い使い方ですが、クラス内の一連の静的メソッドから同じ動作を得ることができるようです。私はenumを使う利点がないと思います。 – Dave

+0

必要に応じて列挙型を追加する方がずっと簡単です。彼らは自分自身も認識しています - あなたは列挙型の文字列をtrans()内で得ることができます - したがって、あなたはあなたの翻訳テーブル内で一致するキーワードとしてそれを使うことができます –

8

Enumタイプも、真のシングルトンを実装するのに最適な方法です。

Javaのクラシックシングルトンパターンには、通常、プライベートコンストラクタやpublic static factoryメソッドが含まれますが、リフレクションまたは(デ)シリアライゼーションによるインスタンス化に対して脆弱です。列挙型はそれを防ぐ。

+0

あなたは "無料で"ちょっとした奇妙な方法を取っています。 (とにかくシングルトンは悪です。) –

+0

コメントが分かりません。 –

+0

興味深い点。 enumはどのようにリフレクションとデシリアライゼーションを防ぎますか?私は実際に私が反射を介して列挙型をインスタンス化するのを妨げるのかと尋ねていると思いますか?コンパイラはチェック例外をスローしますか? – Dave

2

enumインスタンスはシングルトンなので、switchステートメントで使用するか、==ステートメントで使用して同等性をチェックできます。

2

Javaの列挙型は、クラスです(私はバイトコードレベルで違いはないと考えています)。可能性のあるインスタンスの固定セットが既知で、スイッチステートメントでそれらを使用できるという追加の利点があります。

通常のクラス(数え切れないほどの本や記事に記述されている "typesafe enum"パターン)を使用して、 "可能なインスタンスの既知の固定セット"をエミュレートすることはできますが、シリアライゼーション、equals()、hashCode()、そしておそらく私が忘れてしまったいくつかの事に関しては本当に正しく動作します。言語レベルの列挙型はあなたの仕事を惜しみません。また、前述のように、switch文では言語レベルの列挙型のみを使用できます。

+0

これらはクラスですが、バイトコードレベルで違いがあります。 1つはenumクラスにACC_ENUMフラグが付いていることです。 http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdfを参照してください。 –

0

java/jodaタイムクラスを見てください。ここでenumは大量のジョブを実行します。ここで

はjava.time.Monthの例である:

public enum Month implements TemporalAccessor, TemporalAdjuster { 
    JANUARY, 
    FEBRUARY, 
    MARCH, 
    APRIL, 
    MAY, 
    JUNE, 
    JULY, 
    AUGUST, 
    SEPTEMBER, 
    OCTOBER, 
    NOVEMBER, 
    DECEMBER; 

    private static final Month[] ENUMS = Month.values(); 

    public static Month of(int month) { 
     if (month < 1 || month > 12) { 
      throw new DateTimeException("Invalid value for MonthOfYear: " + month); 
     } 
     return ENUMS[month - 1]; 
    } 

    // About a dozen of other useful methods go here 

} 
関連する問題