技术开发 频道

Java和C++在细节上的差异(二)

       上一篇文章为大家介绍了《Java和C++的差异第一部分》,在这篇文章中我们继续解开其中的奥妙。

  四、枚举:

  枚举的是在Java 1.5SE 中开始支持的,以下为Java枚举的基本概念和应用技巧:

  1. 所有的enum对象均是由class对象作为底层支持的,该对象继承自JDK中的Enum,但是该底层类确实final类,既不能再被其他的类继承。

  2. 枚举的出现完全替代了原有的"public static final"常量表示法,枚举以一种更加合理、优雅和安全的方式替换了原有的方案。其最基本的声明方式如下:

1     public enum Color {
2         RED, BLUE, BLACK, YELLOW
3     }

  3. Enum中构造函数的原型为protected Enum(String name, int ordinal),自定义的枚举对象会将自身的名字以字符串的形式,同时将自己在整个常量从声明的顺序作为超类构造函数的两个参数传给超类并由超类完成必要的初始化,如:RED枚举常量将调用super("RED",0)。

  4. 枚举中可以定义构造函数、域方法和域字段,但是枚举中的构造器必须是私有(private)的,如果自定义枚举中有了自定义的构造函数,那么每个枚举常量在声明时必须按照自定义构造函数的规则传入参数。枚举对象的构造函数只是在枚举常量对象声明的时刻才调用一次,之后再也不能像普通对象那样通过new的方法创建,见如下代码:

1     public enum Size {
2         SMALL(0.8),
3         MEDIUM(1.0),
4         LARGE(1.2);
5         double pricingFactor;
6         private Size(double p) {
7           pricingFactor = p;
8         }
9     }

  注:枚举常量列表必须写在最前面声明,否则编译器报错。

  5. 可以给自定义枚举添加域方法,见如下代码:

1     public enum Size {
2         SMALL(0.8),
3         MEDIUM(1.0),
4         LARGE(1.2);
5         private double pricingFactor;
6         Size(double p) {
7             pricingFactor = p;
8         }
9         public double getPricingFactor() {
10             return pricingFactor;
11         }
12     }

  6. 枚举中常用域方法:

1     public enum Size{
2         SMALL,
3         MEDIUM,
4         LARGE;
5     }
6     public static void main(String[] args){
7         //两种获得枚举类型的方法
8         Size s1 = Size.SMALL;
9         //valueOf的函数原型为<T extends Enum<T>> T valueOf(Class<T> enumType,String name)
10         Size s2 = Enum.valueOf(Size.class, "SMALL");
11         //Size(自定义枚举)的valueOf方法是Java编译器在生成字节码的时候自动插入的。
12         Size s3 = Size.valueOf("MEDIUM");//1
13
14         //结果同上,枚举重载了equals方法
15         System.out.println("Size.MEDIUM.equals(Enum.valueOf(Size.class, \"MEDIUM\")):"+
16                 Size.MEDIUM.equals(Enum.valueOf(Size.class, "MEDIUM")));
17
18         //遍历枚举类型中所有的成员,这里应用的Size.values方法和Size.valueOf方法
19         //一样均是编译器在生成字节码的时候自动插入的。
20         for(Size s:Size.values()){//2
21             //ordinal()和name()方法均为Enum提供的方法,返回枚举常量在声明时的构
22             //造函数中自动调用超类构造函数时传入的自身字符串名和在声明列表中的序号
23             System.out.println(s.ordinal()+"  "+s.name()+"  "+s.toString());
24         }
25         //compareTo方法缺省比较的是枚举常量的ordinal()的返回值。
26         if (s1.compareTo(s3) < 0)
27             System.out.println("Size.SMALL is less than Size.MEDIUM");
28     }

  7. 在枚举中可以声明基于特定常量的类主体,见如下代码:

1     public enum Size {
2         //Small、ExtraLarge和ExtraExtraLarge均使用自定义的getPricingFactor
3         //方法覆盖Size提供的缺省getPricingFactor方法。
4         Small {
5             @Override
6             public double getPricingFactor() {
7                 return 0.8;
8             }
9         },
10         //Medium和Large将使用Size内部缺省实现的getPricingFactor方法。
11         Medium,
12         Large,
13         ExtraLarge {
14             @Override
15             public double getPricingFactor() {
16                 return 1.2;
17             }
18         },
19         ExtraExtraLarge {
20             @Override
21             public double getPricingFactor() {
22                 return 1.2;
23             }
24         };
25         public double getPricingFactor() {
26             return 1.0;
27         }
28     }
29     public static void main(String args[]) {
30         for (Size s : Size.values()) {
31             double d = s.getPricingFactor();
32             System.out.println(s + " Size has pricing factor of " + d);
33         }
34     }
35     /*    结果如下:
36         Small Size has pricing factor of 0.8
37         Medium Size has pricing factor of 1.0
38         Large Size has pricing factor of 1.0
39         ExtraLarge Size has pricing factor of 1.2
40         ExtraExtraLarge Size has pricing factor of 1.2    */

  8. 枚举在switch语句中的用法,见如下代码:

1     public enum Color {
2         RED, BLUE, BLACK, YELLOW
3     }
4     public static void main(String[] args) {
5         Color m = Color.BLUE;
6         //case语句中引用枚举常量时不需要再加上枚举的类型名了。
7         switch (m) {
8         case RED:
9             System.out.println("color is red");
10             break;
11         case BLACK:
12             System.out.println("color is black");
13             break;
14         case YELLOW:
15             System.out.println("color is yellow");
16             break;
17         case BLUE:
18             System.out.println("color is blue");
19             break;
20         default:
21             System.out.println("color is unknown");
22             break;
23         }
24     }

  9. 和枚举相关的两个容器EnumMap和EnumSet,声明和主要用法如下。

1     EnumMap<K extends Enum<K>, V>  
2     EnumSet<E extends Enum<E>>
3     //Code Example 1
4     public enum State {    
5         ON, OFF    
6     };    
7     public static void main(String[] args) {    
8         //EnumSet的使用    
9         EnumSet stateSet = EnumSet.allOf(State.class);  
10         for (State s : stateSet)
11             System.out.println(s);  
12  
13         //EnumMap的使用  
14         EnumMap stateMap = new EnumMap(State.class);  
15         stateMap.put(State.ON, "is On");  
16         stateMap.put(State.OFF, "is off");  
17         for (State s : State.values())
18             System.out.println(s.name() + ":" + stateMap.get(s));
19     }
20        
21     //Code Example 2
22     public enum Size {
23         Small,Medium,Large
24     }
25     public static void main(String args[]) {
26         Map<Size, Double> map = new EnumMap<Size, Double>(Size.class);
27         map.put(Size.Small, 0.8);
28         map.put(Size.Medium, 1.0);
29         map.put(Size.Large, 1.2);
30         for (Map.Entry<Size, Double> entry : map.entrySet())
31           helper(entry);
32     }
33     private static void helper(Map.Entry<Size, Double> entry) {
34         System.out.println("Map entry: " + entry);
35     }

  10. Java枚举和C++枚举的主要区别为两点,一是C++中的枚举中只能定义常量,主要用于switch子句,二是C++中的枚举常量可以直接和数值型变量进行各种数学运算。

0
相关文章