1. 程式人生 > >簡要介紹Java中的列舉類

簡要介紹Java中的列舉類

一、概念
在某些情況下,一個類的物件是有限而且固定的,例如季節類,它只有四個物件,這種例項有限而且固定的類,在Java裡被稱為列舉類。
手動實現列舉類:
1.通過private將構造器隱藏起來。
2.把這個類的所有可能例項都使用public static final屬性來儲存。
3.如果有必要,可以提供一些靜態方法,允許通過特定引數來獲取與之匹配的例項。

請看下面示例:

package com.home;

public class Season {
	private final String name;
	public static final Season SPRING = new Season("春天");
	public static final Season SUMMER = new Season("夏天");
	public static final Season FALL = new Season("秋天");
	public static final Season WINTER = new Season("冬天");

	// 將構造器定義為private
	public Season(String name) {
		super();
		this.name = name;
	}

	// 只提供getter方法
	public String getName() {
		return name;
	}

	/**
	 * 提供一個靜態方法獲取例項
	 * 
	 * @param seasonNum
	 * @return
	 */
	public static Season getSeason(int seasonNum) {
		switch (seasonNum) {
		case 1:
			return SPRING;
		case 2:
			return SUMMER;
		case 3:
			return FALL;
		case 4:
			return WINTER;
		default:
			return null;
		}
	}
}

二、區別
從上面的示例中可以看出手動定義列舉類是比較麻煩的,我們可以使用關鍵字enum來定義列舉類,列舉類與普通類的區別:
1.使用enum定義的列舉類預設繼承了java.lang.Enum類,而不是繼承Object類。java.lang.Enum類實現了java.lang.Serialiable和java.lang.Comparable兩個介面。
2.列舉類的構造器只能使用private修飾,即使省略也預設是private的。
3.列舉類例項只能顯示給出,否則永遠不能產生例項,列出這些例項時,系統會自動新增public static final修飾,無需程式設計師顯示新增。
4.所有列舉類都提供了一個values方法,用於可以很方便地遍歷所有列舉值。



使用enum關鍵字定義的列舉類示例:

package com.home;

public enum Gender {
	// 此處的列舉值必須呼叫對應的構造器來建立
	MALE("男"), FEMALE("女");
	private final String name;

	// 列舉類的構造器只能使用private修飾
	private Gender(String name) {
		this.name = name;
	}

	// 只提供getter方法
	public String getName() {
		return name;
	}

	/**
	 * 提供一個靜態方法獲取例項對應的描述資訊
	 * 
	 * @param gender
	 * @return
	 */
	public static String getGenderDisc(Gender gender) {
		// 注意switch表示式中可以是列舉值
		switch (gender) {
		case MALE:
			return "I am a man";
		case FEMALE:
			return "I am a woman";
		default:
			return null;
		}
	}

}


三、列舉類的一些常用方法介紹,請看下面測試類:

package com.home;

public class TestGender {

	public static void main(String[] args) {
		// Gender.values()列出所有列舉值
		for (Gender g : Gender.values()) {
			System.out.println(g);
		}
		// 獲取例項可以直接使用EnumClass.variable形式
		Gender gender = Gender.MALE;
		System.out.println(Gender.getGenderDisc(gender));
		// 也可以使用Enum的valueOf方法獲取列舉值
		System.out.println(Enum.valueOf(Gender.class, "MALE"));
		// 比較列舉物件的順序,如果該列舉物件位於指定列舉物件之前,則返回負整數-1;之後,則返回正整數1;否則返回0
		System.out.println(Gender.FEMALE.compareTo(Gender.MALE));
		// name方法大致和toString方法一樣,返回列舉常量的名稱,一般習慣用toString方法
		System.out.println(Gender.MALE.name());
		// ordinal()返回列舉值的索引值,第一個為0,即從0開始
		System.out.println(Gender.MALE.ordinal());
	}

}


四、實現介面的列舉類

其實列舉類實現介面和普通類沒多少區別,也是使用implements關鍵字,可以實現一個或多個介面。但是需要注意的是,如果像普通類一樣實現介面後直接重寫接口裡的方法的話,那麼列舉類的所有例項就擁有一樣的介面實現了,這樣就失去了意義和靈活性,所以往往會為每個例項提供不同的方法實現,示例如下:

package com.home;

public enum Gender implements GenderDesc {
	MALE("男") {
		// 花括號部分實際上是一個類體部分
		public void info() {
			System.out.println("I am a man");
		}
	},
	FEMALE("女") {
		public void info() {
			System.out.println("I am a woman");
		}
	};
	private final String name;

	// 列舉類的構造器只能使用private修飾
	private Gender(String name) {
		this.name = name;
	}

	// 只提供getter方法
	public String getName() {
		return name;
	}
}

介面:

package com.home;

public interface GenderDesc {
	public void info();
}


五、包含抽象方法的列舉類,列舉類中對普通方法的使用和普通類一樣,這裡就只介紹其抽象方法的使用,其實抽象方法跟實現介面是一個道理,這裡不多說,看示例:

package com.home;

public enum Gender {
	MALE("男") {
		// 花括號部分實際上是一個類體部分
		public String getInfo() {
			return "I am a man";
		}
	},
	FEMALE("女") {
		public String getInfo() {
			return "I am a woman";
		}
	};
	private final String name;

	// 列舉類的構造器只能使用private修飾
	private Gender(String name) {
		this.name = name;
	}

	// 只提供getter方法
	public String getName() {
		return name;
	}

	// 為列舉類定義一個抽象方法,這個抽象方法由不同列舉值提供不同實現
	public abstract String getInfo();
}


注意:上面列舉類中定義了抽象方法,但是,類卻沒用abstract修飾,這點跟普通類不一樣,因為列舉類需要顯示建立列舉值,併為抽象方法提供實現,否則會出現編譯錯誤。