Java枚举,也称为Java枚举类型,是一种类型,其字段由一组固定的常量组成。枚举的目的是强制编译时类型安全。enum关键字是Java中的保留关键字。
当我们在编译时或设计时知道变量的所有可能值时,我们应该使用枚举,尽管我们可以在将来识别它们时添加更多值。在这个enum教程中,我们将了解枚举是什么以及它们解决了哪些问题?
目录
1.什么是Java中的
枚举2.枚举构造函数
3.枚举方法
4.枚举继承
5.比较枚举
6. EnumMap和EnumSet
7.总结
1. Java中的枚举
枚举(通常)通常是一组相关的常量。他们从一开始就使用其他编程语言,比如C ++。在JDK 1.4之后,Java设计者也决定在Java中支持它,它在JDK 1.5版本中正式发布。
关键字支持Java中的枚举enum
。枚举是一种特殊类型的类,它总是扩展java.lang.Enum。
1.1。enum是保留关键字
enum
在Java中是保留关键字。这意味着您无法定义名称变量enum
。例如,它将导致编译时错误"invalid VariableDeclaratorId"
。

enum是保留关键字
1.2。Java枚举声明
创建枚举的简单示例。众所周知,我们通常会处理日常生活中的四个方向。他们的名字,角度和其他属性是固定的。因此,在程序中,我们可以为它们创建枚举。创建枚举的语法如下:
Direction.java
public enum Direction { EAST, WEST, NORTH, SOUTH; } |
从逻辑上讲,每个枚举都是枚举类型本身的一个实例。所以给定枚举可以看作如下声明。JVM在内部为这个类添加了序数和值方法,我们可以在使用enum时调用它们。
Direction.java
final class Direction extends Enum<Direction> { public final static Direction EAST = new Direction(); public final static Direction WEST = new Direction(); public final static Direction NORTH = new Direction(); public final static Direction SOUTH = new Direction(); } |
1.3。Java枚举示例
我们可以像使用final
static
类字段一样使用枚举。
EnumExample.java
public class EnumExample { public static void main(String[] args) { Direction north = Direction.NORTH; System.out.println(north); //Prints NORTH } } |
1.4。enum序数()
该ordinal()
方法返回枚举实例的顺序。它表示枚举声明中的序列,其中初始常量的序数为'0'
。它非常像数组索引。
它设计用于复杂的基于枚举的数据结构,例如EnumSet
和EnumMap
。
enum序数
Direction.EAST.ordinal(); //0 Direction.NORTH.ordinal(); //2 |
1.5。枚举值()和valueOf()
该枚举值()方法在返回所有枚举值枚举阵列。
枚举值()
Direction[] directions = Direction.values(); for (Direction d : directions) { System.out.println(d); } //Output: EAST WEST NORTH SOUTH |
该枚举的valueOf()方法有助于字符串转换为枚举实例。
枚举valueOf()
Direction east = Direction.valueOf( "EAST" ); System.out.println(east); //Output: EAST |
1.6。枚举命名约定
按照惯例,枚举是常量。在Java中,常量以所有UPPER_CASE字母定义。以下是枚举。
- 枚举名称应该是标题大小写(与类名相同)。
- 枚举字段应该在所有大写字母中(与静态最终常量相同)。
2.枚举构造函数
默认情况下,枚举不需要构造函数定义,它们的默认值始终是声明中使用的字符串。但是,您可以定义自己的构造函数来初始化枚举类型的状态。
例如,我们可以angle
向方向添加属性。所有方向都有一定的角度。所以让我们添加它们。
枚举与构造函数
public enum Direction { // enum fields EAST( 0 ), WEST( 180 ), NORTH( 90 ), SOUTH( 270 ); // constructor private Direction( final int angle) { this .angle = angle; } // internal state private int angle; public int getAngle() { return angle; } } |
如果我们想要访问任何方向的角度,我们可以在枚举字段引用中进行简单的方法调用。
EnumExample.java
Direction north = Direction.NORTH; System.out.println( north ); //NORTH System.out.println( north.getAngle() ); //90 System.out.println( Direction.NORTH.getAngle() ); //90 |
3.枚举方法
请记住,枚举基本上是一种特殊的类类型,并且可以像任何其他类一样拥有方法和字段。您可以添加哪些方法是抽象和具体方法为好。枚举中允许使用这两种方法。
3.1。枚举中的具体方法
在枚举中添加具体方法类似于在任何其他类中添加相同方法。您可以使用任何访问说明符,例如public
,private
或protected
。您可以从枚举方法返回值,或者只是使用它们来执行内部逻辑。
枚举 - 非抽象方法
public enum Direction { // enum fields EAST, WEST, NORTH, SOUTH; protected String printDirection() { String message = "You are moving in " + this + " direction" ; System.out.println( message ); return message; } } |
您可以printDirection()
在enum实例上调用方法作为简单方法调用。
EnumExample.java
Direction.NORTH.printDirection(); //You are moving in NORTH direction Direction.EAST.printDirection(); //You are moving in EAST direction |
3.2。枚举中的抽象方法
我们可以在枚举中添加抽象方法。在这种情况下,我们必须分别在每个枚举字段中实现抽象方法。
public enum Direction { // enum fields EAST { @Override public String printDirection() { String message = "You are moving in east. You will face sun in morning time." ; return message; } }, WEST { @Override public String printDirection() { String message = "You are moving in west. You will face sun in evening time." ; return message; } }, NORTH { @Override public String printDirection() { String message = "You are moving in north. You will face head in daytime." ; return message; } }, SOUTH { @Override public String printDirection() { String message = "You are moving in south. Sea ahead." ; return message; } }; public abstract String printDirection(); } |
重新运行上面的例子。
EnumExample.java
Direction.NORTH.printDirection(); //You are moving in north. You will face head in daytime. Direction.EAST.printDirection(); //You are moving in east. You will face sun in morning time. |
您可以通过这种方式强制创建所有枚举的合同。它可以作为枚举创建的模板。
例如,如果我们希望每个枚举类型Direction
都能够在需要时使用自定义消息打印方向名称。这可以通过abstract
在内部定义一个方法来完成Direction
,每个枚举都必须覆盖它。将来,在添加的任何方向(真的吗?),我们也必须添加自定义消息。
4.枚举继承
如前所述,枚举扩展了Enum类。java.lang.Enum
是一个抽象类。这是所有Java枚举类型的公共基类。
java.lang.Enum.java
public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable { } |
这意味着所有枚举都是可比较的,并且可以隐式序列化。此外,Java中的所有枚举类型都是默认的单例。
如前所述,所有枚举都会扩展java.lang.Enum
,因此枚举不能扩展任何其他类,因为Java不支持这种方式的多重继承。但是枚举可以实现任意数量的接口。
5.比较枚举
默认情况下,所有枚举都是可比较的和单身人士。这意味着您可以将它们与equals()
方法进行比较,即使是与"=="
操作员进
EnumExample.java
Direction east = Direction.EAST; Direction eastNew = Direction.valueOf( "EAST" ); System.out.println( east == eastNew ); //true System.out.println( east.equals( eastNew ) ); //true |
您可以使用运算符或方法比较枚举类型,因为枚举是singlton并且默认情况下是可比较的。'=='
equals()
6.枚举集合 - EnumSet和EnumMap
为了java.util
支持枚举而添加了两个类- EnumSet
(枚举的高性能Set实现;枚举集的所有成员必须具有相同的枚举类型)和EnumMap
(用于枚举键的高性能Map实现) 。
6.1。java.util.EnumSet中
EnumSet类定义如下:
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, Serializable { } |
Set
与枚举类型一起使用的专用实现。枚举集中的所有元素必须来自单个枚举类型,该类型在创建集时显式或隐式指定。
6.1.1。EnumSet示例
public class Test { public static void main(String[] args) { Set enumSet = EnumSet.of( Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH ); } } |
像大多数集合实现EnumSet
不同步。如果多个线程同时访问枚举集,并且至少有一个线程修改了该集,则应该在外部进行同步。
null
元素是不允许的。此外,这些集合保证了集合中元素的顺序,这是基于它们在枚举常量中的顺序被声明的。与常规集实现相比,性能和内存优势非常高。
6.2。java.util.EnumMap中
EnumMap声明为:
public class EnumMap<K extends Enum<K>,V> extends AbstractMap<K,V> implements Serializable, Cloneable { } |
Map
与枚举类型键一起使用的专用实现。此外,枚举映射中的所有键必须来自创建映射时显式或隐式指定的单个枚举类型。
比如EnumSet
,null
密钥是不允许的,也不是同步的。
6.2.1。EnumMap示例
public class Test { public static void main(String[] args) { //Keys can be only of type Direction Map enumMap = new EnumMap(Direction. class ); //Populate the Map enumMap.put(Direction.EAST, Direction.EAST.getAngle()); enumMap.put(Direction.WEST, Direction.WEST.getAngle()); enumMap.put(Direction.NORTH, Direction.NORTH.getAngle()); enumMap.put(Direction.SOUTH, Direction.SOUTH.getAngle()); } } |
7.总结
- 枚举是隐式的类的最终子
java.lang.Enum
类 - 如果一个枚举是一个类的成员,那就是隐含的
static
new
关键字不能用于初始化枚举,即使在枚举类型本身内也是如此name()
和valueOf()
方法只是使用枚举常量的文本,而toString()
如果需要,可以重写方法以提供任何内容- 对于枚举常量,
equals()
并"=="
评估相同的结果,并可以互换使用 - 枚举常量是隐含的
public static final
- 该枚举常数的列表的出现顺序被称为其“ 自然顺序 “,并且定义使用的其它项目以及顺序:
compareTo()
方法,迭代顺序中的值EnumSet
,EnumSet.range()
。 - 枚举构造函数应声明为
private
。编译器允许非私有构造函数,但这似乎对读者有误导性,因为new永远不能与枚举类型一起使用。 - 由于这些枚举实例都是有效的单例,因此可以使用identity(
"=="
)比较它们的相等性。 - 你可以在switch语句中使用enum,比如int或char原始数据类型
在本文中,我们探讨了从语言基础知识到更高级和有趣的实际用例的Java枚举。