首页 > 其他分享 >枚举

枚举

时间:2024-08-07 15:10:29浏览次数:8  
标签:enum EnumSet priority ThreadStatesEnum 枚举 public

枚举

枚举(Enum)是Java中一种特殊的数据类型,它允许程序员定义一个有限的、可枚举的数据集。枚举类型提供了一种更强大、更安全和更易读的方式来表示一组相关的常量。以下是关于Java中枚举的详细解释:

一、枚举的定义

在Java中,枚举类型是通过使用enum关键字来定义的。枚举类型的定义通常在类的内部,但也可以在类的外部定义并使用。枚举类型可以包含一个或多个枚举常量,每个常量都是枚举类型的实例。例如:

public enum Color {  
    RED, GREEN, BLUE;  
}

这个例子中,Color是一个枚举类型,它包含了三个枚举常量:REDGREENBLUE

二.声明枚举

声明枚举时必须使用 enum 关键字,然后定义枚举的名称、可访问性、基础类型和成员等。枚举声明的语法如下:

enum-modifiers enum enumname:enum-base
{
    enum-body,
}

其中,enum-modifiers 表示枚举的修饰符主要包括 public、private 和 internal;enumname 表示声明的枚举名称;enum-base 表示基础类型;enum-body 表示枚举的成员,它是枚举类型的命名常数。

任意两个枚举成员不能具有相同的名称,且它的常数值必须在该枚举的基础类型的范围之内,多个枚举成员之间使用逗号分隔。

提示:如果没有显式地声明基础类型的枚举,那么意味着它所对应的基础类型是 int。

例 1

下面代码定义了一个表示性别的枚举类型 SexEnum 和一个表示颜色的枚举类型 Color。

1. public enum SexEnum
2. {
3. male,female;
4. }
5. public enum Color
6. {
7. RED,BLUE,GREEN,BLACK;
8. }

之后便可以通过枚举类型名直接引用常量,如 SexEnum.male、Color.RED。

使用枚举还可以使 switch 语句的可读性更强,例如以下示例代码:

 1. enum Signal
2. {
3. //定义一个枚举类型
4. GREEN,YELLOW,RED
5. }
6. public class TrafficLight
7. {
8. Signal color=Signal.RED;
9. public void change()
10. {
11. switch(color)
12. {
13. case RED:
14. color=Signal.GREEN;
15. break;
16. case YELLOW:
17. color=Signal.RED;
18. break;
19. case GREEN:
20. color=Signal.YELLOW;
21. break;
22. }
23. }
24. }

三.枚举类

EnumMap基本用法

public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
    implements java.io.Serializable, Cloneable

从上述定义可以看出,EnumMap的Key,必须事Enum 类型,而Value可以是任意类型。看下边初始化格式:

EnumMap<Color, String> enumMap = new EnumMap<Color, String>(Color.class);

实例如下:

import java.util.EnumMap;
import java.util.Iterator;
import java.util.Map.Entry;
 
public class EnumTest {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        EnumMap<Color, String> enumMap=new EnumMap<>(Color.class);
        enumMap.put(Color.BLANK, "黑夜就是我的面纱");
        enumMap.put(Color.GREEN, "我就给你绿帽子");
        enumMap.put(Color.RED, "红旗我的样子");
        enumMap.put(Color.BLANK, "黑夜没月亮");
        Iterator<Entry<Color, String>> iterator=enumMap.entrySet().iterator();
        while(iterator.hasNext())
        {
            System.out.println(iterator.next());
        }
    }
 }

运行结果:

RED=红旗我的样子
GREEN=我就给你绿帽子
BLANK=黑夜没月亮

从实例我们发现,可以通过这种方式给枚举赋上特殊的值。

EnumSet基本用法

  • EnumSet 是一个与枚举类型一起使用的专用 Set 实现。枚举set中所有元素都必须来自单个枚举类型(即必须是同类型,且该类型是Enum的子类)。枚举类型在创建 set 时显式或隐式地指定。枚举 set 在内部表示为位向量。 此表示形式非常紧凑且高效。此类的空间和时间性能应该很好,足以用作传统上基于 int 的“位标志”的替换形式,具有高品质、类型安全的优势。
  • Enumset是个虚类,我们只能通过它提供的静态方法来返回Enumset的实现类的实例。返回EnumSet的两种不同的实现:如果EnumSet大小小于64,就返回RegularEnumSet实例(当然它继承自EnumSet),这个EnumSet实际上至用了一个long来存储这个EnumSet。如果 EnumSet大小大于等于64,则返回JumboEnumSet实例,它使用一个long[]来存储。这样做的好处很明显: 大多数情况下返回的RegularEnumSet效率比JumboEnumSet高很多。
    源码:
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[]universe=getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");
 
        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }

上文说RegularEnumSet方法效率高很多,那为什么呢 ,我们看看RegularEnumSet的源码:
枚举存储:

private long elements = 0L;

add方法:

public boolean add(E e) {
		typeCheck(e);
      
        long oldElements = elements;
        elements |= (1L << ((Enum<?>)e).ordinal());
        return elements != oldElements;
}

细心的读者发现,小于64位时,仅仅是对一个长整型数据进行操作,效率当然要快许多。
我们再看看JumboEnumSet类实现:
枚举值存储:

private long elements[];
 public boolean add(E e) {
        typeCheck(e);
     
        int eOrdinal = e.ordinal();
        int eWordNum = eOrdinal >>> 6;
        long oldElements = elements[eWordNum];
        elements[eWordNum] |= (1L << eOrdinal);
        boolean result = (elements[eWordNum] != oldElements);
        if (result)
            size++;
        return result;
 }

从源码看出,JumboEnumSet使用long数组存储数据,添加操作也是操作数组,效率当然要慢点。
实例:

import java.util.EnumSet;
import java.util.Iterator;
 
public class EnumSetTest {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        EnumSet<Color> enumSet=EnumSet.allOf(Color.class);
        Iterator<Color> iterator=enumSet.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
            
        }
    }
 
}

运行结果:

RED
GREEN
BLANK
YELLO

综合实例(线程状态)

public enum ThreadStates {
    START,
    RUNNING,
    WAITING,
    DEAD;
}
import java.io.Closeable;
import java.io.IOException;
 
/**
 * This Enum example shows all the things we can do with Enum types
 * @author pankaj
 *
 */
public enum ThreadStatesEnum implements Closeable{
    START(1){
        @Override
        public String toString(){
            return "START implementation. Priority="+getPriority();
        }
 
        @Override
        public String getDetail() {
            return "START";
        }
    },
    RUNNING(2){
        @Override
        public String getDetail() {
            return "RUNNING";
        }
    },
    WAITING(3){
        @Override
        public String getDetail() {
            return "WAITING";
        }
    },
    DEAD(4){
        @Override
        public String getDetail() {
            return "DEAD";
        }
    };
    
    private int priority;
    
    public abstract String getDetail();
    //Enum constructors should always be private.
    private ThreadStatesEnum(int i){
        priority = i;
    }
    
    //Enum can have methods
    public int getPriority(){
        return this.priority;
    }
    
    public void setPriority(int p){
        this.priority = p;
    }
    
    //Enum can override functions
    @Override
    public String toString(){
        return "Default ThreadStatesConstructors implementation. Priority="+getPriority();
    }
 
    @Override
    public void close() throws IOException {
        System.out.println("Close of Enum");
    }
}

测试端:

import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;
 
public class JavaEnumExamples {
 
    public static void main(String[] args) throws IOException {
                
        usingEnumMethods();
        
        usingEnumValueOf();
        
        usingEnumValues();
        
        usingEnumInSwitch(ThreadStatesEnum.START);
        usingEnumInSwitch(ThreadStatesEnum.DEAD);
        
        usingEnumMap();
        
        usingEnumSet();
        
    }
 
    private static void usingEnumSet() {
        EnumSet<ThreadStatesEnum> enumSet = EnumSet.allOf(ThreadStatesEnum.class);
        for(ThreadStatesEnum tsenum : enumSet){
            System.out.println("Using EnumSet, priority = "+tsenum.getPriority());
        }
    }
 
    private static void usingEnumMap() {
        EnumMap<ThreadStates, String> enumMap = new EnumMap<ThreadStates,String>(ThreadStates.class);
        enumMap.put(ThreadStates.START, "Thread is started");
        enumMap.put(ThreadStates.RUNNING, "Thread is running");
        enumMap.put(ThreadStates.WAITING, "Thread is waiting");
        enumMap.put(ThreadStates.DEAD, "Thread is dead");
        
        Set<ThreadStates> keySet = enumMap.keySet();
        for(ThreadStates key : keySet){
            System.out.println("key="+key.toString()+":: value="+enumMap.get(key));
        }
        
    }
 
    private static void usingEnumInSwitch(ThreadStatesEnum th) {
        switch (th){
        case START:
            System.out.println("START thread");
            break;
        case WAITING:
            System.out.println("WAITING thread");
            break;
        case RUNNING:
            System.out.println("RUNNING thread");
            break;
        case DEAD:
            System.out.println("DEAD thread");
        }
    }
 
    private static void usingEnumValues() {
        ThreadStatesEnum[] thArray = ThreadStatesEnum.values();
        
        for(ThreadStatesEnum th : thArray){
            System.out.println(th.toString() + "::priority="+th.getPriority());
        }
    }
 
    private static void usingEnumValueOf() {
        ThreadStatesEnum th = Enum.valueOf(ThreadStatesEnum.class, "START");
        System.out.println("th priority="+th.getPriority());
    }
 
    private static void usingEnumMethods() throws IOException {
        ThreadStatesEnum thc = ThreadStatesEnum.DEAD;
        System.out.println("priority is:"+thc.getPriority());
        
        thc = ThreadStatesEnum.DEAD;
        System.out.println("Using overriden method."+thc.toString());
        
        thc = ThreadStatesEnum.START;
        System.out.println("Using overriden method."+thc.toString());
        thc.setPriority(10);
        System.out.println("Enum Constant variable changed priority value="+thc.getPriority());
        thc.close();
    }
 
}

运行结果:

priority is:4
Using overriden method.Default ThreadStatesConstructors implementation. Priority=4
Using overriden method.START implementation. Priority=1
Enum Constant variable changed priority value=10
Close of Enum
th priority=10
START implementation. Priority=10::priority=10
Default ThreadStatesConstructors implementation. Priority=2::priority=2
Default ThreadStatesConstructors implementation. Priority=3::priority=3
Default ThreadStatesConstructors implementation. Priority=4::priority=4
START thread
DEAD thread
key=START:: value=Thread is started
key=RUNNING:: value=Thread is running
key=WAITING:: value=Thread is waiting
key=DEAD:: value=Thread is dead
Using EnumSet, priority = 10
Using EnumSet, priority = 2
Using EnumSet, priority = 3
Using EnumSet, priority = 4

四.枚举的使用场景

枚举类型非常适合用于表示一组固定的常量集合,当一个变量有几种固定可能的取值时,就可以将它定义为枚举类型。例如:

  • 季节(春、夏、秋、冬)
  • 星期几(星期一至星期日)
  • 颜色(红、绿、蓝等)
  • 指令集(在状态机或命令模式中使用)

标签:enum,EnumSet,priority,ThreadStatesEnum,枚举,public
From: https://www.cnblogs.com/yhy373286277/p/18347054

相关文章

  • 枚举
    枚举1.枚举的定义Java中的枚举(Enumeration)是一种特殊的数据类型,用于定义一组有限的命名常量。枚举提供了一种更直观、更可读的方式来表示一组相关的常量,并且可以为这些常量绑定其他数据或行为。枚举是在JDK1.5(Java5)以后引入的,它是对之前使用常量(如publicstaticfinal变量)表示......
  • 枚举声明
    枚举Java枚举知识点概念enum的全称为enumeration,是JDK1.5中引入的新特性。在Java中,被enum关键字修饰的类型就是枚举类型。形式如下:enumColor{RED,GREEN,BLUE}如果枚举不添加任何方法,枚举值默认为从0开始的有序数值。以Color枚举类型举例,它的枚举常量依......
  • C语言day11(string函数族、递归函数、结构体、共用体、枚举)
    【1】string函数族1.strlen头文件:#include<string.h>格式:size_tstrlen(constchar*s);功能:计算字符串实际长度,不包括\0参数:s:目标字符串首地址返回值:字符串实际长度2.strcpy    头文件:#include<string.h>    格式:char*strcpy(char*dest,......
  • 可用于机器学习的排列组合枚举算法含passcal - c shap-c源码
    可用于机器学习的排列组合枚举算法含passcal-cshap-c源码1机器学习和数据挖掘• 特征选择:在机器学习中,需要从多个特征中选择最有价值的组合。通过枚举不同的特征组合,可以找到最佳的特征集合。• 超参数优化:在训练模型时,需要调整多个超参数。通过枚举不同的超参数组......
  • C自定义类型(结构体,联合体,枚举)详解
            在C语言中,数据类型可以分为内置类型(charshortintlongfloatdouble...)和自定义类型。内置类型是由编程语言本身定义的基本数据类型,而自定义类型是由程序员根据需要创建的数据类型。    自定义类型:  结构体,联合体(共用体),枚举。结构体:用于组......
  • 枚举
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceMR.View{classProgram{enumenXingQi{星期一=1,星期二=2,星期三=3,星期四=4,......
  • java基础6—抽象类、接口、枚举
    1.抽象类1.1简介        由于继承这个显著特点,我们可以将子类设计的更加具体,而父类更加一般化,通用化。父类可以封装不同子类的共同特征或者共同行为。而有的时候,父类中封装的方法无法具体完成子类中需要的逻辑,因此我们可以将此方法设计成抽象方法,即使用关键字abstra......
  • 枚举知识点(完结)
    枚举文章目录枚举枚举定义枚举类的实现枚举类的属性枚举类的创建创建代码常用方法枚举定义Java枚举是一个特殊类,一边表示一组常量,比如一年的4个季节,一年的12个月份,一个星期的七天,方向有东南西北等类的对象只有有限个,确定的性别:男,女枚举类的实现JDK1.5之前需要......
  • 如何定义作为函数的枚举值?
    我遇到一种情况,我需要强制并向用户提供多个选择函数之一的选项,将其作为参数传递给另一个函数:我真的想实现如下所示的功能:|||因此可以执行以下命令:fromenumimportEnum#TrivialFunction1deffunctionA():pass#TrivialFunction2deffunctionB():pass......
  • Atcoder 356 C - Keys 二进制枚举
    原题链接:https://atcoder.jp/contests/abc356/tasks/abc356_c C-Keys:问题陈述您有 N 个编号为1,2,…,N 的密钥。其中一些是真钥匙,其他都是假钥匙。有一扇门,门X,你可以插入任意数量的钥匙。只有插入至少 K 把真钥匙,X门才会打开。你已经对这些钥匙进行了 M 次......