java笔记--枚举总结与详解
由于工作原因,已经有两礼拜没有更新博客了,好不容易完成了工作项目,终于又可以在博客园上愉快的玩耍了。
嗯,今天下午梳理了一下关于java枚举的笔记,比较长,不过还是觉得挺厚实的,哈哈,有出入的地方,欢迎朋友们指出来,一起学习,共同进步!!
一、枚举简介:
为什么要用枚举:
枚举是Java1.5出来之后新增的类型,它可以用来定义一组取值范围固定的的变量。
在枚举没有出来之前,要定义这样的变量,往往是通过定义一个接口,将不同的变量
使用不同的整数赋值。但是这样的却有着很明显的缺点:
1.不能保证其定义数值的合法性;
2.无法根据数值大小获取其含义。
但是通过枚举这些问题将不再是问题。
--支持知识共享,转载请标注地址"http://www.cnblogs.com/XHJT/p/3945401.html "——和佑博客园,谢谢~~--
枚举特性:
1.Enum类是枚举的一个封装类,,是所有枚举类型的超类,它是一个没有抽象方法的抽象类。
2.通过关键字"enum"可以定义枚举类型;
3.Enum类中定义了很多常用的方法:如元素间的比较,获取元素名称,获取元素定义的次序等:
a.compareTo(E o) : 比较枚举元素的顺序
b.equals(Object obj) : 判断枚举元素是否相同
c. name() : 获取元素定义时的名称
d.ordinal() : 获取枚举元素被定义时的顺序,从0开始计算
注:对于枚举可以使用"=="来比较两个枚举元素相同与否,由于他们已经自动了equals()和hashCode()两个方法,
故这两个方法不需要重写。
枚举的简单运用之创建和调用枚举:
1.枚举类的定义:
public enum Demo{
ENUMTYPEA,ENUMTYPEB,ENUMTYPEC;
}
2.在枚举类中,所有的属性以大写的形式存在,属性之间以逗号隔开,属性的值以括号String类型存在;
3.若是枚举属性有值strName,则需要定义这个strName,并且定义枚举类的有参构造方法,即必须要要先
定义枚举类型description才能定义构造方法Demo(String description);
public enum Demo{
ENUMTYPEA(strName),//枚举类型A,strName==" 枚举类型属性的值";
ENUMTYPEB(strName),//枚举类型B
ENUMTYPEC(strName);//枚举类型C
private String description;
private Demo(String description){
this.descrition = descrition;
}
public String getDescription(){
return description;
}
}
4.枚举类不能被继承,但可看作普通类,可重写方法,可有main方法。
5.枚举类的构造方法可以用public和protected修饰,但只能用来创建枚举对象,不能创建枚举类的实例
代码实例:
无参枚举类:
package com.xhj.Enum; /** * 无参枚举 * * @author XIEHEJUN * */ public enum Color { BLUE, YELLOW, RED, GREEN, WHITE, BRACK, PURPLE }
有参枚举类:
package com.xhj.Enum; /** * 有参枚举 * * @author XIEHEJUN * */ public enum ColorValues { BLUE("蓝色"), YELLOW("黄色"), RED("红色"), GREEN("绿色"), WHITE("白色"), BRACK("黑色"), PURPLE( "紫色"); private String description; private ColorValues(String description) { this.description = description; } public String getDescription() { return description; } }
枚举测试类:
package com.xhj.Enum; /** * 对枚举封装类方法的简单运用 * * @author XIEHEJUN * */ public class Test { /** * 调用无参枚举 */ public static void printColor() { for (Color color : Color.values()) { System.out.println("第" + (color.ordinal() + 1) + "个枚举是:" + color.name()); System.out .println("此枚举和枚举BLUE比较的值为:" + color.compareTo(color.BLUE)); System.out.println("用'equals()方法'判断此枚举是否和枚举BLUE相等为:" + color.equals(color.BLUE)); System.out.println("用'== '的形式判断此枚举是否和枚举BLUE相等为:" + (color == color.BLUE)); System.out.println(color.getDeclaringClass()); System.out .println("========================================================"); } } /** * 调用有参枚举 */ public static void printColorValues() { for (ColorValues colorValues : ColorValues.values()) { System.out.println("第" + (colorValues.ordinal() + 1) + "个枚举是:" + colorValues.name()); System.out.println("此枚举的值为:" + colorValues.getDescription()); System.out.println("此枚举和枚举BLUE比较的值为:" + colorValues.compareTo(colorValues.BLUE)); System.out.println("用'equals()方法'判断此枚举是否和枚举BLUE相等为:" + colorValues.equals(colorValues.BLUE)); System.out.println("用'== '的形式判断此枚举是否和枚举BLUE相等为:" + (colorValues == colorValues.BLUE)); System.out.println(colorValues.getDeclaringClass()); System.out .println("========================================================"); } } public static void main(String[] args) { Test Test.printColor(); System.out .println("***************************************************************\n" +"***************************************************************"); Test.printColorValues(); } }
枚举的简单运用之switch调用枚举:
我们知道在java7(加上了switch可以调用String类型的特性)没有出来之前switch只能调用整数类型变量。
我想很多人可能会说,这个结论不对,因为他还可以调用枚举类型。
是的,没有错,switch确实可以调用枚举类型,但是她能调用的必要前提是调用的类型必须是整数。这个怎么理解呢?
其实,事实上是因为枚举类会自动的为它的每一个元素生成一个整数的顺序编号(可以通过ordinal()方法获知其编号),
所以当我们向switch传入枚举类型时,事实上,传进去的是一个整数--元素的顺序编号。
代码实例:
package com.xhj.Enum; /** * switch枚举类型的调用 * * @author XIEHEJUN * */ public enum UseSwitch { LILEI, LILY, SHITOU; /** * 获取每一个USER的性别 * * @param user * @return */ public static String getGrend(UseSwitch user) { switch (user) { case LILEI: return "我是一名男孩"; case LILY: return "我是一名女孩"; default: return "咦?我是谁呢?"; } } public static void main(String[] args) { for (UseSwitch user : UseSwitch.values()) { System.out.println(user + ":" + user.getGrend(user)); } } }
注:在switch语句中,若是有return返回值,则必须要有default语句:
二、枚举的高效运用:
枚举的高效运用之枚举集合:
Set回顾:
Set是Java集合类中一个很重要的子类,它用来存储不能重复的对象。
枚举和Set对比:
1.枚举也和Set一样要求每一个枚举元素都必须各不相同;
2.Set可以随意对数据进行增删操作,枚举不能。
EnumSet:
1.枚举集合,和Set集合一样,保证每一个元素的唯一性,不可重复性;
2.当创建EnumSet对象时,需要显式或隐士指明元素的枚举类型;
3.此对象中的元素仅能取自同一枚举类
4.在EnumSet内部以"位向量"的形式表示,这种结构紧凑而高效,使得类的时间、控件性能非常优越。
5.常用方法:
allOf(Class<E> elementType): 创建一个EnumSet,它包含了elementType 中所有枚举元素
complementOf(EnumSet<E> s): 创建一个EnumSet,其中的元素是s的补集
noneOf(Class<E> elementType): 创建一个EnumSet,其中的元素的类型是elementType,但是没有元素
range(E from, E to): 创建一个EnumSet,其中的元素在from和to之间,包括端点
add(E e): 增加一个元素e
remove(Object o): 删除一个元素o
addAll(Collection<? extends E>): 增加一个集合元素c
removeAll(Collection<?> c): 删除一集合元素c
注:不能在EnumSet中增加null元素,否则将会抛出空指针异常
代码实例:
package com.xhj.Enum; import java.util.EnumSet; /** * EnumSet的运用 * * @author XIEHEJUN * */ public class EnumSetDemo { /** * 获取元素信息并打印输出 * * @param enumSet */ public static void getElement(EnumSet<ColorValues> enumSet) { StringBuffer strName = new StringBuffer(); for (int j = 0; j < enumSet.size(); j++) { System.out.print("\t" + enumSet.toArray()[j]); for (ColorValues colorValues2 : enumSet) { strName.append("\t" + colorValues2.getDescription() + "\n"); } System.out.println(strName.toString().split("\n")[j]); } } /** * EnumSet方法的具体使用实例 */ public static void getEnumSet() { EnumSet<ColorValues> enumSet1 = EnumSet.allOf(ColorValues.class); System.out.println("enumSet1枚举集合中元素有" + enumSet1.size() + "个"); System.out.println("分别是:"); getElement(enumSet1); System.out .println("=====================添加元素============================"); EnumSet<ColorValues> enumSet2 = EnumSet.noneOf(ColorValues.class); System.out.println("\n此时枚举集合enumSet2中元素有" + enumSet2.size() + "个"); System.out.println("\n向枚举集合enumSet2添加一个元素" + ColorValues.BLUE); enumSet2.add(ColorValues.BLUE); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out.println("\n向枚举集合enumSet2添加一个元素" + ColorValues.RED); enumSet2.add(ColorValues.RED); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out.println("\n向枚举集合enumSet2添加一个元素" + ColorValues.GREEN); enumSet2.add(ColorValues.GREEN); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out.println("\n向枚举集合enumSet2添加ColorValues的补集enumSet3"); EnumSet<ColorValues> enumSet3 = EnumSet.complementOf(enumSet2); getElement(enumSet3); enumSet2.addAll(enumSet3); System.out.println("\n此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out .println("=====================删除元素============================"); System.out.println("\n枚举集合enumSet2删除一个元素" + ColorValues.GREEN); enumSet2.remove(ColorValues.GREEN); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out.println("\n枚举集合enumSet2删除一个固定范围内的元素"); enumSet2.removeAll(enumSet2 .range(ColorValues.YELLOW, ColorValues.WHITE)); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out.println("\n枚举集合enumSet2删除一个枚举集合enumSet3,这个集合的元素个数有:" + enumSet3.size()); enumSet2.removeAll(enumSet3); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); getElement(enumSet2); System.out .println("=====================清除所有元素============================"); enumSet2.clear(); System.out.println("此时枚举集合enumSet2中元素个数有:" + enumSet2.size()); } public static void main(String[] args) { EnumSetDemo.getEnumSet(); } }
枚举的高效运用之枚举映射:
1.对于枚举集合来说,Java除了提供EnumSet外,还提供了另外一个集合类EnumMap
2.Map是Java集合类的子类,主要是通过键值对来保存对象,要求其键必须是唯一的;
3.在枚举类型中,枚举元素也是要求唯一的,固可作为Map的键。
4.EnumMap类是Java专门为枚举类型提供的Map实现类。
5.和EnumSet类一样,当创建EnumMap类型时,要显式或者隐式指明其元素的枚举类型,且只能取自统一枚举类
6.在EunmMap内部,用数组表示
7.常用方法:
clear(): 删除所有映射关系
containKey(Object key): 若包含此key,则返回true,否则返回false
containsValue(Object value): 若包含此value,则返回true,否者返回false
put(K key,V value): 往EnumMap中存入键值对
get(Object key): 获取键为key对应的value值
size(): 查看EnumMap中键值对的个数
remove(Object key): 删除键为key相对应的value值
注:在EunmMap中,不可存入null,否则将抛出空指针异常
代码实例:
package com.xhj.Enum; import java.util.EnumMap; /** * EnumMap的运用 * * @author XIEHEJUN * */ public class EnumMapDemo { /** * EnumMap的具体运用 */ public static void getEnumMap() { EnumMap<ColorValues, String> enumMap1 = new EnumMap<ColorValues, String>( ColorValues.class); String[] Weeks = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天" }; System.out .println("==========================添加枚举键值对================================"); enumMap1.put(ColorValues.BLUE, ColorValues.BLUE.getDescription() + Weeks[ColorValues.BLUE.ordinal()]); System.out.println("key=0时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); enumMap1.put(ColorValues.BRACK, ColorValues.BRACK.getDescription() + Weeks[ColorValues.BRACK.ordinal()]); System.out.println("key=1时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); enumMap1.put(ColorValues.GREEN, ColorValues.GREEN.getDescription() + Weeks[ColorValues.GREEN.ordinal()]); System.out.println("key=2时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); enumMap1.put(ColorValues.PURPLE, ColorValues.PURPLE.getDescription() + Weeks[ColorValues.PURPLE.ordinal()]); System.out.println("key=3时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); enumMap1.put(ColorValues.RED, ColorValues.RED.getDescription() + Weeks[ColorValues.RED.ordinal()]); System.out.println("key=4时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); enumMap1.put(ColorValues.WHITE, ColorValues.WHITE.getDescription() + Weeks[ColorValues.WHITE.ordinal()]); System.out.println("key=5时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); enumMap1.put(ColorValues.YELLOW, ColorValues.YELLOW.getDescription() + Weeks[ColorValues.YELLOW.ordinal()]); System.out.println("key=6时enumMap1的元素有 " + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); System.out .println("==========================判断枚举键值对================================"); System.out.println("判断是否存在键" + ColorValues.BLUE); System.out.println("结果为:" + enumMap1.containsKey(ColorValues.BLUE)); System.out.println("判断是否存在值'蓝色星期二'"); System.out.println("结果为:" + enumMap1.containsValue("蓝色星期二")); System.out .println("==========================删除枚举键值对================================"); enumMap1.remove(ColorValues.BLUE); System.out.println("剩余元素有:" + enumMap1); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); System.out .println("==========================获取键对应的值================================"); System.out.println(" 获取RED对应的值,结果为: " + enumMap1.get(ColorValues.RED)); System.out .println("==========================清空枚举键值对================================"); enumMap1.clear(); System.out.println(" 此时键值对个数为: " + enumMap1.size() + "\n"); } public static void main(String[] args) { getEnumMap(); } }
注:EnumMap可以用来实现23种设计模式中的命令模式(对于设计模式,后续会有详细的笔记)
枚举的高效运用之遍历枚举接口元素:
1.集合类的主要作用就是用来管理一组相关的对象,当需要查看、使用集合中的所有对象时可以使用枚举接口对其进行遍历。
2.实现了Enumeration接口的对象可以生成一系列元素,每次生成一个。
3.通过连续调用nextElement()方法可以连续获得枚举接口中的元素。但若枚举接口已没有元素,调用该方法会抛出异常。
故在这之前要先用hasMoreElement()进行判断:
boolean hasMoreElements()
4.Collection类的静态方法enumeration()可以用来将任意集合转换成枚举接口类型。
代码实例:
1.利用SequenceInputStream方法合并文件
package com.xhj.Enum; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Vector; /** * 利用SequenceInputStream方法合并文件 * * @author XIEHEJUN * */ public class MergeFiles { public static void main(String[] args) { String uri1 = "src/com/xhj/Enum/file1.txt"; String uri2 = "src/com/xhj/Enum/file2.txt"; String uri3 = "src/com/xhj/Enum/file3.txt"; List<InputStream> v = new ArrayList<InputStream>(); SequenceInputStream sis = null; OutputStream os = null; try { v.add(new FileInputStream(uri1)); v.add(new FileInputStream(uri2)); Enumeration<InputStream> e = Collections.enumeration(v); sis = new SequenceInputStream(e); os = new FileOutputStream(new File(uri3)); int len = 0; byte[] bu = new byte[1024]; while ((len = sis.read(bu)) != -1) { os.write(bu, 0, len); } } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } finally { try { sis.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2.用IO流实现文件合并
package com.xhj.io; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; /** * 用IO流的方法合并文件 * * @author XIEHEJUN * */ public class MergeFiles { public static File createFile(String uri, String contents) { File file = new File(uri); try { OutputStream os = new FileOutputStream(uri); os.write(contents.getBytes()); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return file; } public static String getContents(File file) { StringBuffer sb = new StringBuffer(); try { if (file.exists()) { FileInputStream is = new FileInputStream(file); BufferedReader b_reader = new BufferedReader( new InputStreamReader(is)); String inLine = b_reader.readLine(); while (inLine != null) { // System.getProperty("line.separator")--获取当前系统的换行符 sb.append(inLine + System.getProperty("line.separator")); inLine = b_reader.readLine(); } b_reader.close(); is.close(); } } catch (Exception e) { e.printStackTrace(); } return sb.toString(); } public static void main(String[] args) { File file1 = createFile("src/com/xhj/io/file1.txt", "你好!"); File file2 = createFile("src/com/xhj/io/file2.txt", "我是和佑!"); File file3 = createFile("src/com/xhj/io/file3.txt", "你呢?"); String content1 = mergeContents(getContents(file1), getContents(file2)); String content2 = mergeContents(content1, getContents(file3)); createFile("src/com/xhj/io/file3.txt", content2); } /** * 合并内容 * * @param contents1 * @param contents2 * @return */ public static String mergeContents(String contents1, String contents2) { contents1 = contents1.replace("\r\n", ""); if (contents2.indexOf(contents1) == -1) { contents2 = contents1 + contents2; } return contents2; } }