设计模式前篇——枚举

除了上一篇中的同步相关的知识之外,还有一个知识点——枚举enum,也同样重要。

简单介绍一下枚举类型吧:

枚举是在j5中新出的一种类型,它是一种很特殊的数据类型,我们可以把它看成一种特殊的类。因为它与类相比,多了一些约束,而又比类简洁。

枚举使用

相信枚举的使用大家都不会太陌生,但这里还是写一个简单的例子吧:

public class EnumText {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Day day = Day.MONDAY;
		System.out.println(day);
	}

}

enum Day{
	MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNNDAY
}

下面的Day为我们定义的枚举类型,里面的一共有7个枚举常量分别是MONDAY.........SUNNDAY。

我们在main中创建了一个Day类型,制定为Day中的MONDAY枚举常量,然后sysout打印出来。

结果如下:

MONDAY

这个可以说是枚举里面最简单的使用了,在枚举类型没有产生之前,我们可以通过静态常量的方式实现上述的方法:

class NotEnum {
	public static final int MONDAY = 0;
	public static final int TUESDAY = 1;
	public static final int WEDNESDAY = 2;
	public static final int THURSDAY = 3;
	public static final int FRIDAY = 4;
	public static final int SATURDAY = 5;
	public static final int SUNNDAY = 6;
}

比如我们想要实现一个switch判断功能,那么在没有枚举的情况,可以用上述方法实现。当然用枚举可以实现,而且这么一对比,我们发现枚举的方法貌似更简单吧。


实现原理

现在我们注意上面中的一行代码:

Day day = Day.MONDAY;

我们知道在java中只有类或接口是这种方式声明,我们定义Day是一个枚举类型,它也可以这样声明,是不是说明有一个Day类呢?我们来验证一下:

jibaideMacBook-Pro:Desktop jibai$ ls
EnumText.java
jibaideMacBook-Pro:Desktop jibai$ javac EnumText.java
jibaideMacBook-Pro:Desktop jibai$ ls
Day.class	EnumText.class	EnumText.java
jibaideMacBook-Pro:Desktop jibai$

首先打开命令工具,我们先看一下当前目录下的java文件只有EnumText一个。

接着通过javac编译,我们发现在编译过后除了EnumText.class文件之外,还有一个Day.class文件。这是不是验证了我们之前说过的,可以将Day看做是一个类。

实现原理:我们在使用enum创建了枚举类型,在经过编译之后,会将其转换为一个实实在在的类,该类继承自java.lang.Enum类,且:

  • 类中已经为每个枚举常量创建对应的实例对象。
  • 在类中创建了两个方法:valuesOf和values。
由于没有电脑上没有合适的反编译软件-。+,所以只能用大神的反编译结果了:
//反编译Day.class
final class Day extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Day[] values()
    {
        return (Day[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Day valueOf(String s)
    {
        return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
    }
    //私有构造函数
    private Day(String s, int i)
    {
        super(s, i);
    }
     //前面定义的7种枚举实例
    public static final Day MONDAY;
    public static final Day TUESDAY;
    public static final Day WEDNESDAY;
    public static final Day THURSDAY;
    public static final Day FRIDAY;
    public static final Day SATURDAY;
    public static final Day SUNDAY;
    private static final Day $VALUES[];

    static 
    {    
        //实例化枚举实例
        MONDAY = new Day("MONDAY", 0);
        TUESDAY = new Day("TUESDAY", 1);
        WEDNESDAY = new Day("WEDNESDAY", 2);
        THURSDAY = new Day("THURSDAY", 3);
        FRIDAY = new Day("FRIDAY", 4);
        SATURDAY = new Day("SATURDAY", 5);
        SUNDAY = new Day("SUNDAY", 6);
        $VALUES = (new Day[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

我们把这段反编译的代码分为三部分:从上而下分别是:

  1. 创建的两个方法values和valueOf
  2. 私有化构造方法
  3. 实例创建并在static代码块中初始化。

关于前面两部分等会儿再说,我们先看第三部分:

我们在Day中为每个Day的枚举常量都创建了对应的Day引用,并在static代码块中初始化(static代码块中的代码在类加载阶段完成,所以该过程只会进行一次)。

接着我们创建了两个方法,我们来看一下他们是干什么的:

valueOf是返回对应枚举常量名的Day对象,values是返回所有枚举常量对应的Day对象的数组。


Enum常见方法

上面说到在编译之后生成的Day类是继承自Enum类的,我们来看一下这个类的一些主要方法:

String name(); 返回枚举常量的名称
String toString(); 同上
Class<?> getDeclaringCLass() 返回枚举常量对应的类的class对象
int ordinal(); 返回枚举常量的序数(序数按照声明位置,从0开始)
int compareTo(E o); 与o比较顺序:为负表示小于,0表示相等,为正表示大于

<T extends Enum<T>> T valueOf(Class<T> enumType

,String name )

返回指定名称(name)的枚举常量。

enumType参数表示对应的哪个类


枚举的更多使用

现在我们知道枚举类型经过编译后会产生一个类类型,而且在枚举内的枚举常量都对应一个类的实例。还有两个方法valueOf和values分别用来根据枚举常量名来获取对应的类和获取全部的类的数组。

我们还可以在枚举类型里面添加方法和属性,反正最后编译完了都是类-。+:

public class EnumText {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Day day = Day.MONDAY;
		System.out.println(day);
		day.sysoutTag();
	}

}

enum Day{
	MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNNDAY;
	
	private String TAG = "tag";
	
	public void asd() {
		System.out.println("我是asd");
	}
	public void sysoutTag() {
		System.out.println(TAG);
	}
}
在Day中我们添加了一个字符串tag和两个方法(), 注意一定要将枚举常量写在最上面。


让枚举类实现接口

由于枚举对应的类要继承java.lang,Enum类,所以无法继承其他类,但是可以实现接口。

interface Weather{
	boolean isSunny();
}

enum Day implements Weather{
	
			
	MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNNDAY;
	private String TAG = "tag";
	
	
	public void asd() {
		System.out.println("我是asd");
	}
	public void sysoutTag() {
		System.out.println(TAG);
	}
	@Override
	public boolean isSunny() {
		// TODO Auto-generated method stub
		return false;
	}
}



这只是枚举的一小部分知识,由于笔者不是深入研究这个的,所以只说了一些会用到的知识点。

希望大家多多支持!!!




猜你喜欢

转载自blog.csdn.net/zy_jibai/article/details/80723092