Java编程思想笔记——第19章枚举类型

1.1  关键字enum可以将一组具名的值的优先级和创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。

1.2  基本enum特性

声明一个enum的基本方法:

enum Shrubbery
{
	GROUND,
	CRAWLING,
	HANGING
}
对这个enum进行遍历:

	for(Shrubbery s : Shrubbery.values())
		{
			System.out.println(s);
			System.out.println(s.ordinal());//得到此枚举在enum实例中声明的次序
		}

1.3 向enum中添加新方法

我们还可以以类的形式声明enum,形如:

public enum Spiciness {
	FIRST,
	SECOND,
	THIRD
}
对于此种enum类来说,除了不能继承自另一个enum类的限制(因为所以的enum都默认继承自Enum,Java中不允许多重继承,所以不能继承)之外,和普通类没有太多区别。在这个类中,你可以编写数组这个类的方法,甚至是main()函数。但是要注意书写的顺序,必须先进行枚举类型的声明,然后再对函数进行声明和定义:

package com.canglingye_19;

public enum WithText {
	//每一个枚举值来说,可以视之为单独的WithText,在后文中,我们将会定义其含参构造函数,
	//“我是第一个”即为传入构造函数的参数,这样做的好处是,我们可以自己为各个枚举值提供描述,使程序清晰易读
	FIRST("我是第一个"),
	SECOND("我是第二个");
	
	private String description;
	
	//构造器为私有访问或者包访问不难理解,因为当我们结束WithText的定义时,我们已经不能够
	//再次想WithText中追加枚举值了,故此构造函数不能为public,只能为private或者包访问权限。
	private WithText(String des)
	{
		this.description = des;
	}
	
	public String getDes()
	{
		return description;
	}
	
	//如果不想自己再重新写构造函数,但是又想使对每一个枚举值有单独的描述,则可以覆盖toString()方法
	public String toString()
	{
		String n = this.name();
		String re = new String("可以根据name的不同创建不同的说明");
		return re;
	}
	
	public static void main(String[] args)
	{
		System.out.println(WithText.FIRST.getDes());
	}
}


1.4  switch语句中的enum

         因为java中的switch只支持int和char,如果没有枚举类型,那么你只能case 1: break; case 2: break;时间长了你可能会混淆每个数字所代表的含义,但是,自从有了枚举类型,你得到的解放。用枚举类来替代每个数字,提高程序的可读性。


1.5  enum类型虽然不能够继承自其它基类,但是可以实现其它接口,诸如:

         

enum ColorGenerator
implements Generator<ColorGenerator>
{
	BLUE,BLACK,WHITE,GREEN,YELLOW,RED;
	private Random rn = new Random(47);
	public ColorGenerator next()
	{
		return this.values()[rn.nextInt(this.values().length)];
	}
}
基于此,当我们要管理比较复杂的接口时,比如一个枚举大类为Food,Food又可以细化分为A,B两种类型,那我们可以用一下这种方式实现此枚举模型:

interface Food
{
	enum A implements Food
	{
		A1,A2,A3,A4
	}
	
	enum B implements Food
	{
		B1,B2,B3,B4
	}
}
在上一段代码中,A和B都实现了接口Food,故都可以向上转型为Food,都属于Food类型。但是如果枚举类型更加复杂,我们可以通过下面这种巧妙的方式再次组织枚举:

enum MatureEnum
{
	TrueA(Food.A.class),
	TrueB(Food.B.class);
	private Food[] con;
	private MatureEnum(Class<? extends Food> kind)
	{
		con = kind.getEnumConstants();
	}
	public Food getnext()
	{
		return con[new Random(47).nextInt(con.length)];
	}
}
这样看起来,代码是否变得更加优雅?整个封装的过程类似于:枚举——接口——枚举


1.6 关于使用EnumSet和EnumMap的技巧

EnumSet属于专门为Enum设计的高效的枚举集合器,其内部默认使用一个long类型作为基础,每一个bit作为一个枚举值,故其可以实现快速的查找等操作。其基本操作如下:

		EnumSet<Food.A> test = EnumSet.noneOf(Food.A.class);
		System.out.println(test);
		test.add(Food.A.A1);
		System.out.println(test);
		test.addAll(EnumSet.of(Food.A.A1,Food.A.A2));
		System.out.println(test);

EnumMap属于专门为Enum设计的高效Map查找集合,其中限制Key必须来自一个enum。其基本用法与Map差不多。

1.7  常量相关的方法

enum Shrubbery
{
	GROUND
	{
		String getInfo()
		{
			return "有趣";
		}
	},
	CRAWLING
	{
		String getInfo()
		{
			return "哈哈";
		}
	},
	HANGING	{
		String getInfo()
		{
			return "可以这样";
		}
	};
	//在这里声明一个abstract方法,然后强制每个枚举值都实现这个方法
	//通过此种方式,可以实现每个枚举值的差异化,当然,通过改写构造函数
	//可以实现类似的效果
	abstract String getInfo();
}
通过定义常量相关方法,可以使每个枚举值变得更具有特色化,当然,也可以通过前文已经介绍的改写构造函数、编写新的函数等方法来实现此种效果。此种方式称之为:表驱动的代码

如果String getInfo()方法不是abstract,而是常量方法,也同样可以覆盖,不过一般来说,推荐使用abstract修饰。

1.8  关于enum实现职责链和状态机的问题,属于设计模式的问题,第二遍学习。

1.9  关于多路分发问题,第二遍学习。


总之,enum枚举类型还是挺有意思的,嘿嘿。


你可能感兴趣的:(Java编程思想笔记——第19章枚举类型)