枚举(enum)类型
2017-12-03 15:46
357 查看
关键字enum 可以将一组具名的值的有限集合创建一种新的类型,而这些具名的值可以作为常规的程序使用。创建enum 时,编译器会为你生成一个相关的类,这个类继承自java.lang.Enum 。下面是一个例子演示了一些Enum 提供的一些功能。
输出:
CAT oridinal:0
-1 false false
class com.jas.enumtest.Animal
CAT
——–分割线———-
DOG oridinal:1
0 true true
class com.jas.enumtest.Animal
DOG
——–分割线———-
SHEEP oridinal:2
1 false false
class com.jas.enumtest.Animal
SHEEP
——–分割线———-
DOG CAT SHEEP
ordinal() 方法返回一个int 类型的值,这个值是enum 在实例中声明的顺序,从0 开始。可以使用 == 来比较enum 实例,编译器会自动为你提供equals() 方法与 hashCode() 方法。Enum 类实现了Comparable 接口,所以你可以使用compareTo() 方法。同时Enum 类还实现了Serializable 接口。
getDeclaringClass() 方法返回其所属的类。
name 方法返回enum 实例声明时的名字,这与toString 方法返回的值相同。valueOf() 是在Enum 中定义的static 方法,它可以根据给定的名字返回相应的enum 实例,如果不存在给定名字的实例,就会抛出异常。
覆盖enum 的方法:
当我们想要覆盖enum 中的方法时,我们会发现,它就只有一个方法toString(),当我们覆盖它时与覆盖一般的类的方法没有区别。
输出
Cat Dog Sheep
向enum 中添加方法:
除了不能继承一个enum 之外,我们基本上可以将enum 看作是一个常规的类。这也意味着enum 拥有自己的构造函数,以及我们可以向enum 中添加方法。它甚至是可以拥有main() 方法。这里我们通过一个方法返回一个枚举类型的描述不再仅仅是一个toString() 类型的实现。
输出:
CAT : 喵喵喵~
DOG : 汪汪汪~
SHEEP : 咩咩咩~
需要注意的是:如果我们打算自定义方法,那么必须在enum 徐磊实例的后面添加一个分号。同时Java 要求你必须先定义enum 实例,就像上面这样我们打算在定义enum 实例之前定义description 但是却得到一个编译器的错误提示。enum 中的构造函数与方法与普通的类没有任何区别,除了有少量的限制enum 可以说就是一个类。所以我们可以使用enum 做许多额外的事。
switch 语句中的 enum:
一般来说,在switch 语句中 只能使用整数值,而枚举天生就具备整数值的次序,并且可以通过ordinal() 方法获得其在enum 中的顺序,因此我们可以在switch 中使用枚举。
输出:
The traffic light is : RED
The traffic light is : GREEN
The traffic light is : YELLOW
The traffic light is : RED
values() 的神秘之处:
我们知道编译器为我们创建的enum 都继承自Enum 类。但是如果你去查看Enum 类就会发现,它并没有values() 方法。但是我们在上面确实使用了这个方法,这是为什么呢?下面我们使用反射机制来查看其中的原因。
—– Analyzing class com.jas.enumtest.Explore —–
superClass : class java.lang.Enum
—– end —–
—– Analyzing class java.lang.Enum —–
genericInterface : java.lang.Comparable
genericInterface : interface java.io.Serializable
superClass : class java.lang.Object
—– end —–
exploreMethods : [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
enumMethods : [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
exploreMethods.containsAll(enumMethods): true
exploreMethods.removeAll(enumMethods): true
exploreMethods : [values]
答案就是values() 方法是由编译器添加的static 方法。其实这个过程中还未其添加了valueOf() 方法。但是Enum 中明明已经有了valueOf() 方法,为什么编译器还会为其添加这个方法呢?Enum 中的valueOf() 方法需要传递进来两个参数,但是新增的这个方法只需要传递进来一个参数。
参考书籍:
《Java 编程思想》Bruce Eckel 著 陈昊鹏 译
package com.jas.enumtest; enum Animal{CAT,DOG,SHEEP} public class EnumClass { public static void main(String[] args) { for(Animal animal : Animal.values()){ System.out.println(animal + " oridinal:" + animal.ordinal()); System.out.print(animal.compareTo(Animal.DOG) + " "); System.out.print(animal.equals(Animal.DOG) + " "); System.out.println(animal == Animal.DOG); System.out.println(animal.getDeclaringClass()); System.out.println(animal.name()); System.out.println("--------分割线----------"); } for(String str : "DOG,CAT,SHEEP".split(",")){ Animal animal = Animal.valueOf(Animal.class,str); System.out.print(animal + " "); } } }
输出:
CAT oridinal:0
-1 false false
class com.jas.enumtest.Animal
CAT
——–分割线———-
DOG oridinal:1
0 true true
class com.jas.enumtest.Animal
DOG
——–分割线———-
SHEEP oridinal:2
1 false false
class com.jas.enumtest.Animal
SHEEP
——–分割线———-
DOG CAT SHEEP
ordinal() 方法返回一个int 类型的值,这个值是enum 在实例中声明的顺序,从0 开始。可以使用 == 来比较enum 实例,编译器会自动为你提供equals() 方法与 hashCode() 方法。Enum 类实现了Comparable 接口,所以你可以使用compareTo() 方法。同时Enum 类还实现了Serializable 接口。
getDeclaringClass() 方法返回其所属的类。
name 方法返回enum 实例声明时的名字,这与toString 方法返回的值相同。valueOf() 是在Enum 中定义的static 方法,它可以根据给定的名字返回相应的enum 实例,如果不存在给定名字的实例,就会抛出异常。
覆盖enum 的方法:
当我们想要覆盖enum 中的方法时,我们会发现,它就只有一个方法toString(),当我们覆盖它时与覆盖一般的类的方法没有区别。
enum Animal{ CAT,DOG,SHEEP; @Override public String toString() { String id = name(); String lower = id.substring(1).toLowerCase(); return id.charAt(0) + lower; } } public class EnumClass { public static void main(String[] args) { for(Animal animal : Animal.values()) System.out.print(animal + " "); } }
输出
Cat Dog Sheep
向enum 中添加方法:
除了不能继承一个enum 之外,我们基本上可以将enum 看作是一个常规的类。这也意味着enum 拥有自己的构造函数,以及我们可以向enum 中添加方法。它甚至是可以拥有main() 方法。这里我们通过一个方法返回一个枚举类型的描述不再仅仅是一个toString() 类型的实现。
enum Animal{ // private String description; 这是不允许的 CAT("喵喵喵~"), DOG("汪汪汪~"), SHEEP("咩咩咩~"); private String description; private Animal(String description){ this.description = description; } public String getDescription(){ return description; } } public class EnumClass { public static void main(String[] args) { for(Animal animal : Animal.values()) System.out.println(animal + " : " + animal.getDescription()); } }
输出:
CAT : 喵喵喵~
DOG : 汪汪汪~
SHEEP : 咩咩咩~
需要注意的是:如果我们打算自定义方法,那么必须在enum 徐磊实例的后面添加一个分号。同时Java 要求你必须先定义enum 实例,就像上面这样我们打算在定义enum 实例之前定义description 但是却得到一个编译器的错误提示。enum 中的构造函数与方法与普通的类没有任何区别,除了有少量的限制enum 可以说就是一个类。所以我们可以使用enum 做许多额外的事。
switch 语句中的 enum:
一般来说,在switch 语句中 只能使用整数值,而枚举天生就具备整数值的次序,并且可以通过ordinal() 方法获得其在enum 中的顺序,因此我们可以在switch 中使用枚举。
enum Singal{GREEN, YELLOW, RED} public class TrafficLight { Singal color = Singal.RED; public void 4000 change(){ switch (color){ case RED: color = Singal.GREEN; break; case GREEN: color = Singal.YELLOW; break; case YELLOW: color = Singal.RED; break; } } public String toString(){ return "The traffic light is : " + color; } public static void main(String[] args) { TrafficLight light = new TrafficLight(); for (int i = 0; i < 4; i++) { System.out.println(light.toString()); light.change(); } } }
输出:
The traffic light is : RED
The traffic light is : GREEN
The traffic light is : YELLOW
The traffic light is : RED
values() 的神秘之处:
我们知道编译器为我们创建的enum 都继承自Enum 类。但是如果你去查看Enum 类就会发现,它并没有values() 方法。但是我们在上面确实使用了这个方法,这是为什么呢?下面我们使用反射机制来查看其中的原因。
import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Set; import java.util.TreeSet; enum Explore{HERE,THERE} public class Reflection { public static Set<String> analyze(Class<?> enumClass){ Set<String> set = new TreeSet<>(); System.out.println("----- Analyzing " + enumClass + " -----"); for(Type type : enumClass.getGenericInterfaces()) System.out.println("genericInterface : " + type); System.out.println("superClass : " + enumClass.getSuperclass()); for(Method method : enumClass.getMethods()) set.add(method.getName()); System.out.println("----- end -----"); System.out.println(); return set; } public static void main(String[] args) { Set<String> exploreMethods = analyze(Explore.class); Set<String> enumMethods = analyze(Enum.class); System.out.println("exploreMethods : " + exploreMethods); System.out.println("enumMethods : " + enumMethods); System.out.println("exploreMethods.containsAll(enumMethods): " + exploreMethods.containsAll(enumMethods)); System.out.println("exploreMethods.removeAll(enumMethods): " + exploreMethods.removeAll(enumMethods)); System.out.println("exploreMethods : " + exploreMethods); } }
—– Analyzing class com.jas.enumtest.Explore —–
superClass : class java.lang.Enum
—– end —–
—– Analyzing class java.lang.Enum —–
genericInterface : java.lang.Comparable
genericInterface : interface java.io.Serializable
superClass : class java.lang.Object
—– end —–
exploreMethods : [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
enumMethods : [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
exploreMethods.containsAll(enumMethods): true
exploreMethods.removeAll(enumMethods): true
exploreMethods : [values]
答案就是values() 方法是由编译器添加的static 方法。其实这个过程中还未其添加了valueOf() 方法。但是Enum 中明明已经有了valueOf() 方法,为什么编译器还会为其添加这个方法呢?Enum 中的valueOf() 方法需要传递进来两个参数,但是新增的这个方法只需要传递进来一个参数。
参考书籍:
《Java 编程思想》Bruce Eckel 著 陈昊鹏 译
相关文章推荐
- C语言enum(枚举)数据类型
- 第十五节 常量const 、 枚举enum 、结构struct 值类型和引用类型
- iOS: 枚举类型 enum,NS_ENUM,NS_OPTIONS
- C/C++ enum class枚举类型
- 枚举类型enum 使用
- 枚举类型Enum用来存放系统常量
- 【C++】enum枚举类型
- Hibernate将Enum枚举类型映射为Int类型(补充VARCHAR类型配置)
- Java中Enum类型的序列化及类升级不建议用枚举的原因
- C++之枚举类型enum
- iOS: 枚举类型 enum,NS_ENUM,NS_OPTIONS
- c语言之枚举类型(enum)
- java关键字之enum枚举类型浅析
- ORM框架中用枚举类型enum来接收数据库中的tinyint字段
- iOS/object-c: 枚举类型 enum,NS_ENUM,NS_OPTIONS
- java中的枚举类型enum的使用
- C#中的枚举类型enum用法
- enum枚举类型使用
- C#枚举类型-Enum