枚举
枚举基本的概念
-
枚举从字面上来说就是一一列举的意思
-
一年中的所有季节:春季、夏季、秋季、冬季。
-
所有的性别:男、女。
-
键盘上的所有方向键:向上、向下、向左、向右。
-
在日常生活中这些事物的取值只有明确的几个固定值,此时描述这些事物的所有制都可以一一列举出来,而这个列举出来的类型就叫做枚举类型。
-
只有几个固定,明确数量,不可更改对象 的类就称作枚举类
package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 19:03 * @description 编程实现所有方向的枚举,所有的方向:向上、向下、向左、向右 */ public class Direction { private final String desc; // 用于描述方向字符串的成员变量 // 2、声明本类类型的引用指向本类类型的对象,此时不够严谨,和单例相比很像 // 该类只有固定的、确定的几个对象,不能再new出新的对象,这样的类就叫枚举类 // 在开发里尽量减少代码的冗余 public static final Direction UP = new Direction("向上"); public static final Direction DOWN = new Direction("向下"); public static final Direction LEFT = new Direction("向左"); public static final Direction RIGHT = new Direction("向右"); // 通过构造方法实现成员变量的初始化,更加灵活 // 1、私有化构造方法,此时该构造方法只能在本类的内部使用 private Direction(String desc) { this.desc = desc; } // set方法提供了无用,此处的成员变量是final的,不可修改,提供了还会报错 // 通过公有的get方法可以在本类的外部访问该类成员变量的数值 public String getDesc() { return desc; } } package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 19:09 * @description */ public class DirectionTest { public static void main(String[] args) { // 1、声明Direction类型的引用指向该类型的对象并打印特征 /*Direction d1 = new Direction("向上"); System.out.println("获取到的字符串是:" + d1.getDesc()); // 向上 Direction d2 = new Direction("向下"); System.out.println("获取到的字符串是:" + d2.getDesc()); // 向下 Direction d3 = new Direction("向左"); System.out.println("获取到的字符串是:" + d3.getDesc()); // 向左 Direction d4 = new Direction("向右"); System.out.println("获取到的字符串是:" + d4.getDesc()); // 向右 System.out.println("------------------------------------"); Direction d5 = new Direction("向前"); // 'Direction(java.lang.String)' has private access in 'com.lagou.module02.task05.Direction' System.out.println("获取到的字符串是:" + d5.getDesc()); // 向前*/ // Direction.UP = 2; Error: 类型不匹配 // Direction d2 = null; // Direction.UP = d2; Error: Cannot assign a value to final variable 'UP' 不能修改被final修饰的变量'UP' Direction d1 = Direction.UP; System.out.println("获取到的方向是:" + d1.getDesc()); // 向上 } }
枚举的定义
-
使用public static final 表示的常量描述较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从Java5开始增加的一种引用数据类型。
-
枚举值就是当前类的类型,也就是指向本类的对象(就是把上面的代码中重复冗余的内容删掉了),默认使用public static final关键字共同修饰,因此采用==枚举类型.==的方式调用。
-
枚举类中可以自定义构造方法,但是构造方法的修饰符必须是private,默认也是私有的。
package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 19:03 * @description 编程实现所有方向的枚举,所有的方向:向上、向下、向左、向右 枚举类型要求所有枚举值必须放在枚举类型的最前面 */ public enum DirectionEnum { // 2、声明本类类型的引用指向本类类型的对象,此时不够严谨,和单例相比很像 // 该类只有固定的、确定的几个对象,不能再new出新的对象,这样的类就叫枚举类 // 在开发里尽量减少代码的冗余 // Enum types cannot be instantiated枚举类型不能new对象,也就是说枚举类型不能初始化 // Missing method body, or declare abstract // Parameter expected无效方法声明 // 跟Direction相比只是把相同的重复的东西去掉了 UP("向上"),DOWN("向下"),LEFT("向左"),RIGHT("向右"); private final String desc; // 用于描述方向字符串的成员变量 // 通过构造方法实现成员变量的初始化,更加灵活 // 1、私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String desc) { this.desc = desc; } // set方法提供了无用,此处的成员变量是final的,不可修改,提供了还会报错 // 通过公有的get方法可以在本类的外部访问该类成员变量的数值 public String getDesc() { return desc; } } 测试类中---------------------------------------------- // 使用一下Java5开始的枚举类型 DirectionEnum down = DirectionEnum.DOWN; System.out.println("获取到的方向是:" + down.getDesc()); // 向下
自定义类和枚举类型在switch结构的使用
package com.lagou.module02.task05;
/**
* @author hhc19
* @date 2022/1/1 21:37
* @description
*/
public class DirectionUseTest {
// 自定义静态方法实现根据参数指定的字符串内容来打印具体的方向信息
public static void test1(String str) {
switch (str) {
case "向上":
System.out.println("抬头望明月!");
break;
case "向下":
System.out.println("低头思故乡!");
break;
case "向左":
System.out.println("左牵黄!");
break;
case "向右":
System.out.println("右擎苍!");
break;
default:
System.out.println("没有这样的方向哦!");
}
}
// 自定义静态方法实现根据参数指定的枚举类型来打印具体的方向信息
public static void test2(DirectionEnum de) {
switch (de) {
// case de.UP: // An enum switch case label must be the unqualified name of an enumeration constant
case UP:
System.out.println("抬头望明月!");
break;
case DOWN:
System.out.println("低头思故乡!");
break;
case LEFT:
System.out.println("左牵黄!");
break;
case RIGHT:
System.out.println("右擎苍!");
break;
default:
System.out.println("没有这样的方向哦!");
}
}
public static void main(String[] args) {
DirectionUseTest.test1(Direction.UP.getDesc());
DirectionUseTest.test1("今天是个好日子");
System.out.println("---------------------------------");
DirectionUseTest.test2(DirectionEnum.DOWN);
// DirectionUseTest.test2("今天是个好日子"); // Error 不匹配的类型, 减少了出错的可能型,只有当这个东西只有固定的几个值的时候,我们推荐使用枚举类型
}
}
Enum 类的概念和常用方法
-
所有的枚举类都继承自java.lang.Enum类,常用方法如下:
compareTo 方法比较结果:
- 当调用对象在参数对象之后时,获取到的比较结果为 正数
- 当调用对象在参数对象相同位置时,获取到的比较结果为 零
- 当调用对象在参数对象之前时,获取到的比较结果为 负数
package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 22:21 * @description 编程实现方向枚举类的测试,调用从Enum中继承下来的方法 */ public class DirectionEnumTest { public static void main(String[] args) { // 1、获取DirectionEnum类型中所有的枚举对象 DirectionEnum[] arr = DirectionEnum.values(); // 2、打印每个枚举对象在枚举类型中的名称和索引位置 /** * 运行结果: * 获取到的枚举对象的名称是:UP * 获取到的枚举对象对应的索引位置是:0 * 获取到的枚举对象的名称是:DOWN * 获取到的枚举对象对应的索引位置是:1 * 获取到的枚举对象的名称是:LEFT * 获取到的枚举对象对应的索引位置是:2 * 获取到的枚举对象的名称是:RIGHT * 获取到的枚举对象对应的索引位置是:3 */ for (int i = 0; i < arr.length; i++) { System.out.println("获取到的枚举对象的名称是:" + arr[i].toString()); System.out.println("获取到的枚举对象对应的索引位置是:" + arr[i].ordinal()); // 和数组一样下标从0开始 } System.out.println("--------------------------------"); // 3、根据参数指定的字符串得到枚举类型的对象,也就是将字符串转换为对象 // DirectionEnum de = DirectionEnum.valueOf("向下"); // 编译ok, 运行会发生java.lang.IllegalArgumentException非法参数异常 // No enum constant com.lagou.module02.task05.DirectionEnum.向下 没有一个枚举常量叫做:com.lagou.module02.task05.DirectionEnum.向下 DirectionEnum de = DirectionEnum.valueOf("DOWN"); // DirectionEnum de = DirectionEnum.valueOf("UP LEFT"); 要求字符串名称必须在枚举对象中存在 // System.out.println("转换出来的枚举对象是:" + de.toString()); System.out.println("转换出来的枚举对象是:" + de); // 当打印引用变量时,会自动调用toString()方法 System.out.println("--------------------------------"); // 4、使用获取到的枚举对象与枚举类中已有的对象比较先后顺序 for (int i = 0; i < arr.length; i++) { // 当调用对象在参数对象之后时,获取到的比较结果为 正数 // 当调用对象在参数对象相同位置时,获取到的比较结果为 零 // 当调用对象在参数对象之前时,获取到的比较结果为 负数 System.out.println("调用对象与数组中对象比较的先后顺序结果是:" + de.compareTo(arr[i])); // 大于是正数,等于是0,小于是负数 } } }
枚举类实现接口的方式
-
用enum定义的枚举类型默认继承Enum类,也就是说它们无法再继承别的类了。
-
枚举类实现接口后需要重写抽象方法,而重写方法的方式有两种:重写一个,或者每个对象都重写。
package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 22:57 * @description */ public interface DirectionInterface { // 自定义抽象方法 public abstract void show(); } package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 19:03 * @description 编程实现所有方向的枚举,所有的方向:向上、向下、向左、向右 枚举类型要求所有枚举值必须放在枚举类型的最前面 */ public enum DirectionEnum implements DirectionInterface { // 2、声明本类类型的引用指向本类类型的对象,此时不够严谨,和单例相比很像 // 该类只有固定的、确定的几个对象,不能再new出新的对象,这样的类就叫枚举类 // 在开发里尽量减少代码的冗余 // Enum types cannot be instantiated枚举类型不能new对象,也就是说枚举类型不能初始化 // Missing method body, or declare abstract // Parameter expected无效方法声明 // 跟Direction相比只是把相同的重复的东西去掉了 // Class 'Anonymous class derived from DirectionEnum' must implement abstract method 'show()' in 'DirectionInterface' // 匿名内部类的语法格式:接口/父类类型 引用变量名 = new 接口/父类类型() { 方法的重写 }; // 下方的枚举类型只是简化/省略写法,完整写法应该是:public static final Direction UP = new Direction("向上"){ 方法重写 }; // 每个对象都单独重写自己的show方法的好处:在每个对象中都可以让它干不同的工作 UP("向上"){ @Override public void show() { // System.out.println("贪吃蛇向上移动了一下!"); } }, DOWN("向下") { @Override public void show() { System.out.println("贪吃蛇向下移动了一下!"); } }, LEFT("向左") { @Override public void show() { System.out.println("贪吃蛇向左移动了一下!"); } }, RIGHT("向右") { @Override public void show() { System.out.println("贪吃蛇向右移动了一下!"); } }; private final String desc; // 用于描述方向字符串的成员变量 // 通过构造方法实现成员变量的初始化,更加灵活 // 1、私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String desc) { this.desc = desc; } // set方法提供了无用,此处的成员变量是final的,不可修改,提供了还会报错 // 通过公有的get方法可以在本类的外部访问该类成员变量的数值 public String getDesc() { return desc; } // 整个枚举类型只重写一次,所有对象调用同一个 /*@Override public void show() { System.out.println("现在可以实现接口中抽象方法的重写了!"); }*/ } package com.lagou.module02.task05; /** * @author hhc19 * @date 2022/1/1 22:21 * @description 编程实现方向枚举类的测试,调用从Enum中继承下来的方法 */ public class DirectionEnumTest { public static void main(String[] args) { // 1、获取DirectionEnum类型中所有的枚举对象 DirectionEnum[] arr = DirectionEnum.values(); // 2、打印每个枚举对象在枚举类型中的名称和索引位置 /** * 运行结果: * 获取到的枚举对象的名称是:UP * 获取到的枚举对象对应的索引位置是:0 * 获取到的枚举对象的名称是:DOWN * 获取到的枚举对象对应的索引位置是:1 * 获取到的枚举对象的名称是:LEFT * 获取到的枚举对象对应的索引位置是:2 * 获取到的枚举对象的名称是:RIGHT * 获取到的枚举对象对应的索引位置是:3 */ for (int i = 0; i < arr.length; i++) { System.out.println("获取到的枚举对象的名称是:" + arr[i].toString()); System.out.println("获取到的枚举对象对应的索引位置是:" + arr[i].ordinal()); // 和数组一样下标从0开始 } System.out.println("--------------------------------"); // 3、根据参数指定的字符串得到枚举类型的对象,也就是将字符串转换为对象 // DirectionEnum de = DirectionEnum.valueOf("向下"); // 编译ok, 运行会发生java.lang.IllegalArgumentException非法参数异常 // No enum constant com.lagou.module02.task05.DirectionEnum.向下 没有一个枚举常量叫做:com.lagou.module02.task05.DirectionEnum.向下 DirectionEnum de = DirectionEnum.valueOf("DOWN"); // DirectionEnum de = DirectionEnum.valueOf("UP LEFT"); 要求字符串名称必须在枚举对象中存在 // System.out.println("转换出来的枚举对象是:" + de.toString()); System.out.println("转换出来的枚举对象是:" + de); // 当打印引用变量时,会自动调用toString()方法 System.out.println("--------------------------------"); // 4、使用获取到的枚举对象与枚举类中已有的对象比较先后顺序 for (int i = 0; i < arr.length; i++) { // 当调用对象在参数对象之后时,获取到的比较结果为 正数 // 当调用对象在参数对象相同位置时,获取到的比较结果为 零 // 当调用对象在参数对象之前时,获取到的比较结果为 负数 System.out.println("调用对象与数组中对象比较的先后顺序结果是:" + de.compareTo(arr[i])); // 大于是正数,等于是0,小于是负数 } System.out.println("--------------------------------"); // 5、使用数组中每个DirectionEnum对象都去调用show方法测试 for (int i = 0; i < arr.length; i++) { arr[i].show();// 每个对象调用的都是自己匿名内部类重写的方法 } // 枚举类型跟之前普通类重写方法的不同之处在于:实现抽象方法有两种方式:1、重写一次,所有对象共用;2、每个对象的内部都可以单独重写这个方法 } }