Javaの列挙型
列挙型は何ですか
JDK5は、新しい機能を導入し、新しいタイプとして指定される値のキーワード列挙有限集合を作成することができ、これらの値は、列挙型である、定期的な部品の用途として指名することができます。
一个枚举的简单例子
enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER;
}
列挙クラスの一般的な方法
Enum 常用方法有以下几种:
- 名前():インスタンス宣言列挙型の名前を返します。
- ORDINAL(); intを返し、列挙を順にインスタンスを示し
- 等号();戻り値ブール値、等しい列挙インスタンス解析
- compareTo();列挙を順次特定のオブジェクトインスタンスを比較
- 値();戻り値列挙インスタンス・アレイ
- valuesOf(文字列名)は、クラスで定義されている列挙定数の名前を取得します。
结合例子实现
package com.legend.enumdemo;
/**
* 枚举测试类
*/
enum Shrubbery {
GROUND, CRAWLING, HANGING
}
/**
* @author legend
*/
public class EnumClassTest {
public static void main(String[] args) {
//values 返回enum实例的数组
for (Shrubbery temp : Shrubbery.values()) {
// name 返回实例enum声明的名字
System.out.println(temp.name() + " ordinal is " + temp.ordinal() + " ,equal result is " +
Shrubbery.CRAWLING.equals(temp) + ",compare result is " + Shrubbery.CRAWLING.compareTo(temp));
}
//由名称获取枚举类中定义的常量值
System.out.println(Shrubbery.valueOf("CRAWLING"));
}
}
列挙型クラスの本当の色
どのようなそれの最後に列挙型?
- 簡単な列挙を作成します。
public enum Shrubbery {
GROUND,CRAWLING, HANGING
}
- 上記列挙クラス、利用可能Shrubbery.classファイルをコンパイルするために使用するのjavac。
javac Shrubbery.java
- 続いてjavapコマンド、逆コンパイルバイトコードファイルを取得します。以下のような:以下はShrubbery.classてjavapバイトコードファイルを実行することができます。
Compiled from "Shrubbery.java"
public final class enumtest.Shrubbery extends java.lang.Enum<enumtest.Shrubbery> {
public static final enumtest.Shrubbery GROUND;
public static final enumtest.Shrubbery CRAWLING;
public static final enumtest.Shrubbery HANGING;
public static enumtest.Shrubbery[] values();
public static enumtest.Shrubbery valueOf(java.lang.String);
static {};
}
バイトコードファイルから見つけることができます:
- Shrubbery 枚举变成了一个final修饰的类,也就是说,他不能被继承
- Shrubbery是java.lang.Enum的子类
- Shrubbery定义的枚举值都是 public static final 修饰的,即都是静态变量
アドバンテージ列挙クラス
何が、それは、コードの可読性、保守性を向上させているので、我々は同時に、それはまた、セキュリティを持っている、?列挙クラスを使用することを選択した理由は?利点を列挙クラスです。
列挙型クラスは、可読性、保守性を向上させることができます
そのようなビジネスシナリオがあることを今仮定します。注文が完了すると、買い手のコメントを通知します。次のコードを持つことは簡単です:
//订单已完成
if(3==orderStatus){
//do something
}
あなたは状態3は順序が、読んで維持し、非常に退屈していないだけでは難しいことを示していることを知っている書き込みのノートを、しなかった場合は明らかに、このコードでは、マジックナンバーが登場しましたか?あなたが列挙クラスを使用する場合は、次のように:
public enum OrderStatusEnum {
UNPAID(0, "未付款"),
PAID(1, "已付款"),
SEND(2, "已发货"),
FINISH(3, "已完成"),
;
private int index;
private String desc;
public int getIndex() {
return index;
}
public String getDesc() {
return desc;
}
OrderStatusEnum(int index, String desc) {
this.index = index;
this.desc = desc;
}
}
//订单已完成
if(OrderStatusEnum.FINISH.getIndex()==orderStatus){
//do something
}
目に見える、列挙クラスのpublic static final intこの、それは一部の人々が考える、それを1つのより直接的列挙状態を追加し、プラス新しい注文状況の背後にある、維持することをお勧めします、このコードを読みやすくまた、この関数はああを達成することができます静的定数
public class OrderStatus {
//未付款
public static final int UNPAID = 0;
public static final int PAID = 1;
public static final int SENDED = 2;
public static final int FINISH = 3;
}
//订单已完成
if(OrderStatus.FINISH==orderStatus){
//do something
}
このように、静的定数を達成するために、読みやすさは問題ありませんもちろん、
しかし、同じ変数が混乱し、int型の値を定義し、あなたが支払ったとsendedでは状態が2で定義するように、コンパイラは与えられていません。
したがって、列挙クラス第1の利点は、可読性、保守性は、それが推奨され、良いされています。
列挙型クラスのセキュリティ
別に可読性、保守性、および列挙クラスからの大きな利点は、セキュリティがされています。
列挙クラスのバイトコードの分析から、我々は知っています:
- 列挙クラスはfinalキーワードは、それが継承することができない、変更されました
- そしてそののpublic static final変数が変更され、静的定数であります
初めてのJavaクラスは、本当に静的リソースが初期化されるときに使用され、初期化プロセスの負荷のJavaクラスはスレッドセーフですされている場合。
一般的な使用の列挙
enum定数団体
JDK5前に、定数はこのように定義され、クラスまたはインタフェースを定義し、属性タイプがのpublic static finalあり、次のように...、そして列挙して、定数は、列挙されたクラスに編成することができます。
enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER,;
}
連動列挙型スイッチ
一般に、スイッチケースのみの値の整数を使用するが、整数値の自然順序の列挙インスタンスを有し、従って、switch文に次のように列挙型を使用することができるであることができます。
enum OrderStatusEnum {
UNPAID, PAID, SEND, FINISH
}
package com.legend.enumdemo.advantage;
/**
* enum-switch 相结合使用测试
*
* @author legend
*/
public class OrderStatusTest {
public static void main(String[] args) {
//改变订单状态
changeByOrderStatus(OrderStatusEnum.FINISH);
}
/**
* 改变订单状态
*
* @param orderStatusEnum
*/
private static void changeByOrderStatus(OrderStatusEnum orderStatusEnum) {
switch (orderStatusEnum) {
case UNPAID:
System.out.println("你下单了,赶紧付钱吧");
break;
case PAID:
System.out.println("我已经付钱啦");
break;
case SEND:
System.out.println("已发货");
break;
case FINISH:
System.out.println("订单完成啦");
break;
}
}
}
日々の開発では、列挙型は、スイッチと組み合わせて使用、あなたのコードを読みやすく
このようgetメソッド、通常の方法として列挙クラスに新しいアプローチを追加し、それが最も一般的に使用される列挙文言の日々の仕事は次のとおりです。
public static OrderStatusEnum of(int index) {
for (OrderStatusEnum temp : values()) {
if (temp.getIndex() == index) {
return temp;
}
}
return null;
}
列挙は、インターフェイスを実装します
列挙がjava.lang.Enumと他のクラスから継承することはできませんので、列挙クラスのすべてが継承します。しかし、次のように列挙インタフェースは、達成することができます。
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
列挙クラスの比較がある==または等しいですか?
package com.legend.enumdemo.equals;
/**
* 枚举类比较
*
* @author legend
*/
public class EnumTest {
public static void main(String[] args) {
Shrubbery s1 = Shrubbery.CRAWLING;
Shrubbery s2 = Shrubbery.GROUND;
Shrubbery s3 = Shrubbery.CRAWLING;
System.out.println("s1==s2,result: " + (s1 == s2));
System.out.println("s1==s3,result: " + (s1 == s3));
System.out.println("Shrubbery.CRAWLING.equals(s1),result: " + Shrubbery.CRAWLING.equals(s1));
System.out.println("Shrubbery.CRAWLING.equals(s2),result: " + Shrubbery.CRAWLING.equals(s2));
}
}
运行结果:
s1==s2,result: false
s1==s3,result: true
Shrubbery.CRAWLING.equals(s1),result: true
Shrubbery.CRAWLING.equals(s2),result: false
それはない仕事を見つけることができます==または等号が可能です。実際には、米国のドラマは、メソッドが==比較を使用することです等しいです
public final boolean equals(Object other) {
return this==other;
}
単一の実施形態は、列挙を実装しました
言及した効果的なJavaは、シングルモードの列挙のベストモードの実施例です。なぜを列挙するための最良の方法を達成するために、いくつかの方法がありますSingletonパターンを実現しますか?
単一の実施形態は、以下の利点が得列挙したため。
- 例の列挙単一の単純な言葉遣い
- スレッドの安全性の問題を解決するための列挙
- 単一のケースを破壊する問題のデシリアライズを解決するための列挙
次のように例では、単一の列挙をデモ:
package com.legend.enumdemo.singleton;
/**
* 枚举实现的单例
*
* @author legend
*/
public class SingletonEnumTest {
public static void main(String[] args) {
SingletonEnum.INSTANCE.setName("legend@qichunlin");
System.out.println(SingletonEnum.INSTANCE.getName());
}
public enum SingletonEnum {
INSTANCE,
;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
EnumSetのとEnumMap
EnumSetの
先来看看EnumSet的继承体系图
もちろん、EnumSetのもHashSetのに比べて、インタフェースのセットを実装し、それは次のような利点があります。
- 少ないメモリを消費
- それはビットベクトルの実装であるため、より効率的。
- 予測可能な走査順序(enum定数の宣言順序)
- ヌルを追加することを拒否
EnumSetのは、同じ列挙型でなければなりませんストアに要求され、高いパフォーマンスを実現するために設定されています。一般的な方法をEnumSetの:
- ALLOF()指定された列挙クラスは、すべての列挙値をEnumSetの含まれているコレクションを作成するには
- range() 获取某个范围的枚举实例
- of() 创建一个包括参数中所有枚举元素的EnumSet集合
- complementOf() 初始枚举集合包括指定枚举集合的补集
package com.legend.enumdemo.enumset;
import java.util.EnumSet;
/**
* EnumSet枚举
*
* @author legend
*/
public class EnumTest {
public static void main(String[] args) {
EnumSet<SeasonEnum> set1, set2, set3, set4;
set1 = EnumSet.of(SeasonEnum.SPRING, SeasonEnum.FALL, SeasonEnum.WINTER);
set2 = EnumSet.complementOf(set1);
set3 = EnumSet.allOf(SeasonEnum.class);
set4 = EnumSet.range(SeasonEnum.SUMMER, SeasonEnum.WINTER);
System.out.println("Set 1: " + set1);
System.out.println("Set 2: " + set2);
System.out.println("Set 3: " + set3);
System.out.println("Set 4: " + set4);
}
}
运行结果:
Set 1: [SPRING, FALL, WINTER]
Set 2: [SUMMER]
Set 3: [SPRING, SUMMER, FALL, WINTER]
Set 4: [SUMMER, FALL, WINTER]
EnumMap
EnumMap的继承体系图如下:
显然,EnumMap也实现了Map接口,相比于HashMap,它有以下优点:
- 消耗较少的内存
- 效率更高
- 可以预测的遍历顺序
- 拒绝 null
EnumMap就是map的高性能实现。 它的常用方法跟HashMap是一致的,唯一约束是枚举相关。
看实例
package com.legend.enumdemo.enummap;
import java.util.EnumMap;
import java.util.Map;
/**
* enumMap 实现
*/
public class EnumTest {
public static void main(String[] args) {
Map<SeasonEnum, String> map = new EnumMap<SeasonEnum, String>(SeasonEnum.class);
map.put(SeasonEnum.SPRING, "春天");
map.put(SeasonEnum.SUMMER, "夏天");
map.put(SeasonEnum.FALL, "秋天");
map.put(SeasonEnum.WINTER, "冬天");
System.out.println(map);
System.out.println(map.get(SeasonEnum.SPRING));
}
}
运行结果:
{SPRING=春天, SUMMER=夏天, FALL=秋天, WINTER=冬天}
春天