Emum是在Java5中引入的新特性牛曹,從那開始似袁,它被廣泛的用在不同的Java應(yīng)用中存璃,相比于C和C++的Enum淋叶,Java的Enum功能更加強(qiáng)大阎曹。但是很多開發(fā)人員暫時(shí)還沒意識(shí)到它的強(qiáng)大之處伪阶,在Enum的一些細(xì)節(jié)問題上把握的還不到位。Enum的特性及相關(guān)資料可以整理出一本書也不為過处嫌,這里簡(jiǎn)單對(duì)Enum做個(gè)大概栅贴。主要講解以下幾個(gè)方面。
- Enum的介紹
- Enum的特性
- Enum的用法
- Enum的一些面試題
- Enum用法建議
什么是Enum
Enum是一個(gè)Java的關(guān)鍵字熏迹,用于表示一個(gè)固定的常用值檐薯。例如,每周的天數(shù)注暗,每年的月數(shù)等坛缕。Enum是一種類型,就像Class和Interface可以用于定義一系列的Enum常量
Enum的特性
- Enum常量隱式的加上了static和final捆昏,一旦被創(chuàng)建就無法修改
- Enum提供了是類型安全的(type-safe)
- Enum隱式的加上了values()方法赚楚,返回一個(gè)數(shù)組包含所有的Enum常量
- 兩個(gè)Enum常量可以使用
==
或equals()
方法比較 - Enum可以用在switch語句中,就像int骗卜,String宠页。
- Enum有自己的名稱空間
- Enum可以實(shí)現(xiàn)Java接口
- 可以在Enum中定義構(gòu)造器
Enum的用法
1 . Enum的聲明,Enum可以聲明在一個(gè)類之外或者在類內(nèi)部寇仓,但是不能在方法中举户。
// 外部聲明Enum
enum Color {
RED,GREEN,BLUE;
}
public class Test
{
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
}
}
//內(nèi)部聲明Enum
public class Test
{
enum Color
{
RED, GREEN, BLUE;
}
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
}
}
2 . 在創(chuàng)建Enum常量的時(shí)候可以指定值,但是這個(gè)時(shí)候你需要定義一個(gè)成員變量構(gòu)造器遍烦。構(gòu)造器必須是private的俭嘁,不然會(huì)報(bào)編譯錯(cuò)誤。
public enum Currency {
PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
private int value;
private Currency(int value) {
this.value = value;
}
}
3 . 使用==
或equals
比較兩個(gè)enum
因?yàn)閑num對(duì)象都是繼承自Enum類的服猪,可以看到Enum中的equals方法為供填。
建議使用==
方法,直接比較應(yīng)該比調(diào)用方法的速度更快一些蔓姚。另外==
號(hào)還能防止NullPointerException
public final boolean equals(Object other) {
return this==other;
}
4 . 對(duì)Enum進(jìn)行排序的時(shí)候捕虽,使用compareTo方法慨丐。
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
5 .有兩個(gè)新的集合類EnumMap
和EnumSet
坡脐,他們兩個(gè)是對(duì)Set和Map的高性能實(shí)現(xiàn),當(dāng)有機(jī)會(huì)使用它們的時(shí)候房揭,盡量使用它們备闲。
Enum面試問題
說說Enum的繼承
所有的enums隱式的extend了java.lang.Enum類,因?yàn)橐粋€(gè)類只能extend一個(gè)父親捅暴,所以enum不能extend其它的類恬砂。
但是Enum可以實(shí)現(xiàn)許多接口Enum的values,ordinal,valueOf方法
enums默認(rèn)有values(),ordinal()和valueOf()方法蓬痒。
values()方法返回所有在enum中定義的常量值泻骤,以數(shù)組形式返回。
ordinal()方法返回每個(gè)常量的索引下標(biāo),就像數(shù)組的下標(biāo)
valueOf()方法傳入字符串參數(shù)狱掂,如果enum中存在對(duì)應(yīng)字符串的常量值演痒,則返回對(duì)應(yīng)的enum常量
// 案例代碼
enum Color
{
RED, GREEN, BLUE;
}
public class EnumLearn
{
public static void main(String[] args)
{
Color arr[] = Color.values();
for (Color col : arr)
{
System.out.println(col + " at index "
+ col.ordinal());
}
System.out.println(Color.valueOf("RED"));
}
}
//輸出
RED at index 0
GREEN at index 1
BLUE at index 2
RED
3 . Enum的構(gòu)造器特性
enum可以有構(gòu)造器方法,它的構(gòu)造器方法會(huì)在enum類型加載的時(shí)候趋惨,按常量的個(gè)數(shù)順序的執(zhí)行
我們不能直接創(chuàng)建enum對(duì)象鸟顺,因此我們也不能直接調(diào)用enum的構(gòu)造器方法,構(gòu)造器方法必須是private的
//案例代碼
enum AccountType implements Serializable,Cloneable
{
SAVING, FIXED, CURRENT;
private AccountType()
{
System.out.println("It is a account type");
}
}
class EnumOne
{
public static void main(String[]args)
{
System.out.println(AccountType.FIXED);
}
}
//輸出結(jié)果
It is a account type
It is a account type
It is a account type
FIXED
4 . Enum的單例模式優(yōu)缺點(diǎn)
參考《Effitive Java》器虾,優(yōu)點(diǎn)大于缺點(diǎn)讯嫂,因?yàn)閑num是線程安全的,因此我們無需考慮單例模式的雙重檢查兆沙。主要原因:
- enum的單例模式簡(jiǎn)單
- enum是線程安全的
- enum的單例模式自己處理序列化 *
// Enum的單例模式 VS 傳統(tǒng)雙重檢查的單例模式
//單例模式欧芽,僅需使用一行代碼.
// EasySingleton.INSTANCE,enum中也可以寫其他方法
public enum EasySingleton{
INSTANCE;
}
//傳統(tǒng)模式
public class DoubleCheckedLockingSingleton{
private volatile DoubleCheckedLockingSingleton INSTANCE;
private DoubleCheckedLockingSingleton(){}
public DoubleCheckedLockingSingleton getInstance(){
if(INSTANCE == null){
synchronized(DoubleCheckedLockingSingleton.class){
// 二次檢查
if(INSTANCE == null){
INSTANCE = new DoubleCheckedLockingSingleton();
}
}
}
return INSTANCE;
}
}
5 . Enum的==
和equals
的區(qū)別葛圃。
前面有提到渐裸。
6 . 我們能使用構(gòu)造方法創(chuàng)建enum實(shí)例嗎?
不能装悲,enum的構(gòu)造方法必須是私有的昏鹃。
Enum的用法建議
在能想到使用Enum的時(shí)候可以考慮使用Enum。
- 使用Enum代替定義的相關(guān)int類型常量
- 能用到EnumSet和EnumMap的時(shí)候使用它們诀诊,后面會(huì)再說明它們兩個(gè)的用法
- 表示固有的對(duì)象最好使用Enum
最后
看一些Java相關(guān)的面試題洞渤,發(fā)現(xiàn)Enum相關(guān)問題出現(xiàn)頻率挺高的,在這里對(duì)enum用法做個(gè)整理属瓣。希望能幫助到大家