http://www.meichua.com (收藏,设为首页)
以前打牌的时候出牌太慢,其他人就叫着出啊,出啊,所以就变成了chua...... (手机请访问 http://3g.dlog.cn/meichua)

java特性-枚举

2008年3月28日(Friday) 17点14分 作者: chua 天气: 心情: 一般

2 Enumerated Types
2.1 创建enum

 创建enum类型必须包括至少3个基本成分
 A:enum关键字
 B:enum类的名字
 C:一组该类的值
 一些其他可定义的成分
 D:一些enum要实现的接口
 E:变量定义
 F:方法定义
 G:特殊的赋值
 
 看一下代码:
  public enum Grade {
     A, B, C, D, F, INCOMPLETE
  }
  
  public class Student {
      private String name;
      private Grade  grade;
      public Student(String name){
          this.name = name;
      }
      public void setName(String name) {
          this.name = name;
      }
      public String getName() {
          return name;
      }
      public void assignGrade(Grade grade) {
          this.grade = grade;
      }
      public Grade getGrade() {
          return grade;
      }
      /**
       * @param args
       */
      public static void main(String[] args) {
          Student studentA = new Student("A");
          Student studentB = new Student("B");
          Student studentC = new Student("C");
          studentA.assignGrade(Grade.B);
          studentB.assignGrade(Grade.INCOMPLETE);
          studentC.assignGrade(Grade.A);
      }
  }
  
 注意:
 A:你可以把所有的public static final的变量在enum类中声明
 B:大部分时候,你只需要使用enum的基本功能
 C:按照约定用大写字符定义你的enum
 D:enum类像一般的class类被引用
 以下是enum的基本概念:
 A:enum是类
 B:所有的enum类都继承java.lang.Enum
 C:enum类中定义的值不是integer,而是一个java.lang.Enum的实例
 D:enum类没有公有的构造器,这是为了防止创建新的值
 E:enum类中的所有值都是public static final的(Enums are not "final" when they have value-specific methods)
 F:enum的值可以用=或或者equasl()来计较
 G:enum类都实现了java.lang.Comparable
 H:enum类override toString()方法,返回类中value的name,如Grade.INCOMPLETE.toString()返回"INCOMPLETE",toString()方法不是fianl,你可以override
  I:enum类提供一个valueOf()方法,如Grade.valueOf("INCOMPLETE")返回Grade.INCOMPLETE
  J:enum类提供一个final的方法ordinal(),返回整形的各enum值在enum类中的位置,从0开始
  K:enum类提供values()方法,返回enum类中enum值的集合


2.2 Declaring Enums Inline
 看一下代码
   public class Downloader {
      public enum DownloadStatus { INITIALIZING, IN_PROGRESS, COMPLETE };
       .
       .
   }
   需要说明的是申明DownloadStatus就不需要再用static修饰了


2.3 Switching on Enums
 看一下代码
    public static void switchStatement(Student student) {
        switch (student.getGrade()) {
            case A:
                break;
            case B:
                break;
            case C:
                break;
            case D:
                break;
            case F:
                break;
            case INCOMPLETE:
                break;
            default:
                break;
        }
    }
  需要注意的是在这里case A而不是case Grade.A;这里只是为了简化写法,和static import没有关系
  switch语句最好加上default处理,说不定有人会修改enum类,这样你的switch语句还是可以处理unknown conditions


2.4 Maps of Enums
  看一下以前的写法
    public static final int INITIALIZING = 0;
    public static final int COMPILING    = 1;
    public static final int COPYING      = 2;
    public static final int JARRING      = 3;
    public static final int ZIPPING      = 4;
    public static final int DONE         = 5;
    public static final int ERROR        = 6;

    public static String[] antMessages = new String[] {
            "Initalizing Ant...",        // INITIALIZING
            "Compiling Java classes...", // COMPILING
            "Copying files...",          // COPYING
            "JARring up files...",       // JARRING
            "ZIPping up files...",       // ZIPPING
            "Build complete.",           // DONE
            "Error occurred."            // ERROR
                                         };

    public static void main(String[] args) {
        .
        .
        int antStatus = antProcess.getStatus();
        System.out.println("ant> " + antMessages[antStatus]);
        .
    }
  使用EnumMap的写法
    public enum AntStatus {
        INITIALIZING, COMPILING, COPYING, JARRING, ZIPPING, DONE, ERROR
    }
    
    import java.util.EnumMap;
    public class AntEnumMap {
        /**
         * @param args
         */
        public static void main(String[] args) {
            EnumMap antMessages = new EnumMap(AntStatus.class);
            antMessages.put(AntStatus.INITIALIZING, "Initializing Ant...");
            antMessages.put(AntStatus.COMPILING, "Compiling Java classes...");
            antMessages.put(AntStatus.COPYING, "Copying files...");
            antMessages.put(AntStatus.JARRING, "JARring up files...");
            antMessages.put(AntStatus.ZIPPING, "ZIPping up files...");
            antMessages.put(AntStatus.DONE, "Build complete.");
            antMessages.put(AntStatus.ERROR, "Error occurred.");
            for (AntStatus status : AntStatus.values()) {
                System.out.println("For status " + status + ", message is: " + antMessages.get(status));
            }
        }
    }
 附件的好处是初始化EnumMap的时候不需要排序,保证enums对应message的正确性
 感觉优化不是很明显,还是那么多代码要写;在创建EnumMap对象的时候如果可以写成new EnumMap(AntStatus.class,String[] strings)从而在内部完成map的装载是不是更方便?


2.5 Sets of Enums
 看一下代码
  public enum GuitarFeatures {
      ROSEWOOD, // back/sides
      MAHOGANY, // back/sides
      ZIRICOTE, // back/sides
     
      SPRUCE, // top
      CEDAR,  // top
  
      AB_ROSETTE,    // abalone rosette
      AB_TOP_BORDER, // abalone top border
     
      IL_DIAMONDS, // diamond/square inlay
      IL_DOTS      // dots inlays
  }
  
  import java.util.EnumSet;

  public class GuitarEnumSet {
      public static void main(String[] args) {
          EnumSet allFeatures = EnumSet.allOf(GuitarFeatures.class);
          EnumSet backSides = EnumSet.of(GuitarFeatures.ROSEWOOD,
                                         GuitarFeatures.MAHOGANY,
                                         GuitarFeatures.ZIRICOTE);
          EnumSet bourgeoisD150 = EnumSet.of(GuitarFeatures.ROSEWOOD,
                                             GuitarFeatures.SPRUCE,
                                             GuitarFeatures.AB_ROSETTE,
                                             GuitarFeatures.IL_DIAMONDS);
          boolean hasAbRosette = bourgeoisD150.contains(GuitarFeatures.AB_ROSETTE);
      }
  }
 详细看一下api


2.6 Adding Methods to an Enum
 看一下代码:
  public enum GuitarFeatures {
      ROSEWOOD(0),        // back/sides
      MAHOGANY(0),        // back/sides
      ZIRICOTE(300),      // back/sides
      SPRUCE(0),          // top
      CEDAR(0),           // top
      AB_ROSETTE(75),     // abalone rosette
      AB_TOP_BORDER(400), // abalone top border
      IL_DIAMONDS(150),   // diamond/square inlay
      IL_DOTS(0);         // dots inlays
  
      private float upcharge;
  
      GuitarFeatures(float upcharge){
          this.upcharge = upcharge;
      }
  
      public float getUpcharge() {
          return upcharge;
      }
  }
 为enum类添加了带float参数构造方法,类中的每个枚举值的声明都要将使用此构造方法;枚举值的定义以分号结束;变量upcharge的申明不能放到枚举值的申明之前;枚举类的构造方法是私有的,不能申明为public


2.7 Implementing Interfaces with Enums
 首先构造一个interface类
  public interface Features {
    public float getUpcharge();
  }
 修改enum类的定义为:
 public enum GuitarFeatures implements Features {
  .
  .
 }


2.8 Value-Specific Class Bodies
 看一下代码
  enum Opcode {
    PUSH(1) {
      public void perform(StackMachine machine, int[] operands) {
        machine.push(operands[0]);
      }
    },
  
    ADD(0) {
      public void perform(StackMachine machine, int[] operands) {
        machine.push(machine.pop( ) + machine.pop( ));
      }
    },
  
    BEZ(1) {
      public void perform(StackMachine machine, int[] operands) {
        if (machine.pop( ) == 0) machine.setPC(operands[0]);
      }
    };
  
    Opcode(int numOperands) { this.numOperands = numOperands; }
    int numOperands;
    public abstract void perform(StackMachine machine, int[] operands);
  }
 之前说过enum都是final的,除了在Value-Specific Class Bodies的情况下,实事上,上面的编码看,每个enum value都创建了一个匿名子类,编译后,除了enum类本身外,多了几个enum value的子类,又从反编译class文件看到一般的enum类都会被声明为final,而这里没有.
 以上的写法往往在debug时很麻烦,以前在debug ejb代码的时候也是碰到,系统会帮你生成一些非代码级的代码调用,看一下简单的实现:
  enum Opcode {
      PUSH(1), ADD(0), BEZ(1);
  
      int numOperands;
  
      Opcode(int numOperands){
          this.numOperands = numOperands;
      }
  
      public void perform(StackMachine machine, int[] operands) {
          switch (this) {
              case PUSH:
                  machine.push(operands[0]);
                  break;
              case ADD:
                  machine.push(machine.pop() + machine.pop());
                  break;
              case BEZ:
                  if (machine.pop() == 0) machine.setPC(operands[0]);
                  break;
              default:
                  throw new AssertionError();
          }
      }
  }

标签: java 枚举 Enumerated Types enum 
姓名: 
邮箱:  {可选}
网址:  {可选} 此评论只有我和写日记的人查阅
校验码: ... <我看不清楚>
网记为您提供手机和互联网同步的个人主页,带给你不一样的体验