java枚举的特点_Java中有些好的特性(二):枚举
前言
我在寫上一篇時,開始選了一個很土的名字“Java超過C#的地方”,然后引起了某些同學的不滿,后來修改了個名。我在這里再次申明一下,我沒有貶低任何語言之意,純粹是從一個.NET程序員的角度去看Java,看看是不是有些什么在開發中覺得比較“爽”的東西。務必請用專業的態度來比較各種技術的長短。
Java的枚舉是一個“class”
Java的早期版本時沒有enum的,大家都用interface里加常量的方式實現,Java 1.5版本之后添加了對enum的支持。
Java認為類C的枚舉不是類型安全的(type safe),所以Java中沒有枚舉,Java的枚舉就是類(Enum Class),只是用了一個enum代替class而已(雖然.NET里在MSIL層面枚舉最終也是一種“class”)。因為Java的枚舉是類,所以就帶來一些與C#中的枚舉有趣的不同點,比如可以添加方法,可以添加屬性。請看下面的Java代碼:
1: public enum Role{
2: Admin("管理員"),
3: Owner("所有者"),
4: Creator("創建者");
5:
6: private String displayName;
7:
8: Role(String displayName){
9: this.displayName = displayName;
10: }
11:
12: public String getDisplayName(){
13: return this.displayName;
14: }
15: }
Java的枚舉居然可以這么寫!枚舉里可以有方法。這里的Admin,Owner,Creator實際上是Role類的常量,調用Role(String)構造器,但是Java不允許你將enum的構造器設為public,由Java自己內部調用。
有人可能會問這樣有什么用處呢?比如上面這段代碼,建一個枚舉表示系統中的所有角色,為了用戶友好性,數據庫里我們保存角色名字,但是在系統界面上我們要顯示一個更具描述性的名字,而且假如我們的系統需要多語言化,那么在不同的語言平臺上的界面上我們的系統應該顯示不同的描述性短語(注意:.NET中的枚舉是不能國際化的),比如下面的界面:
那我們就可以這樣做:
1: public enum Role{
2: Admin("role-admin"),
3: Owner("role-owner"),
4: Creator("role-creator");
5:
6: private String displayName;
7:
8: Role(String displayName){
9: this.displayName = displayName;
10: }
11:
12: public String getDisplayName(){
13: return Resource.get(this.displayName);
14: }
15: }
我們這里getDisplayName的時候調用一個國際化的API,通過枚舉構造器里傳入的參數作為key獲取國際化的表示。
Java的enum是類型安全、版本安全的
這樣一說好像C#的enum不是類型安全的一樣,哼!嗯,某種角度上來說C#(本文以C#指代整個.NET平臺)的枚舉真的不是類型安全的。比如下面的代碼:
1: using System;
2: public enum Role:short
3: {
4: Admin,Owner,Creator
5: }
6:
7: public class Program
8: {
9: public static void Main(String[] args)
10: {
11: byte i = (byte)Role.Owner;
12: }
13: }
即使我們給C#的enum指定了underlying type,但是我們還是可以將其任意的與基本類型進行轉換。而且這種轉換是靜悄悄地進行的,編譯器和運行時都不會提醒我們。
C#的enum完全是一個常量,所以跟C#的const一樣還會帶來版本的問題。比如A程序集定義了一個枚舉Role,B程序集引用A程序集,使用Role,實際上在運行時B程序集不再需要A程序集了(大家知道什么原因吧)。這樣如果A程序集修改了Role,比如修改了枚舉常量的順序:從Admin,Owner,Creator變為Admin,Creator,Owner。而B程序集沒有重新編譯,這個時候就會出現問題。
C#中實現Enum class
實際上Enum Class是一種模式,只是java的enum將這種模式放到了語言中,我們在C#里一樣可以實現:
1: public sealed Class Role
2: {
3: public static readonly Role Admin = new Role("role-admin");
4: public static readonly Role Owner = new Role("role-owner");
5: public static readonly Role Creator = new Creator("role-creator");
6:
7: private String displayName;
8:
9: private Role(String displayName)
10: {
11: this.displayName = displayName;
12: }
13:
14: public String DisplayName
15: {
16: get
17: {
18: Resource.Get(this.displayName);
19: }
20: }
21: }
只是實現起來比java的默認實現繁瑣一點而已,畢竟那是人家語言的first class。
位標記
如果在C#的enum上添加[Flags]的特性話,這個enum就不再是enum了,就變成了位標記。位標記這東西在實現某些功能時確實非常滴方便,比如一個文件的屬性:只讀,只寫,可讀寫,比如權限控制系統等等。Java的枚舉就不能添加這么一個annotation了,不過Java有個EnumSet,我們借助這個API實現位標記同樣的功能。
后記
Java的enum與C#的enum各有特色,Java的enum更靈活一些,C#的enum更輕型一些,但是使用時請注意C#的enum的一些問題。
總結
以上是生活随笔為你收集整理的java枚举的特点_Java中有些好的特性(二):枚举的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 1.5.0 gcj_CentO
- 下一篇: java获取系统当前时间格式化_java