文章目录
- 1.枚举概述
- 1.1.什么是枚举类型
- 1.2.枚举历史
- 2.定义枚举类型
- 3.枚举与switch
- 4.枚举与类
- 4.1. 所有枚举类都是Enum的子类
- 4.2. 枚举类的构造器
- 4.3. 枚举类的方法
- 4.4. 枚举类的属性
- 4.5 使用匿名类来创建枚举常量
- 5.使用匿名类来创建枚举常量
- 5.1.枚举也是编译期状态
1.枚举概述
1.1.什么是枚举类型
word文档的对齐方式有几种:左对齐、居中对齐、右对齐;
开车的方向有几种:前、后、左、右;
枚举就是有限实现个数的类型,你可能会说,byte类型也只有256个,没错,但我们真实定义为枚举的类型,一般最多也就十多个实例,再多就不会定义为枚举了。
1.2.枚举历史
枚举是JDK1.5版本新增的特性(泛型、For-each等如今被广泛应用的特性也是由JDK1.5时所新增的),另外到了JDK1.6后switch语句支持枚举类型。
在JDK1.4之前没有枚举类型,都是使用int或字符串类型来表示枚举,如果枚举只有两个选项,那么连int都用不上,只需要使用boolean类型即可。
JDK1.5又新增了枚举类型。
2.定义枚举类型
定义枚举类型需要使用enum关键字,例如:
/**
* @Description l枚举
*/
public enum Direction {
FRONT, BEHIND, LEFT, RIGHT;
}
说明:
注意,每个枚举选项之间是用逗号隔开的。如果枚举类没有构造器、方法等,在最后一个枚举选择后面可以不打分号。但是如果枚举类还有其他成员,那么就要在最后一个枚举项后面添加分号了。
Direction类型只有四个选项,你可以理解为这个枚举类只有四个实例对象一样
。外界无法去创建新的枚举对象,只能从这四个中去选择。
其实大多数时候,我们使用枚举类型还是与以及使用int或String表示的枚举一样,基本上都是很简单的。
- 1,定义枚举类——关键字 enum (地位与class、interface相同)。
- 2,枚举类是一个特殊的类,可以有成员变量、方法,实现一个或多个接口,定义自己的构造器。
- 3,一个Java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。
3.枚举与switch
1.5开始枚举类型可以在switch中使用!在1.7之后,String类型也可以放到switch中使用了。
public class Test {
public static void main(String[] args) {
Direction d = Direction.FRONT;
switch (d) {
case FRONT:
System.out.println("前面");
break;
case BEHIND:
System.out.println("后面");
break;
case LEFT:
System.out.println("左面");
break;
case RIGHT:
System.out.println("右面");
break;
default:
System.out.println("错误的方向");
}
Direction d1 = d;
System.out.println(d1);
}
}
注意,在switch中,不能使用枚举类名称,例如:“case Direction.FRONT:”这是错误的,因为编译器会根据switch中d的类型来判定每个枚举类型,在case中必须直接给出与d相同类型的枚举选项,而不能再有类型。
4.枚举与类
4.1. 所有枚举类都是Enum的子类
所有枚举类都默认是Enum
类的子类,无需我们使用extends
来继承。这说明Enum
中的方法所有枚举类都可以的。
- int compareTo(E e):比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序,例如FRONT的下标为0,BEHIND下标为1,那么FRONT小于BEHIND;
- boolean equals(Object o):比较两个枚举常量是否相等;
- int hashCode():返回枚举常量的hashCode;
- String name():返回枚举常量的名字;
- int ordinal():返回枚举常量在枚举类中声明的序号,第一个枚举常量序号为0;
- String toString():把枚举常量转换成字符串;
- static T valueOf(Class enumType, String name):把字符串转换成枚举常量。
4.2. 枚举类的构造器
枚举类也可以有构造器,构造器不能给出访问修饰,而且默认都是private
构造器。因为枚举类的实例不能让外界来创建!
/**
* @author bruceliu
* @Description l枚举
*/
public enum Direction {
//在枚举常量后面必须添加分号,因为在枚举常量后面还有其他成员时,分号是必须的。枚举常量必须在枚举类中所有成员的上方声明。
FRONT, BEHIND, LEFT, RIGHT;
//枚举类的构造器不可以添加访问修饰符,枚举类的构造器默认是private的。但你自己不能添加private来修饰构造器。
Direction(){
System.out.println("hello");
}
}
4.3. 枚举类的方法
再次强调,枚举类也是类,也可以有构造器、方法和属性,只是对构造器有一些限制而已。在语法上有一些怪异罢了!
/**
* @Description l枚举
*/
public enum Direction {
// 在枚举常量后面必须添加分号,因为在枚举常量后面还有其他成员时,分号是必须的。枚举常量必须在枚举类中所有成员的上方声明。
FRONT, BEHIND, LEFT, RIGHT;
// 枚举类的构造器不可以添加访问修饰符,枚举类的构造器默认是private的。但你自己不能添加private来修饰构造器。
Direction() {
System.out.println("hello");
}
//给枚举类添加方法
public void fun() {
System.out.println("hello Enum!");
}
}
4.4. 枚举类的属性
枚举类也可以有属性。但是,如果每个枚举常量的属性值如果都相同,那就失去了意义,我们需要让每个枚举常量的属性值不同,那么就需要自己使用构造器来创建枚举常量,然后在构造器中给每个枚举常量传递不同的值。
public enum Direction {
FRONT("前面"), BEHIND("后面"), LEFT("左面"), RIGHT("右面");
Direction() {
System.out.println("hello");
}
// 给本类添加一个实例属性prop
//为本类设置一个有参构造器,本类只有这一个构造器,那么说明在声明枚举常量时必须调用本构造器。每个常量都会传递一个字符串给自己的explain属性。
private String prop;
Direction(String prop) {
this.prop = prop;
}
public String getProp() {
return prop;
}
public void setProp(String prop) {
this.prop = prop;
}
// 给枚举类添加方法
public void fun() {
System.out.println("hello Enum!");
}
}
使用
public class Test {
public static void main(String[] args) {
System.out.println(Direction.BEHIND.getProp());
}
}
4.5 使用匿名类来创建枚举常量
还可以使用匿名类来创建枚举常量,这说明枚举常量的类型是当前枚举类的子类,而且是个匿名类。但是我们知道就算给匿名类添加了自己独有的方法,也是无法调用的,因为匿名类没有名字,只能使用父类的引用指向匿名类的实例,而多态之后只能调用父类中存在的方法。所以,使用这种情况时,通常是为了让每个枚举常量重写当前枚举类中的方法(抽象方法)。
匿名类的方法来重写父类的方法。这时每个枚举常量的真实类型都是Direction的子类类型了!而且重写了fun()方法。
/**
* @Description
*/
public enum Direction {
FRONT() {
public void fun() {
System.out.println("FROND:重写了fun()方法");
}
},
BEHIND() {
public void fun() {
System.out.println("BEHIND:重写了fun()方法");
}
},
LEFT() {
public void fun() {
System.out.println("LEFT:重写了fun()方法");
}
},
RIGHT() {
public void fun() {
System.out.println("RIGHT:重写了fun()方法");
}
};
public void fun() {
System.out.println("没有意义的方法");
}
}
- 使用:
//调用枚举常量的方法!
Direction.FRONT.fun();
Direction.BEHIND.fun();
Direction.LEFT.fun();
Direction.RIGHT.fun();
通常fun()方法应该定义为抽象的方法,因为每个枚举常量都会去重写它。
你无法把Direction声明为抽象类,但需要声明fun()方法为抽象方法。
/**
* @Description
*/
public enum Direction {
FRONT() {
public void fun() {
System.out.println("FROND:重写了fun()方法");
}
},
BEHIND() {
public void fun() {
System.out.println("BEHIND:重写了fun()方法");
}
},
LEFT() {
public void fun() {
System.out.println("LEFT:重写了fun()方法");
}
},
RIGHT() {
public void fun() {
System.out.println("RIGHT:重写了fun()方法");
}
};
//如果在Direction类中没有fun()方法,这个类也不会有编译的问题,但是每个常量都是匿名类类型,我们是无法调用匿名类独有的方法的。
//只需要把fun()方法修改为抽象方法,但不可以把Direction类声明为抽象类
public abstract void fun();
}
5.使用匿名类来创建枚举常量
5.1.枚举也是编译期状态
其实枚举也是编译期状态,在运行时JVM并不知道什么是枚举类型。这也就是说,编译器需要把枚举类型转换成普通类。
public enum Direction {
FRONT, BEHIND, LEFT, RIGHT;
}