java 枚举的本质_《Java编程的逻辑》笔记22--枚举的本质

11ae9b5f3bcb

枚举的本质.png

概念

所谓枚举,是一种特殊的数据,它的取值是有限的,可以枚举出来的, 比如说一年就是有四季、一周有七天,虽然使用类也可以处理这种数据,但枚举类型更为简洁、安全和方便。

基本用法

定义

public enum Size {

SMALL, MEDIUM, LARGE

}

枚举类型可以定义为一个单独的文件,也可以定义在其他类内部。

使用

Size size = Size.SMALL;

System.out.println(size.toString());

System.out.println(size.name());

输出都是SMALL

Size size = Size.SMALL;

System.out.println(size==Size.SMALL);

System.out.println(size.equals(Size.SMALL));

System.out.println(size==Size.MEDIUM);

分别是true, true, false

Size size = Size.MEDIUM;

System.out.println(size.ordinal());

枚举类型都有一个方法int ordinal(),表示枚举值在声明时的顺序,从0开始

Size size = Size.SMALL;

System.out.println(size.compareTo(Size.MEDIUM));

比较其实就是比较ordinal的大小

static void onChosen(Size size){

switch(size){

case SMALL:

System.out.println("chosen small"); break;

case MEDIUM:

System.out.println("chosen medium"); break;

case LARGE:

System.out.println("chosen large"); break;

}

}

在switch语句内部,枚举值不能带枚举类型前缀,例如,直接使用SMALL,不能使用Size.SMALL

for(Size size : Size.values()){

System.out.println(size);

}

输出为三行,分别是SMALL, MEDIUM, LARGE

枚举的好处

Java是从JDK 5才开始支持枚举的,在此之前,一般是在类中定义静态整形变量来实现类似功能

定义枚举的语法更为简洁。

枚举更为安全,一个枚举类型的变量,它的值要么为null,要么为枚举值之一,不可能为其他值,但使用整形变量,它的值就没有办法强制,值可能就是无效的。

枚举类型自带很多便利方法(如values, valueOf, toString等),易于使用

基本实现原理

枚举类型实际上会被Java编译器转换为一个对应的类,这个类继承了Java API中的java.lang.Enum类

public final class Size extends Enum {

public static final Size SMALL = new Size("SMALL",0);

public static final Size MEDIUM = new Size("MEDIUM",1);

public static final Size LARGE = new Size("LARGE",2);

private static Size[] VALUES =

new Size[]{SMALL,MEDIUM,LARGE};

private Size(String name, int ordinal){

super(name, ordinal);

}

public static Size[] values(){

Size[] values = new Size[VALUES.length];

System.arraycopy(VALUES, 0,

values, 0, VALUES.length);

return values;

}

public static Size valueOf(String name){

return Enum.valueOf(Size.class, name);

}

}

Size是final的,不能被继承,Enum表示父类,是泛型写法,我们后续文章介绍,此处可以忽略。

Size有一个私有的构造方法,接受name和ordinal,传递给父类,私有表示不能在外部创建新的实例。

三个枚举值实际上是三个静态变量,也是final的,不能被修改。

values方法是编译器添加的,内部有一个values数组保持所有枚举值。

valueOf方法调用的是父类的方法,额外传递了参数Size.class,表示类的类型信息,类型信息我们后续文章介绍, 父类实际上是回过头来调用values方法,根据name对比得到对应的枚举值的。

一般枚举变量会被转换为对应的类变量,在switch语句中,枚举值会被转换为其对应的ordinal值。

注意点

当需要id标记时,最好别用ordinal值

高级用法

枚举类型可以声明抽象方法,每个枚举值中可以实现该方法,也可以重写枚举类型的其他方法。

public enum Size {

SMALL {

@Override

public void onChosen() {

System.out.println("chosen small");

}

},MEDIUM {

@Override

public void onChosen() {

System.out.println("chosen medium");

}

},LARGE {

@Override

public void onChosen() {

System.out.println("chosen large");

}

};

public abstract void onChosen();

}

public enum Size {

SMALL {

@Override

public void onChosen() {

System.out.println("chosen small");

}

},MEDIUM {

@Override

public void onChosen() {

System.out.println("chosen medium");

}

},LARGE {

@Override

public void onChosen() {

System.out.println("chosen large");

}

};

public abstract void onChosen();

}

switch的缺陷是,定义swich的代码和定义枚举类型的代码可能不在一起, 如果新增了枚举值,应该需要同样修改switch代码,但可能会忘记,而如果使用抽象方法,则不可能忘记,在定义枚举值的同时,编译器会强迫同时定义相关行为代码。所以,如果行为代码和枚举值是密切相关的,使用以上写法可以更为简洁、安全、容易维护。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值