三分钟快速掌握Java中枚举(enum)

作者:WaitingAnd 时间:2023-11-27 09:46:30 

什么是枚举?

枚举是JDK5引入的新特性。在某些情况下,一个类的对象是固定的,就可以定义为枚举。在实际使用中,枚举类型也可以作为一种规范,保障程序参数安全。枚举有以下特点:

  1. Java中枚举和类、接口的级别相同。

  2. 枚举和类一样,都有自己的属性、方法、构造方法,不同点是:枚举的构造方法只能是private修饰,也就无法从外部构造对象。构造方法只在构造枚举值时调用。

  3. 使用enum关键字声明一个枚举类型时,就默认继承自Java中的 java.lang.Enum类,并实现了java.lang.Seriablizablejava.lang.Comparable两个接口。

  4. 所有的枚举值都是 public static final 的,且非抽象的枚举类不能再派生子类。

  5. 枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例。

  6. 判断枚举是否相同时,使用 == 和 equals 是一样的。

下面是 java.lang.Enum类中的 equals()


// 这里是final修饰的,不允许子类重写
public final boolean equals(Object other) {
return this==other;
}

枚举的常用方法

int compareTo(E o)

比较此枚举与指定对象的顺序。在该对象小于、等于或大于指定对象时,分别返回负整数、零或正整数。 枚举常量只能与相同枚举类型的其他枚举常量进行比较。


// Enum 中的源码
public final int compareTo(E o) {
Enum other = (Enum)o;
Enum self = this;
if (self.getClass() != other.getClass() && // optimization
 self.getDeclaringClass() != other.getDeclaringClass())
 throw new ClassCastException();
return self.ordinal - other.ordinal;
}

String name()

返回此枚举实例的名称。

static values()

返回一个包含全部枚举值的数组,可以用来遍历所有枚举值。

String toString()

返回此枚举实例的名称,即枚举值。与 name() 一样。


// Enum 中 name() 和 toString()
public String toString() {
return name;
}
public final String name() {
return name;
}

int ordinal()

返回枚举值在枚举类中的索引值(从0开始),即枚举值在枚举声明中的顺序,这个顺序根据枚举值声明的顺序而定。

<T extends Enum<T>> valueOf()

返回带指定名称的指定枚举类型的枚举常量,名称必须与在此类型中声明枚举常量所用的标识符完全匹配(不允许使用额外的空白字符)。这个方法与toString相对应,因此重写 toString() 方法,一定要重写 valueOf()方法(我们可以重写 toString() 方法,但不能自己重写 valueOf() 方法,当我们重写 toString()方法时,valueOf() 方法会自动重写,不用我们理会。)

枚举的应用

枚举是一种特殊的类型,其用法和普通的类使用非常相似。

代替一组常量


public enum Color {
RED, GREEN, BLANK, YELLOW
}

switch 语句中使用


// JDK1.6 中switch加入了对枚举的支持
enum Signal {
GREEN, YELLOW, RED
}

...
switch (color) {
case RED:
 color = Signal.GREEN;
 break;
}
...

向枚举中添加方法


public enum Color {

RED("红色"), GREEN("绿色"), BLANK("白色"), YELLO("黄色");

// 成员变量
private String name;
// 构造方法
private Color(String name) {
 this.name = name;
}

// get set 方法
public String getName() {
 return name;
}
public void setName(String name) {
 this.name = name;
}

}

实现接口


public interface Behaviour {
void print();
}

public enum Color implements Behaviour{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);

//接口方法
@Override
public void print() {
 System.out.println(this.index+":"+this.name);
}
}

包含抽象方法的枚举类


public enum Operation {

// 用于执行加法运算
PLUS { // 花括号部分其实是一个匿名内部子类

@Override
 public double calculate(double x, double y) {
  return x + y;
 }

},

// 用于执行减法运算
MINUS { // 花括号部分其实是一个匿名内部子类

@Override
 public double calculate(double x, double y) {
  // TODO Auto-generated method stub
  return x - y;
 }

},

// 用于执行乘法运算
TIMES { // 花括号部分其实是一个匿名内部子类

@Override
 public double calculate(double x, double y) {
  return x * y;
 }

},

// 用于执行除法运算
DIVIDE { // 花括号部分其实是一个匿名内部子类

@Override
 public double calculate(double x, double y) {
  return x / y;
 }

};

//为该枚举类定义一个抽象方法,枚举类中所有的枚举值都必须实现这个方法
public abstract double calculate(double x, double y);

}

使用枚举实现单例(单例的最佳实践)

好处:

     1.利用的枚举的特性实现单例

     2.由JVM保证线程安全

     3.序列化和反射攻击已经被枚举解决


public enum Singleton {
INSTANCE;
public Singleton getInstance(){
 // 增加这个方法是让别人明白怎么使用,因为这种实现方式还比较少见。
 return INSTANCE;
}
}

其他关于枚举的使用

EnumSet

range(E from, E to)

从枚举值中获取一段范围的 Set。


for(WeekDayEnum day : EnumSet.range(WeekDayEnum.Mon, WeekDayEnum.Fri)) {
 System.out.println(day);
}

of(E first, E... rest)

创建一个最初包含指定元素的枚举 Set。

noneOf(Class<E> elementType)

创建一个具有指定元素类型的空枚举 Set。

EnumMap

EnumMap(Class<K> keyType)

创建一个具有指定键类型的空枚举Map。


Map<Weather, String> enumMap = new EnumMap<Weather, String>(Weather.class);
enumMap.put(Weather.Sunny, "晴天");
enumMap.put(Weather.Rainy, "雨天");

Android中的枚举

Enum 需要占用较大的内存,如果对内存敏感,请尽量少使用 Enum,换成静态常量。

但是如果不使用枚举,会出现一些安全隐患,所以官方推出了两个注解,可以在编译时期进行类型检查,以此替代枚举。这两个注解分别是:@IntDef 和 @StringDef。位于compile 'com.android.support:support-annotations:+' 。

使用示例

@StringDef的使用与 @IntDef一致,这里以 @IntDef为例。


public interface QRCodeType {

int WECHAT = 0;
int ALIPAY = 1;

@IntDef({WECHAT , ALIPAY })
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@interface Checker {

}

}

public class QRCode {

@QRCodeType.Checker // 定义在属性
private int type;

public void setType(@QRCodeType.Checker int type) { // 定义在参数
 this.type= type;
}

@QRCodeType.Checker // 定义在方法(也就是检查返回值的类型)
public int getType() {
 return type;
}

}

使用建议

开发中使用范围最广的就是利用枚举代替一组静态常量,这种情况可以使用以上注解方式替代。
当枚举还含有其它功能时(如:包含其它定义的方法),则不能替换。

来源:http://www.jianshu.com/p/6b7f715d06f6

标签:java,枚举,enum
0
投稿

猜你喜欢

  • Android可配置透明度的水印

    2021-06-06 14:07:42
  • 深入了解Java中的反射机制(reflect)

    2022-06-22 06:34:18
  • Java使用条件语句和循环结构确定控制流(实例)

    2022-07-04 04:52:35
  • 解决javac不是内部或外部命令,也不是可运行程序的报错问题

    2022-07-13 22:39:25
  • java实现学生选课系统

    2022-11-19 14:58:24
  • 老生常谈Java动态编译(必看篇)

    2022-04-02 14:19:38
  • SpringBoot集成easy-rules规则引擎流程详解

    2022-04-20 11:39:35
  • 详解C#使用AD(Active Directory)验证内网用户名密码

    2023-03-03 23:17:47
  • Springboot Session共享实现原理及代码实例

    2022-12-16 03:29:52
  • Java设计模式之中介者模式

    2022-11-16 22:39:01
  • java1.8安装及环境变量配置教程

    2023-04-29 10:36:49
  • Java性能优化技巧汇总

    2023-01-05 16:26:31
  • 深入理解Spring事务原理

    2022-01-18 04:16:39
  • java利用Socket实现聊天室功能实例

    2022-11-10 01:25:43
  • C#自定义针对URL地址的处理类实例

    2022-09-12 16:54:02
  • Java项目中获取路径的绝对路径问题和相对路径问题

    2023-07-09 13:25:01
  • C#中Web.Config加密与解密的方法

    2022-11-25 05:31:06
  • 详解在idea 中使用Mybatis Generator逆向工程生成代码

    2023-09-09 17:05:24
  • WPF使用DrawingContext实现二维绘图

    2021-06-08 15:04:27
  • Springboot如何获取yml、properties参数

    2021-09-20 17:34:43
  • asp之家 软件编程 m.aspxhome.com