枚举
枚举是一种特殊的数据,它的取值有限,是可以枚举出来的,比如一周有七天,性别有男女等,虽然定义类也能实现,但是枚举更简洁、安全和方便。
这里先定义最简单一个尺码枚举类来演示:
//这个尺码枚举类里面的每个枚举元素代表尺码的:小小码,小码,中码,大码,加大码
public enum Size {
XSMALL,
SMALL,
MEDIUM,
LARGE,
XLARGE;
}
如果我们想给我们的每个码数加一些具体信息,可以这样改写代码:
/**
* 定义尺码枚举类型
*/
public enum Size { //这里注意不是class 而是 enum
XSMALL("XS","小小码"), //枚举元素里面可以有枚举的自定义值
SMALL("S","小码"), //枚举元素间用逗号 , 分隔开,结尾用 分号 ;
MEDIUM("M","中码"),
LARGE("L","大码"),
XLARGE("XL","加大码");
// 枚举元素里面加了自定义值后,需要声明这些自定义值,以便后续的取值
private String abbr; //的对应XS等代号
private String title; //对应小码等中文代号
//构造方法,给加上枚举类加上英文缩写代号和中文代号
private Size(String abbr, String title) {
this.abbr = abbr;
this.title = title;
}
/**
* 通过XS等代号找对应的枚举码数
*
* @param abbr
* @return
*/
public static Size fromAbbr(String abbr){
for (Size size : Size.values()){ //Size.values() 返回一个Size的所有枚举类型数组
if (size.getAbbr().equals(abbr)){
return size; //遍历找到对于的枚举类型,加入abbr为S,遍历到SMALL就会返回
}
}
return null;
}
//获取自定义值,这里是获取枚举类的缩写代码,如 获取SMALL的缩写代号:S
public String getAbbr() {
return abbr;
}
//同上
public String getTitle() {
return title;
}
}
现在看看具体代码里面怎么使用定义好的枚举类:
public class Test1 {
public static void main(String[] args) {
//获取枚举变量
Size smallSize = Size.SMALL;
System.out.println(smallSize);
//这里的name()是枚举类的默认父类Enum的方法,值为枚举元素的名称
System.out.println(smallSize.name());
//这里的ordinal()是枚举类的默认夫类Enum的方法,获取枚举类的默认值(按枚举的排列顺序从0开始)
System.out.println(smallSize.ordinal());
//遍历枚举类Size
for (Size size : Size.values()){
System.out.print(size + " : ");
//获取具体枚举变量里面的信息
System.out.print("英文缩写:" + size.getAbbr());
//获取具体枚举变量里面的信息
System.out.println(" 中文缩写:" + size.getTitle());
}
}
}
这里总结一下:
枚举的好处:
1、定义枚举的语法更加简洁
2、枚举更加安全,一个枚举型的变量,要么值为null,要么为枚举值之一,不可能为其他值。
3、枚举类型自带很多方便的方法(如values、valueOf、toString)
重点来了!!!!
枚举类实现原理
通过反编译Size.class文件得到以下反编译的代码,其中代码如下:
//Size.class反编译得到的代码
//这里可以看到枚举类最后被编译为一个继承了Enum类的子类,
//这也就解释了为什么我们可以调用Enum的方法了
//因为Java编译器编译枚举类的时候会默认继承Enum类
public final class Size extends Enum
{
public static final Size XSMALL; //最后每个枚举元素都被声明为static final,
public static final Size SMALL; //因此枚举类在后面赋值后也就不能修改了
public static final Size MEDIUM;
public static final Size LARGE;
public static final Size XLARGE;
private String abbr;
private String title;
private static final Size $VALUES[]; //给枚举类默认添加了一个数组,存储了所有枚举元素
static //在静态代码块把枚举元素给实例化出来
{
XSMALL = new Size("XSMALL", 0, "XS", "\u5C0F\u5C0F\u7801");
SMALL = new Size("SMALL", 1, "S", "\u5C0F\u7801");
MEDIUM = new Size("MEDIUM", 2, "M", "\u4E2D\u7801");
LARGE = new Size("LARGE", 3, "L", "\u5927\u7801");
XLARGE = new Size("XLARGE", 4, "XL", "\u52A0\u5927\u7801");
$VALUES = (new Size[] {
XSMALL, SMALL, MEDIUM, LARGE, XLARGE //初始化枚举数组
});
}
public static Size[] values()
{
return (Size[])$VALUES.clone();
}
public static Size valueOf(String s)
{
return (Size)Enum.valueOf(Size, s);
}
private Size(String s, int i, String s1, String s2)
{
super(s, i);
abbr = s1;
title = s2;
}
public static Size fromAbbr(String s)
{
Size asize[] = values();
int i = asize.length;
for(int j = 0; j < i; j++)
{
Size size = asize[j];
if(size.getAbbr().equals(s))
return size;
}
return null;
}
public String getAbbr()
{
return abbr;
}
public String getTitle()
{
return title;
}
}
可见,枚举类可以被编译为“枚举类.class”文件,反编译得到其真实的代码我们可以看到其真实的模样:继承了Enum类的子类。
因此,枚举类型本质上也是类,但由于编译器自动做了很多事情,因此它的使用上很方便、简洁、安全