Java enum深入解释

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是保留关键字

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'。它非常像数组索引

它设计用于复杂的基于枚举的数据结构,例如EnumSetEnumMap

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。枚举中的具体方法

在枚举中添加具体方法类似于在任何其他类中添加相同方法。您可以使用任何访问说明符,例如publicprivateprotected。您可以从枚举方法返回值,或者只是使用它们来执行内部逻辑。

枚举 - 非抽象方法

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与枚举类型键一起使用的专用实现。此外,枚举映射中的所有键必须来自创建映射时显式或隐式指定的单个枚举类型。

比如EnumSetnull密钥是不允许的,也不同步的

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.总结

  1. 枚举是隐式的最终子java.lang.Enum
  2. 如果一个枚举是一个类的成员,那就是隐含的 static
  3. new 关键字不能用于初始化枚举,即使在枚举类型本身内也是如此
  4. name()valueOf()方法只是使用枚举常量的文本,而toString()如果需要,可以重写方法以提供任何内容
  5. 对于枚举常量equals()"=="评估相同的结果,并可以互换使用
  6. 枚举常量是隐含的 public static final
  7. 枚举常数的列表的出现顺序被称为其“ 自然顺序 “,并且定义使用的其它项目以及顺序:compareTo()方法,迭代顺序中的值EnumSetEnumSet.range()
  8. 枚举构造函数应声明为private。编译器允许非私有构造函数,但这似乎对读者有误导性,因为new永远不能与枚举类型一起使用。
  9. 由于这些枚举实例都是有效的单例,因此可以使用identity("==")比较它们的相等性。
  10. 你可以在switch语句中使用enum,比如int或char原始数据类型

在本文中,我们探讨了从语言基础知识到更高级和有趣的实际用例的Java枚举。

猜你喜欢

转载自blog.csdn.net/u010675669/article/details/86673157