枚举类
枚举的定义
在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。 是一个被命名的整型常数的集合,枚举在日常生活中很常见,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一个枚举。
如何用java语言实现枚举
我们学过java的都知道,java是面向对象的一门语言,巧了世界上还就有一些食物能归纳成的对象能用脚趾头数过来,比如季节,星期,月份等,
为了简单起见,这里以周为例-------作为枚举性质的类的演示;
import java.util.Scanner;
final class Week {
private final String WEEKNAME;//季节名
private final String WEEKDESC;//季节描述
//定义构造方法---外界不能随便修改
private Week(String WEEKNAME, String WEEKDESC) {
this.WEEKNAME = WEEKNAME;
this.WEEKDESC = WEEKDESC;
}
public String getWEEKDESC() {
return WEEKDESC;
}
public static Week getMON() {
return MON;
}
public static Week getTUE() {
return TUE;
}
public static Week getWED() {
return WED;
}
public static Week getTHIR() {
return THIR;
}
public static Week getFRI() {
return FRI;
}
public static Week getSAT() {
return SAT;
}
public static Week getSUN() {
return SUN;
}
//定义实例----周一到周日
private final static Week MON = new Week("周一", "工作日");
private final static Week TUE = new Week("周二", "情人节");
private final static Week WED = new Week("周三", "工作日");
private final static Week THIR = new Week("周四", "工作日");
private final static Week FRI = new Week("周五", "工作日");
private final static Week SAT = new Week("周六", "休息日");
private final static Week SUN = new Week("周日", "休息日");
}
public class meiju {
public static void main(String[] args) {
System.out.println("请输入要查询的信息---");
Scanner sc = new Scanner(System.in);
int choice = sc.nextInt();
switch (choice) {
case 1:
System.out.println(Week.getMON().getWEEKDESC());
break;
case 2:
System.out.println(Week.getTUE().getWEEKDESC());
break;
case 3:
System.out.println(Week.getWED().getWEEKDESC());
break;
case 4:
System.out.println(Week.getTHIR().getWEEKDESC());
break;
case 5:
System.out.println(Week.getFRI().getWEEKDESC());
break;
case 6:
System.out.println(Week.getSAT().getWEEKDESC());
break;
case 7:
System.out.println(Week.getSUN().getWEEKDESC());
default:
System.out.println("九天揽月");
sc.close();
}
}
}
看起来很繁琐是不是,于是在jdk1.5之后就出现了枚举类
把上述代码换成枚举类看看有什么区别吧----
java枚举类的实现
import java.util.Scanner;
enum Week {
//定义实例----周一到周日
MON ("周一", "工作日"),
TUE("周二", "情人节"),
WED ("周三", "工作日"),
THIR("周四", "工作日"),
FRI ("周五", "工作日"),
SAT ("周六", "休息日"),
SUN ("周日", "休息日");
private final String WEEKNAME;//季节名
private final String WEEKDESC;//季节描述
//定义构造方法---外界不能随便修改
private Week(String WEEKNAME, String WEEKDESC) {
this.WEEKNAME = WEEKNAME;
this.WEEKDESC = WEEKDESC;
}
public String getWEEKDESC() {
return WEEKDESC;
}
public static Week getMON() {
return MON;
}
public static Week getTUE() {
return TUE;
}
public static Week getWED() {
return WED;
}
public static Week getTHIR() {
return THIR;
}
public static Week getFRI() {
return FRI;
}
public static Week getSAT() {
return SAT;
}
public static Week getSUN() {
return SUN;
}
}
public class meiju {
public static void main(String[] args) {
System.out.println("请输入要查询的信息---");
Scanner sc = new Scanner(System.in);
int choice = sc.nextInt();
switch (choice) {
case 1:
System.out.println(Week.getMON().getWEEKDESC());
break;
case 2:
System.out.println(Week.getTUE().getWEEKDESC());
break;
case 3:
System.out.println(Week.getWED().getWEEKDESC());
break;
case 4:
System.out.println(Week.getTHIR().getWEEKDESC());
break;
case 5:
System.out.println(Week.getFRI().getWEEKDESC());
break;
case 6:
System.out.println(Week.getSAT().getWEEKDESC());
break;
case 7:
System.out.println(Week.getSUN().getWEEKDESC());
default:
System.out.println("九天揽月");
sc.close();
}
}
}
可以发现将
1,实例化的对象放在了枚举类中的开头;
2,枚举对象不用new的形式而是直接写该对象的构造方法即可;
3,枚举对象之间用逗号隔开,最后一个对象用的是分号;
enum类可以定义有参构造,也可以定义无参构造—这点跟普通类是一样的,只不过是实例化时候会有些区别;
例如–
enum类继承的是Java.lang.enum类
枚举类中的一些其他方法
Week mon = Week.valueOf("MON");//返回当前枚举类的
System.out.println(mon);
Week[] values = Week.values();//获得所有枚举对象,以数组的形式
for (Week w:values
) {
System.out.println(w);
}
实现枚举的其他方式------枚举关键字
package org_chwenyu_learn;
public class Meiju {
enum Week {
Sun. Mon.Tue.Wed.Thu.Fri.Sat }
// 枚举类型语法格式--enum 枚举名{元素 1.元素 2};
// 枚举时一定要将所有元素全部列举。
public static void main(String[] args) {
// 枚举名 对象名= 枚举名.枚举元素
Week c1 = Week.Sat;
switch (c1) {
case Sat: System.out.println("今天周六"); break;
default: { System.out.println("今天上学"); } }
Week[]allWeek=Week.values();//遍历枚举对象
for (Week aWeek:allWeek) { System.out.print(aWeek+"."); }
System.out.println("****************************");
System.out.println(c1.getDeclaringClass());//返回 c1 所在的枚举名
System.out.println(c1.hashcode());//返回枚举常量的哈希码
System.out.println(c1.name());//返回枚举常量的名称(在定义时声明的)
System.out.println(c1.ordinal());//返回枚举常量在枚举声明中的位置.序数从 0 开始
System.out.println(c1.toString());//返回枚举常量的名称。}
Enum 类和 enum 关键字的区别
使用关键字定义枚举,实际上是继承了 Enum 类;
Class Enum<E extends Enum>
java.lang.Enum
在含有main方法中不能点工艺枚举类为public
枚举与接口
既然枚举可以是一个类,那么就可以像普通类那样去实现接口;
package enumTest;
interface DescribeSeason {
void desc();
}
enum WEEKEND implements DescribeSeason {
//定义实例----周一到周日
MON {
@Override
public void desc() {
System.out.println("周一");
}
},
TUE() {
@Override
public void desc() {
System.out.println("周二");
}
},
WED {
@Override
public void desc() {
System.out.println("周三");
}
},
THIR {
@Override
public void desc() {
System.out.println("周四");
}
},
FRI {
@Override
public void desc() {
System.out.println("周五");
}
},
SAT {
@Override
public void desc() {
System.out.println("周六");
}
},
SUN {
@Override
public void desc() {
System.out.println("周日");
}
};
}
注意:
-
枚举类的构造方法是不能用 public 声明的, 因为外部不能够调用枚举的构造方法
-
一旦定义了枚举构造,那么就要使用枚举的构造方法
枚举与接口类集对枚举的支持
EnumMap类
EnumMap的基本信息—
public class EnumMap<K extends Enum,V> extends AbstractMap<K,V>
implements Serializable, Cloneable一个专门Map实现 与枚举类型键一起使用。 枚举映射中的所有密钥必须来自创建映射时明确或隐式指定的单个枚举类型。 枚举地图在内部表示为数组。
1,在实例化EnumMap的时候要指定枚举类型—即导入枚举的类信息
代码演示—
public class MeijuLeiji {
public static void main(String[] args) {
EnumMap<WEEKEND,Integer> we=new EnumMap<WEEKEND, Integer>(WEEKEND.class);//指定枚举类型
we.put(WEEKEND.MON,1);
we.put(WEEKEND.TUE,2);
we.put(WEEKEND.WED,3);
we.put(WEEKEND.THIR,4);
we.put(WEEKEND.FRI,5);
we.put(WEEKEND.SAT,6);
we.put(WEEKEND.SUN,7);
Set<Map.Entry<WEEKEND, Integer>> entries = we.entrySet();
for (Map.Entry e:entries
) {
System.out.println(e.getValue());
}
EnumMap<WEEKEND, Integer> clone = we.clone();//返回该EnumMap的浅拷贝
System.out.println(clone.size());//返回EnumMap类集大小----7
clone.putAll(we);//将另一个类集添加到该类集之中;
System.out.println(clone.size());//返回EnumMap类集大小---因为有重复值,所以大小仍为7
}
}
小结—
1,EnumMap像其他大部分类集一样,不同步,线程非安全.多线程访问的时候要注意在外部进行同步;
2, 如果没有此类对象存在,则应使用Collections.synchronizedMap(java.util.Map<K,
V>)方法“包装”地图。 这最好在创建时完成,以防止意外的不同步访问
Map<EnumKey, V> mapEnum
= Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));
Enumset类
先看图----
Enumset类的基本信息—
public abstract class EnumSet<E extends Enum>
extends AbstractSet implements Cloneable, Serializable
一个专门Set实现与枚举类型一起使用。 枚举集中的所有元素都必须来自创建集合时明确或隐式指定的单个枚举类型。
枚举集在内部表示为位向量。 这种表示非常紧凑和高效。 这个类的空间和时间表现应该足够好,可以将其作为基于传统int的“位标志”的高品质,类型安全的替代品使用 。 即使批量操作(如containsAll和retainAll )也应该很快运行
Enumset是一个抽象类,只能通过子类或者借助方法来实例化;所以会出现上图的错误提示;
public class MeijuLeiji {
public static void main(String[] args) {
//创建一个包含指定元素类型中所有元素的枚举集。
EnumSet<WEEKEND> weekends= EnumSet.allOf(WEEKEND.class);
boolean add = weekends.add(WEEKEND.TUE);
weekends.add(WEEKEND.FRI);
weekends.add(WEEKEND.SUN);//添加元素
System.out.println(weekends.size());//类集大小
EnumSet<WEEKEND> clone = weekends.clone();//克隆类集
clone.remove(WEEKEND.FRI);//移除
System.out.println(clone.spliterator());
//创建一个最初包含指定元素的枚举集。
EnumSet<WEEKEND>weekendEnumSet=EnumSet.of(WEEKEND.MON,WEEKEND.TUE,WEEKEND.THIR);
Iterator<WEEKEND> iterator = weekendEnumSet.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("---------------------------------------------");
//创建与指定枚举集具有相同元素类型的枚举集,最初包含此类型的所有元素,该元素 不包含在指定的集合中。
//通俗的讲就是该方法是剔除weekendEnumSet之后剩下WEEKEND枚举之中所有的
EnumSet<WEEKEND>weekends1=EnumSet.complementOf(weekendEnumSet);
Iterator<WEEKEND> iterator1 = weekends1.iterator();
while(iterator1.hasNext()) {
System.out.println(iterator1.next());
}
}
}
小结—
1,EnumSet像其他大部分类集一样,不同步,线程非安全.多线程访问的时候要注意在外部进行同步;
2, 如果没有此类对象存在,则应使用Collections.synchronizedSet(java.util.Set)方法“包装”地图。 这最好在创建时完成,以防止意外的不同步访问
Set<MyEnum> s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
枚举类主要的应用
1,如果一种数据只有有限的个数,可以用枚举类来指定数据的输入范围-----
例如------性别,登录状态等一些实例对象可数的一些数据;
public enum Gender {
男,女;
}
class Person{
String name;
Gender sex;
public Person(String name, Gender sex) {
this.name = name;
this.sex = sex;
}
public void setName(String name) {
this.name = name;
}
public void setSex(Gender sex) {
this.sex = sex;
}
}
这样在设置性别得时候只能选择两种数据----男,女
2,switch对枚举的支持;
import java.util.Scanner;
import static enumTest.Gender.男;
/**
* @author : Gavin
* @date: 2021/8/24 - 08 - 24 - 11:27
* @Description: enumTest
* @version: 1.0
*/
public class Test {
public static void main(String[] args) {
Person per = new Person("张三", 男);//静态导入
Person per1 = new Person("李二狗", Gender.女);
String sexs = null;
Scanner sc = new Scanner(System.in);
sexs = sc.next();
Gender sex = Gender.valueOf(sexs);
switch (sex) {//switch 对int,short,byte,enum,String类型的支持
case 男:
System.out.println("张三");
break;
case 女:
System.out.println("李二狗");
break;
}
sc.close();
}
}