您的位置:首页 > 其它

枚举(enum)类型

2017-12-03 15:46 357 查看
关键字enum 可以将一组具名的值的有限集合创建一种新的类型,而这些具名的值可以作为常规的程序使用。创建enum 时,编译器会为你生成一个相关的类,这个类继承自java.lang.Enum 。下面是一个例子演示了一些Enum 提供的一些功能。

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 著 陈昊鹏 译
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  enum