安卓系统源码--DeskClock源码解析(三)枚举

我选取了DataModel中的部分源码,是关于枚举的。  

public final class DataModel {

    /** Indicates the display style of clocks. */
    public enum ClockStyle {ANALOG, DIGITAL}

    /** Indicates the preferred sort order of cities. */
    public enum CitySort {NAME, UTC_OFFSET}

    /** Indicates the preferred behavior of hardware volume buttons when firing alarms. */
    public enum AlarmVolumeButtonBehavior {NOTHING, SNOOZE, DISMISS}

    /** Indicates the reason alarms may not fire or may fire silently. */
    public enum SilentSetting {
        @SuppressWarnings("unchecked")
        DO_NOT_DISTURB(R.string.alarms_blocked_by_dnd, 0, Predicate.FALSE, null),
        @SuppressWarnings("unchecked")
        MUTED_VOLUME(R.string.alarm_volume_muted,
                R.string.unmute_alarm_volume,
                Predicate.TRUE,
                new UnmuteAlarmVolumeListener()),
        SILENT_RINGTONE(R.string.silent_default_alarm_ringtone,
                R.string.change_setting_action,
                new ChangeSoundActionPredicate(),
                new ChangeSoundSettingsListener()),
        @SuppressWarnings("unchecked")
        BLOCKED_NOTIFICATIONS(R.string.app_notifications_blocked,
                R.string.change_setting_action,
                Predicate.TRUE,
                new ChangeAppNotificationSettingsListener());

        private final @StringRes int mLabelResId;
        private final @StringRes int mActionResId;
        private final Predicate<Context> mActionEnabled;
        private final View.OnClickListener mActionListener;

        SilentSetting(int labelResId, int actionResId, Predicate<Context> actionEnabled,
                View.OnClickListener actionListener) {
            mLabelResId = labelResId;
            mActionResId = actionResId;
            mActionEnabled = actionEnabled;
            mActionListener = actionListener;
        }

        public @StringRes int getLabelResId() { return mLabelResId; }
        public @StringRes int getActionResId() { return mActionResId; }
        public View.OnClickListener getActionListener() { return mActionListener; }
        public boolean isActionEnabled(Context context) {
            return mLabelResId != 0 && mActionEnabled.apply(context);
        }
}


创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式

 Class Enum<E extends Enum<E>>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造

函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。


通常定义常量方法和枚举定义常量方法区别

以下内容可能有些无聊,但绝对值得一窥

1.    代码:

public class State {

public static final int ON = 1;

public static final Int OFF= 0;

}

 

有什么不好了,大家都这样用了很长时间了,没什么问题啊。

首先,它不是类型安全的。你必须确保是int

其次,你还要确保它的范围是0 和1

最后,很多时候你打印出来的时候,你只看到 1 和0 ,

 

但其没有看到代码的人并不知道你的企图,抛弃你所有旧的public static final 常量吧

 

2.    可以创建一个enum 类,把它看做一个普通的类。除了它不能继承其他类了。(java 是单继承,它已经继承了Enum),

可以添加其他方法,覆盖它本身的方法

3.    switch() 参数可以使用enum 了

 

4.    values() 方法是编译器插入到enum 定义中的static 方法,所以,当你将enum 实例向上转型为父类Enum 是,values() 就不可访问了。解决办法:在Class 中有一个getEnumConstants() 方法,所以即便Enum 接口中没有values() 方法,我们仍然可以通过Class 对象取得所有的enum 实例

 

5.    无法从enum 继承子类,如果需要扩展enum 中的元素,在一个接口的内部,创建实现该接口的枚举,以此将元素进行分组。达到将枚举元素进行分组。

 

6.    使用EnumSet 代替标志。enum 要求其成员都是唯一的,但是enum 中不能删除添加元素。

 

7.    EnumMap 的key 是enum ,value 是任何其他Object 对象。

 

8.    enum 允许程序员为eunm 实例编写方法。所以可以为每个enum 实例赋予各自不同的行为。

 

9.    使用enum 的职责链(Chain of Responsibility) . 这个关系到设计模式的职责链模式。以多种不同的方法来解决一个问题。然后将他们链接在一起。当一个请求到来时,遍历这个链,直到链中的某个解决方案能够处理该请求。

 

10.   使用enum 的状态机

 

11.   使用enum 多路分发


更发现一篇枚举相关的好文:http://blog.csdn.net/sup_heaven/article/details/35559117


本以为RED只是一个Color类的一个static final的实例而已。但后然发现不是这样的,先看看下面的一种枚举类型使用的代码。

[java]  view plain  copy
  1. package com.lxq.enumm;  
  2.   
  3. public enum Color  
  4. {  
  5.     RED{  
  6.         public String getName(){  
  7.             return "红色";  
  8.         }  
  9.     }  
  10.     ,GREEN{  
  11.         public String getName(){  
  12.             return "绿色";  
  13.         }  
  14.     }  
  15.     ,YELLOW{  
  16.         public String getName(){  
  17.             return "黄色";  
  18.         }  
  19.     };  
  20.     public abstract String getName();  
  21. }  

如果RED只是一个Color类的一个static final的实例,那么上面的代码就很让了费解了,为什么在枚举类型中可以有一个抽象方法,而每个枚举值可以对其重新实现?

别急,看了我对这个类的测试代码你就明白,测试代码如下:

[java]  view plain  copy
  1. import java.lang.reflect.Modifier;  
  2.   
  3. public class EnumDemoFour{  
  4.     public static void main(String[] args){  
  5.         //打印该枚举值的名称  
  6.         System.out.println(Color.RED.getName());  
  7.         //打印该枚举值的类  
  8.         System.out.println(Color.RED.getClass());  
  9.         //打印该枚举值的类的父类  
  10.         System.out.println(Color.RED.getClass().getSuperclass());  
  11.         //打印该枚举值的类的父类的父类  
  12.         System.out.println(Color.RED.getClass().getSuperclass().getSuperclass());  
  13.         //打印该枚举类型的修饰符  
  14.         System.out.println(Modifier.toString(Color.class.getModifiers()));  
  15.     }     
  16.     /*运行结果 
  17.     红色 
  18.     class com.lxq.enumm.Color$1 
  19.     class com.lxq.enumm.Color 
  20.     class java.lang.Enum 
  21.     public abstract*/  
  22. }  

该运行结果首先说明了RED和Color不是同一个类,而是前者是后者的一个子类;同时也说明了enum申明的其实是一个abstract的类,所以Color中可以有抽象方法。

那么,我们应该这么理解枚举类型的原理,首先enum Color继承了java.lang.Enum这个抽象类,但enum Color还是一个抽象类,所以它可以有抽象方法和非抽象方法。

而enum Color中的枚举值变量RED事实上上Color的一个匿名子类,所以它可以实现Color中的抽象方法,这样,当我们调用System.out.println(Color.RED.getName());

就是调用了匿名子类实现的方法。当然这些过程的很多事都有编译器等为我们做了,所以这里的代码很简单。

要是你不明白上面打印的内容,我再提供一个普通的类给你看看,还是类似的效果哦。

[java]  view plain  copy
  1. public abstract class TestInnerClass  
  2. {  
  3.     public abstract void dosomething();  
  4.     public static void main(String[] args){  
  5.         TestInnerClass tic=new TestInnerClass(){  
  6.             @Override  
  7.             public void dosomething()  
  8.             {  
  9.                 System.out.println("我是匿名子类");  
  10.             }     
  11.         };  
  12.         tic.dosomething();  
  13.         System.out.println(tic.getClass());  
  14.     }  
  15.     /*输出结果 
  16.     我是匿名子类 
  17.     class TestInnerClass$1 
  18.     */  
  19. }  

最后再附上网上一个使用Java普通类模拟枚举的例子http://blog.csdn.net/xyang81/article/details/7185428,这个例子真的很好。

使用Java普通类模拟枚举

[java]  view plain  copy
  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3.   
  4. /** 
  5.  * 模拟星期中的表示的天,每个星期天都表示一个对象 
  6.  * 1、类中的每一个枚举成员都是该类的一个实例对象 
  7.  * 2、构造函数私有化 
  8.  * 3、提供操作枚举成员的抽象方法和静态方法 
  9.  */  
  10. public abstract class WeekDate {  
  11.     /** 
  12.      * 星期一 
  13.      */  
  14.     public static final WeekDate MON = new WeekDate("MON",0) {//匿名子类  
  15.         @Override  
  16.         public WeekDate nextDay() {  
  17.             return TUES;  
  18.         }  
  19.         @Override  
  20.         public WeekDate preDay() {  
  21.             return SUN;  
  22.         }  
  23.         @Override  
  24.         public String toString() {  
  25.             return "WeekDate.MON";  
  26.         }  
  27.     };    
  28.       
  29.     /** 
  30.      * 星期二 
  31.      */  
  32.     public static final WeekDate TUES = new WeekDate("TUES",1) {  
  33.         @Override  
  34.         public WeekDate nextDay() {  
  35.             return WEDNES;  
  36.         }  
  37.         @Override  
  38.         public WeekDate preDay() {  
  39.             return MON;  
  40.         }  
  41.         @Override  
  42.         public String toString() {  
  43.             return "WeekDate.TUES";  
  44.         }  
  45.     };  
  46.       
  47.     /** 
  48.      * 星期三 
  49.      */  
  50.     public static final WeekDate WEDNES = new WeekDate("WEDNES",2) {  
  51.         @Override  
  52.         public WeekDate nextDay() {  
  53.             return THURS;  
  54.         }  
  55.         @Override  
  56.         public WeekDate preDay() {  
  57.             return TUES;  
  58.         }  
  59.         @Override  
  60.         public String toString() {  
  61.             return "WeekDate.WEDNES";  
  62.         }     
  63.     };  
  64.       
  65.     /** 
  66.      * 星期四 
  67.      */  
  68.     public static final WeekDate THURS = new WeekDate("THURS",3) {  
  69.         @Override  
  70.         public WeekDate nextDay() {  
  71.             return FRI;  
  72.         }  
  73.         @Override  
  74.         public WeekDate preDay() {  
  75.             return WEDNES;  
  76.         }         
  77.         @Override  
  78.         public String toString() {  
  79.             return "WeekDate.THURS";  
  80.         }         
  81.     };  
  82.       
  83.     /** 
  84.      * 星期五 
  85.      */  
  86.     public static final WeekDate FRI = new WeekDate("FRI",4){  
  87.         @Override  
  88.         public WeekDate nextDay() {  
  89.             return SATUR;  
  90.         }  
  91.         @Override  
  92.         public WeekDate preDay() {  
  93.             return THURS;  
  94.         }  
  95.         @Override  
  96.         public String toString() {  
  97.             return "WeekDate.FRI";  
  98.         }  
  99.     };  
  100.       
  101.     /** 
  102.      * 星期六 
  103.      */  
  104.     public static final WeekDate SATUR = new WeekDate("SATUR",5){  
  105.         @Override  
  106.         public WeekDate nextDay() {  
  107.             return SUN;  
  108.         }  
  109.         @Override  
  110.         public WeekDate preDay() {  
  111.             return FRI;  
  112.         }         
  113.         @Override  
  114.         public String toString() {  
  115.             return "WeekDate.SATUR";  
  116.         }         
  117.     };  
  118.       
  119.     /** 
  120.      * 星期日 
  121.      */  
  122.     public static final WeekDate SUN = new WeekDate("SUN",6){  
  123.         @Override  
  124.         public WeekDate nextDay() {  
  125.             return MON;  
  126.         }  
  127.         @Override  
  128.         public WeekDate preDay() {  
  129.             return SATUR;  
  130.         }  
  131.         @Override  
  132.         public String toString() {  
  133.             return "WeekDate.SUN";  
  134.         }  
  135.     };  
  136.       
  137.     private static Map<String, WeekDate> valueMap = new HashMap<String, WeekDate>();  
  138.       
  139.     /** 
  140.      * 枚举名称 
  141.      */  
  142.     private final String name;  
  143.       
  144.     /** 
  145.      * 枚举成员的顺序 
  146.      */  
  147.     private final int ordinal;  
  148.       
  149.     private WeekDate(String name,int ordinal) {  
  150.         this.name = name;  
  151.         this.ordinal = ordinal;  
  152.     }  
  153.       
  154.     /** 
  155.      * 保存枚举成员 
  156.      */  
  157.     private static WeekDate[] values = {  
  158.         MON,TUES,WEDNES,THURS,FRI,SATUR,SUN  
  159.     };  
  160.       
  161.     //初始化  
  162.     static {  
  163.         valueMap.put("MON", values[0]);  
  164.         valueMap.put("TUES", values[1]);  
  165.         valueMap.put("WEDNES", values[2]);  
  166.         valueMap.put("THURS", values[3]);  
  167.         valueMap.put("FRI", values[4]);  
  168.         valueMap.put("SATUR", values[5]);  
  169.         valueMap.put("SUN", values[6]);  
  170.     }  
  171.       
  172.     /** 
  173.      * 下一天 
  174.      * @return 
  175.      */  
  176.     public abstract WeekDate nextDay();  
  177.       
  178.     /** 
  179.      * 前一天 
  180.      * @return 
  181.      */  
  182.     public abstract WeekDate preDay();  
  183.       
  184.     /** 
  185.      * 枚举中的所有成员 
  186.      * @return 
  187.      */  
  188.     public static WeekDate[] values() {  
  189.         return values;  
  190.     }  
  191.       
  192.     /** 
  193.      * 将一个字符串转换成一个枚举成员对象 
  194.      * @param name 枚举名称 
  195.      * @return 枚举对象 
  196.      */  
  197.     public static WeekDate valueOf(String name) {  
  198.         if (name.equalsIgnoreCase("MON")) {  
  199.             return MON;  
  200.         } else if (name.equalsIgnoreCase("TUES")) {  
  201.             return TUES;  
  202.         } else if (name.equalsIgnoreCase("WEDES")) {  
  203.             return WEDNES;  
  204.         } else if (name.equalsIgnoreCase("THURS")) {  
  205.             return THURS;  
  206.         } else if (name.equalsIgnoreCase("FRI")) {  
  207.             return FRI;  
  208.         } else if (name.equalsIgnoreCase("SATUR")) {  
  209.             return SATUR;  
  210.         } else if (name.equalsIgnoreCase("SUN")) {  
  211.             return SUN;  
  212.         } else {  
  213.             throw new IllegalArgumentException("找不到" + name + "枚举类型!");  
  214.         }  
  215.     }  
  216.       
  217.     /** 
  218.      * 优化字符串转枚举对象 
  219.      * @param name 枚举名称 
  220.      * @return 枚举对象 
  221.      */  
  222.     public static WeekDate valueOf_2(String name) {  
  223.         WeekDate value = valueMap.get(name.toUpperCase());  
  224.         if (value == null) {  
  225.             throw new IllegalArgumentException("找不到" + name + "枚举类型!");  
  226.         }  
  227.         return value;  
  228.     }  
  229.     public String getName() {  
  230.         return name;  
  231.     }  
  232.     public int getOrdinal() {  
  233.         return ordinal;  
  234.     }  
  235. }  

使用JDK5.0中提供的枚举特性

[java]  view plain  copy
  1. /** 
  2.  * 枚举的应用 
  3.  * 存储每周中的天份 
  4.  */  
  5. public enum WeekDateEnum {  
  6.   
  7.     MON {  
  8.           
  9.         @Override  
  10.         public WeekDateEnum nextDay() {  
  11.             return TUES;  
  12.         }  
  13.           
  14.         @Override  
  15.         public WeekDateEnum preDay() {  
  16.             return SUN;  
  17.         }  
  18.           
  19.     },  TUES {  
  20.           
  21.         @Override  
  22.         public WeekDateEnum nextDay() {  
  23.             return WEDNES;  
  24.         }  
  25.           
  26.         @Override  
  27.         public WeekDateEnum preDay() {  
  28.             return MON;  
  29.         }  
  30.           
  31.     },  WEDNES {  
  32.           
  33.         @Override  
  34.         public WeekDateEnum nextDay() {  
  35.             return THURS;  
  36.         }  
  37.           
  38.         @Override  
  39.         public WeekDateEnum preDay() {  
  40.             return TUES;  
  41.         }  
  42.           
  43.     },  THURS {  
  44.           
  45.         @Override  
  46.         public WeekDateEnum nextDay() {  
  47.             return FRI;  
  48.         }  
  49.           
  50.         @Override  
  51.         public WeekDateEnum preDay() {  
  52.             return WEDNES;  
  53.         }  
  54.           
  55.     },  FRI {  
  56.           
  57.         @Override  
  58.         public WeekDateEnum nextDay() {  
  59.             return SATUR;  
  60.         }  
  61.           
  62.         @Override  
  63.         public WeekDateEnum preDay() {  
  64.             return THURS;  
  65.         }  
  66.           
  67.     },  SATUR {  
  68.           
  69.         @Override  
  70.         public WeekDateEnum nextDay() {  
  71.             return SATUR;  
  72.         }  
  73.           
  74.         @Override  
  75.         public WeekDateEnum preDay() {  
  76.             return FRI;  
  77.         }  
  78.           
  79.     },  SUN {  
  80.           
  81.         @Override  
  82.         public WeekDateEnum nextDay() {  
  83.             return SATUR;  
  84.         }  
  85.           
  86.         @Override  
  87.         public WeekDateEnum preDay() {  
  88.             return MON;  
  89.         }  
  90.           
  91.     };  
  92.   
  93.     private WeekDateEnum() {}  
  94.       
  95.     /** 
  96.      * 下一天 
  97.      * @return 
  98.      */  
  99.     public abstract WeekDateEnum nextDay();  
  100.       
  101.     /** 
  102.      * 前一天 
  103.      * @return 
  104.      */  
  105.     public abstract WeekDateEnum preDay();  
  106.       
  107.     /** 
  108.      * 枚举对象公共的toString方法,可以在case块中反馈自己想要返回的信息 
  109.      */  
  110.     public String toString() {  
  111.         switch (this) {  
  112.         case MON:  
  113.             return "WeekDateEnum.MON";  
  114.         case TUES:  
  115.             return "WeekDateEnum.TUES";  
  116.         case WEDNES:  
  117.             return "WeekDateEnum.WEDNES";  
  118.         case THURS:  
  119.             return "WeekDateEnum.THURS";  
  120.         case FRI:  
  121.             return "WeekDateEnum.FRI";  
  122.         case SATUR:  
  123.             return "WeekDateEnum.SATUR";  
  124.         case SUN:  
  125.             return "WeekDateEnum.SUN";  
  126.         default:  
  127.             return null;  
  128.         }  
  129.     }  
  130. }  

枚举功能测试

[java]  view plain  copy
  1. /** 
  2.  * 枚举功能测试 
  3.  */  
  4. public class EnumTest {  
  5.   
  6.     public static void main(String[] args) {  
  7.           
  8.         //使用普通JAVA类模拟枚举的应用  
  9.         WeekDate weekDate = WeekDate.MON;       //获得一个枚举对象  
  10.         //调用枚举中提供的方法  
  11.         System.out.println(weekDate.nextDay());   
  12.         System.out.println(weekDate.preDay());  
  13.         System.out.println(weekDate.getName());  
  14.         //获得枚举成员所在枚举成员列表中的位置  
  15.         System.out.println(weekDate.getOrdinal());  
  16.         //调用某一个枚举成员的方法  
  17.         System.out.println(WeekDate.values()[0].preDay());  
  18.         System.out.println("---------------遍历枚举成员,普通JAVA类模拟--------------------------");  
  19.         for (WeekDate weekDate2 : WeekDate.values()) {  
  20.             System.out.println(weekDate2);  
  21.         }  
  22.           
  23.         System.out.println("\n=================================================================\n");  
  24.           
  25.         //使用JDK中提供的枚举特性功能应用  
  26.         WeekDateEnum weekDateEnum = WeekDateEnum.MON;   //获得一个枚举对象  
  27.         System.out.println(WeekDate.values().length);   //获得枚举成员数量  
  28.         System.out.println(weekDateEnum.name());        //获得枚举的字符串名称  
  29.         System.out.println(weekDateEnum.toString());    //打印枚举对象,已重写toString方法,默认打印枚举的名称  
  30.         System.out.println(weekDateEnum.nextDay().ordinal());   //枚举成员列表中的位置  
  31.         System.out.println(WeekDateEnum.valueOf("FRI").nextDay().ordinal());  
  32.         System.out.println("---------------遍历枚举成员,使用JDK的枚举特性-------------------------");  
  33.         for (WeekDateEnum enumDemo : WeekDateEnum.values()) {  
  34.             System.out.println(enumDemo);  
  35.         }  
  36.           
  37.     }   
  38.       
  39. }  


猜你喜欢

转载自blog.csdn.net/qiaojianfang_1148/article/details/79066017