国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[Effective Java]第六章 枚舉和注解

2019-11-14 22:45:04
字體:
來源:轉載
供稿:網友
[Effective java]第六章 枚舉和注解聲明:原創作品,轉載時請注明文章來自SAP師太技術博客( 博/客/園www.cnblogs.com):m.survivalescaperooms.com/jiangzhengjun,并以超鏈接形式標明文章原始出處,否則將追究法律責任!原文鏈接:http://m.survivalescaperooms.com/jiangzhengjun/p/4255663.html 第六章 枚舉和注解30、 用enum代替int常量

枚舉類型是指由一組固定的常量組成合法值的類型,例如一年中的季節或一副牌中的花色。在沒引入枚舉時,一般是聲明一組int常量,每個類型成員一個常量:

publicstaticfinalintAPPLE_FUJI= 0;

publicstaticfinalintAPPLE_PipPIN= 1;

publicstaticfinalintAPPLE_GRANNY_SMITH= 2;

publicstaticfinalintORANGE_NAVEL= 0;

publicstaticfinalintORANGE_TEMPLE= 1;

publicstaticfinalintORANGE_BLOOD= 2;

這種方法稱作int枚舉模式,存在很多不足,不具有類型安全與使用方便性。如果你將apple傳到一個想要接收orange的方法中,編譯器也不會出現警告,而且還可以使用==來比較apple與orange。

注意每個apple常量都以APPLE_作為前綴,每個orange常量都以ORANGE_作為前綴,這是因為可以防止名稱沖突。

采用int枚舉模式的程序是十分脆弱,因為int枚舉是編譯時常量,被編譯到使用它們的客戶端中。如果與枚舉常量關聯的int發生了變化,客戶端就必須重新編譯,如果不重新編譯,程序還是可以運行,但不是最新的值了。

另外從使用方便性來看,沒有便利的toString方法,打印出來的為數字,沒有多大的用處。要遍歷一組中所有的int枚舉常量,也沒有可靠的方法。

既然int枚舉常量有這么多的缺點,那使用String枚舉常如何?同樣也不是我們期望的。雖然在可以打印字符串,但它會導致性能問題,因為它依賴于字符串的比較操作。另外與int枚舉常量一樣會編譯到客戶端代碼中,編譯時難以發現,但會在運行時出錯。

幸運的是1.5版本開始,枚舉可以避免int和String枚舉模式的缺點,并提供許多額外的好處。下面是最簡單的形式:

publicenumApple{FUJI,PIPPIN,GRANNY_SMITH}

publicenumOrange{NAVEL,TEMPLE,BLOOD}

Java枚舉類型背后的基本想法很簡單:本質上是int值,它們是通過公有的靜態final域為每個枚舉常量導出實例的類。因為沒有可以訪問的構造器,枚舉類型是真正的final。因為客戶端即不能創建枚舉類型的實例,也不能對它進行擴展,因此對它進行實例化,而只有聲明過的枚舉常量。換句話說,枚舉類型是實例受控的。它們是單例的泛型化,本質上是單元素的枚舉。

枚舉提供了編譯時類型安全。如果聲明一個參數的類型為Apple,就可以保證,被傳到該參數上的任何非null的對象引用一定屬于三個有效的Apple值之一。試圖傳遞類型錯誤的值時,會導致編譯時錯誤,就像試圖將某種枚舉類型的表達式賦值給另一種枚舉類型的變量,或者試圖利用==操作符比較不同枚舉類型的值一樣,都會出錯。

枚舉提供了單獨的命名空間,同一系統中可以有多個同名的枚舉類型變量。你可以增加或者重新排序枚舉類型常量,而無需重新編譯它的客戶端代碼,因為導出常量的域在枚舉類型和它的客戶端之間提供了一個隔離層:常量值并沒有被編譯到客戶端代碼中,而是在int枚舉模式之中。最終,可以通過調用toString方法,將枚舉轉換成可打印的字符串。

除了完善了int枚舉模式不足外,枚舉還允許添加任意的方法和域,并實例任意接口,它們提供了所有Object(見第3章)的高級實現,實現了Comparable和Serializable接口,并針對枚舉型的可任意改變性設計了序列化方式。

如果一個枚舉具有普遍適用性,它就應該成為一個頂層類,如果它只是被用在一個特定的頂層類中,它就應該成為該頂層類的一個成員類。

可以為枚舉類型添加數據域與方法,下面是一個算術運行的枚舉類:

publicenumOperation {

PLUS("+") {

doubleapply(doublex,doubley) {

returnx + y;

}

},

MINUS("-") {

doubleapply(doublex,doubley) {

returnx - y;

}

},

TIMES("*") {

doubleapply(doublex,doubley) {

returnx * y;

}

},

DIVIDE("/") {

doubleapply(doublex,doubley) {

returnx / y;

}

};

PRivatefinalString symbol;//操作符:+ - * /

Operation(String symbol) {//構造函數,存儲操作符供toString打印使用

this.symbol = symbol;

}

@Override

//重寫Enum中的打印name的性為

publicString toString() {

returnsymbol;

}

//抽像方法,不同的常量具有不同的功能,需在每個常量類的主體里重寫它

abstractdoubleapply(doublex,doubley);

/*

* 初始化時,存儲操作符與枚舉常量的對應關系,用來實現fromString方法

* 這樣我們就可以通過操作符來獲取到對應的枚舉常量,有點像valueOf方法,

* 只不過它是通過枚舉常量的名字name來獲取常量的。這種通用的方法還可以

* 應用到其他枚舉類中

*/

privatestaticfinalMap<String, Operation>stringToEnum=newHashMap<String, Operation>();

static{ //從name到枚舉常量轉換到從某個域到枚舉常量的轉換

for(Operation op :values())

stringToEnum.put(op.toString(), op);

}

//根據操作符來獲取對應的枚舉常量,如果沒有返回null,模擬valueOf方法

publicstaticOperation fromString(String symbol) {

returnstringToEnum.get(symbol);

}

publicstaticvoidmain(String[] args) {

doublex = Double.parseDouble(args[0]);

doubley = Double.parseDouble(args[1]);

for(Operation op : Operation.values())

System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));

for(Operation op : Operation.values())

System.out.printf("%f %s %f = %f%n", x, op, y, Operation

.fromString(op.toString()).apply(x, y));

}

}

在opr包下會看見Operation.class、Operation$4.class、Operation$2.class、Operation$3.class、Operation$1.class這樣幾個類,Operation$X.class都是繼承自Operation類,而Operation又繼承自Enum類,下面是反編譯這些類的代碼:

public abstract class opr.Operation extends java.lang.Enum{

Word-spacing: 0px; text-transform: none; word-break: normal; margin: 0cm 0cm 0pt; letter-spacing: normal; line-height: normal; text-indent: 0px; -webkit-text-size

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 万源市| 五家渠市| 迁西县| 环江| 大余县| 灯塔市| 石柱| 塘沽区| 大竹县| 剑川县| 寻乌县| 株洲市| 扎鲁特旗| 金川县| 民乐县| 淮安市| 夏津县| 余江县| 开封市| 商都县| 富蕴县| 郓城县| 高台县| 湘阴县| 阿克| 万宁市| 广平县| 保靖县| 读书| 宝丰县| 宁远县| 雅安市| 南部县| 若尔盖县| 东宁县| 凌海市| 贵南县| 外汇| 弋阳县| 青冈县| 平南县|