枚举的基本概念
一年中所有季节:春季、夏季、秋季、冬季。
所有的性别:男、女。
键盘上的所有方向按键:上、下、左、右。
在日常生活中这些事物的取值只有明确的几个固定值,此时描述这些事物的所有值都可以一一列举出来,而这个列举出来的类型就叫做枚举类型。
package com.lagou.task10; /** * 编程实现所有方向的枚举,所有的方向:向上/向下/向左/向右 */ public class Direction { // 创建私有函数 private final String str ; Direction(String str){ this.str = str; System.out.println("str = " + str); } public String getStr() { return str; } }
package com.lagou.task10; public class DirectionTest { public static void main(String[] args) { Direction d1 = new Direction("向上"); Direction d2 = new Direction("向下"); Direction d3 = new Direction("向左"); Direction d4 = new Direction("向右"); } }
Direction类描述键盘上的方向键,有四个上下左右;但以上方法可以继续创建对象,我们希望创建一个类这个类只能new四个对象。其根本原因是能肆无忌惮的调用构造方法,令该类不能肆无忌惮的调用构造方法就可以了。
按照单例设计模式的历练应该提供封装性,所以加上private关键字在成员变量前面;与单例设计式越来越像,只不过单例模式对外提供一个对象,枚举类型对外提供多个对象。
package com.lagou.task10;
/**
* 编程实现所有方向的枚举,所有的方向:向上/向下/向左/向右
*/
public class Direction {
// 2.声明声明类型的引用指向本类类型的对象
// 这样看就是这个类的成员变量,外界想要访问它就要得到该类的引用;但是现在外界得不到该类的引用
// 加上static关键字成员变量提升为类层级,外界就可以访问了
// Direction d1;
// 如果d1一旦new出来以后,d1就应该和向上绑定起来绝对不能发生改变了,必须把该变量提升为常量
private final static Direction d1 = new Direction("向上");
private final static Direction d2 = new Direction("向下");
private final static Direction d3 = new Direction("向左");
private final static Direction d4 = new Direction("向右");
// 创建私有函数
private final String str;
// 通过构造方法实现成员变量的初始化,更加灵活
// 1.私有化构造方法,此时该构造方法只能在本类的内部使用
private Direction(String str){
this.str = str;
}
public static Direction getD1() {
return d1;
}
public static Direction getD2() {
return d2;
}
public static Direction getD3() {
return d3;
}
public static Direction getD4() {
return d4;
}
public String getStr() {
return str;
}
public void show(){
System.out.println(getStr());
}
}
package com.lagou.task10;
public class DirectionTest {
public static void main(String[] args) {
Direction d1 = Direction.getD1();
d1.show();
Direction d2 = Direction.getD2();
d2.show();
Direction d3 = Direction.getD3();
d3.show();
Direction d4 = Direction.getD4();
d4.show();
}
}
枚举的定义
使用public static final表示的常量描述较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从java5开始增加的一种引用数据类型。
枚举值就是当前类的类型,也就是指向本类的对象,默认使用public static final关键字共同修饰,因此采用枚举类型.的方式调用。
枚举类可以自定义构造方法,但是构造方法的修饰符必须是private关键字修饰,默认也是私有的。
注意:
1、命名规范“枚举”类型使用Enum作为后缀。
2、使用enum定义枚举类。
3、枚举类型是不需要自己new对象,把重复的代码删除,使用逗号分隔各创建枚举类。
4、定义枚举类必须放在枚举类型最前面
package com.lagou.task10; /** * 编程实现所有方向的枚举,所有的方向:向上/向下/向左/向右 * 枚举类型要求所有枚举值必须放在枚举类型的最前面 */ public enum DirectionEnum { D1 ("1"),D2 ("2"),D3 ("3"),D4 ("4"); private final String str; // 通过构造方法实现成员变量的初始化,更加灵活 // 1.私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String str){ this.str = str; } public String getStr() { return str; } public void show(){ System.out.print(getStr()+" "); } }
package com.lagou.task10; public class DirectionTest { public static void main(String[] args) { DirectionEnum D1 = DirectionEnum.D1; D1.show(); DirectionEnum D2 = DirectionEnum.D2; D2.show(); DirectionEnum D3 = DirectionEnum.D3; D3.show(); DirectionEnum D4 = DirectionEnum.D4; D4.show(); } }
自定义类和枚举类在switch结构的使用
test1()创建静态方法传入字符串形参,switch比对传入的字符串
test2()传入的形参是枚举类,switch对比枚举类
注意:
test1()这种方式可以随便随便传字符串,test2()固定枚举类型,不接受该枚举类型以外传入的参数;所以这种写法对比前一种更加安全,推荐使用枚举类型
package com.lagou.task10; public class DirectionUseTest {
//自定义静态方法实现根据参数指定的字符串内容来具体打印的方向信息 public static void test(String str){ switch (str){ case "向上": System.out.println(str);break; case "向下": System.out.println(str);break; case "向左": System.out.println(str);break; case "向右": System.out.println(str);break; default: System.out.println("Game End!"); } } public static void test1(DirectionEnum str){ switch (str){ case D1: System.out.println("上");break; case D2: System.out.println("下");break; case D3: System.out.println("左");break; case D4: System.out.println("右");break; } } public static void main(String[] args) { //DirectionUseTest dt = new DirectionUseTest(); DirectionUseTest.test(Direction.getD1().getStr()); System.out.println("-------------------------------"); DirectionUseTest.test1(DirectionEnum.D3); } }
Enum类的概念和方法
所有的枚举类都继承自java.lang.Enum类,常用方法如下:
1、static t[] vlaues() 加了static关键字就是说这个方法隶属于类层级,也就是说你想调用这个方法就要拿我们写好的枚举类的类名.去调用;vlaues代表好多的值,()空着代表没有参数T[]值的是一维数组T代表type 类型的意思,也就是这是一个数组这个数组放的是当前枚举类的所有对象,但是当前枚举类我们并不知道类型不是固定的,就是说T代表你当前枚举类类型是什么,这个T就代表什么类型,主要功能就是把当前枚举类中所有的对象拿出来。
2、String toString() 没有static关键字修饰:意味着我们应该拿着枚举类的对象.去调用这个方法,这个方法没有参数但是这个方法返回值是String也就是字符串,这个方法的主要功能就是返回当前枚举类对象的名称,什么叫枚举类对象的名称?就是前面我们写的D1D2D3D4
3、int ordinal() 没有static关键字修饰:意味着我们应该拿着枚举类的对象.去调用这个方法,()里面什么都没有意味这不需要参数,这个方法的功能就是获取枚举对象在枚举类中的索引位置,也就是数组中的下标位置。
4、static T valueOf(String str) 加了static关键字就是说这个方法隶属于类层级,也就是说你想调用这个方法就要拿我们写好的枚举类的类名.去调用;(String str)这个方法需要写参数,参数是string类型的str,T代表类型,作用就是把字符串转换为枚举对象。
5、int compareTo(E o) 没有static关键字修饰:意味着我们应该拿着枚举类的对象.去调用这个方法,E实际上就是元素类型,返回值是int类型,作用就是比较两个枚举对象在定义时的顺序,int代表三种结果,正、负、0
package com.lagou.task10; /** * 编程实现方向枚举类的测试 */ public class DirectionEnumTest { public static void main(String[] args) { //1.获取DirectionEnum类型中所有的枚举对象 DirectionEnum[] arr = DirectionEnum.values(); //2.打印每个枚举对象在枚举类型中的名称和索引位置 for(int i=0;i<arr.length;i++){ System.out.println("当前枚举类的引用是:"+arr[i].toString()); System.out.println("获取到的枚举对象的索引位置是:"+arr[i].ordinal()); } System.out.println("--------------------------------------------------------"); //3.根据参数指定的字符串得到枚举类型的对象,也就是将字符串转换为对象 //DirectionEnum de = DirectionEnum.valueOf("向下"); //编译OK,运行IllegalArgumentException //DirectionEnum de = DirectionEnum.valueOf("D10"); //要求字符串名称必须在枚举对象中存在 DirectionEnum de = DirectionEnum.valueOf("D4"); System.out.println("转换出来的枚举对象名称是:" + de.toString()); //4.使用获取到的枚举对象与枚举类中已有的对象比较先后顺序 System.out.println("--------------------------------------------------------"); for(int i=0;i<arr.length;i++){ System.out.println("调用对象与数组中对象比较先后顺序结果是:" + de.compareTo(arr[i])); } } }
注意:
1、valueOf()方法传入的字符串必须是枚举类引用的名字,就是创建出来的枚举对象D1D2D3D4否则报错
2、compareTo()方法必须是枚举类中比较对象.去调用它,()中传入被比较的对象,得出两个对象的先后顺序位置
枚举类实现接口的方式:
枚举类实现接口需要重写抽象方法,而重写方法的方式有两种:重写一个,或者每个对象都重写
1、枚举类不支持继承
重写一个:
package com.lagou.task10; public interface DirectionInterface { //自定义抽象方法 public abstract void show1(); }
package com.lagou.task10; /** * 编程实现所有方向的枚举,所有的方向:向上/向下/向左/向右 * 枚举类型要求所有枚举值必须放在枚举类型的最前面 */ public enum DirectionEnum implements DirectionInterface{ D1 ("1"),D2 ("2"),D3 ("3"),D4 ("4"); private final String str; // 通过构造方法实现成员变量的初始化,更加灵活 // 1.私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String str){ this.str = str; } public String getStr() { return str; } public void show(){ System.out.print(getStr()+" "); } @Override public void show1() { System.out.println("实现接口中重写后的show方法!"); } }
package com.lagou.task10; /** * 编程实现方向枚举类的测试 */ public class DirectionEnumTest { public static void main(String[] args) { //1.获取DirectionEnum类型中所有的枚举对象 DirectionEnum[] arr = DirectionEnum.values(); //2.使用数组中每个DirectionEnum对象去调用show1方法测试 for(int i=0;i<arr.length;i++){ System.out.print(arr[i]); arr[i].show1(); } } }
每个对象都重写:
实际上重写后的show方法都是匿名方法,调用一次就会释放内存
package com.lagou.task10; /** * 编程实现所有方向的枚举,所有的方向:向上/向下/向左/向右 * 枚举类型要求所有枚举值必须放在枚举类型的最前面 */ public enum DirectionEnum implements DirectionInterface{ D1 ("1"){ @Override public void show1() { System.out.println("D1实现接口中重写后的show方法!"); } },D2 ("2") { @Override public void show1() { System.out.println("D2实现接口中重写后的show方法!"); } },D3 ("3") { @Override public void show1() { System.out.println("D3实现接口中重写后的show方法!"); } },D4 ("4") { @Override public void show1() { System.out.println("D4实现接口中重写后的show方法!"); } }; private final String str; // 通过构造方法实现成员变量的初始化,更加灵活 // 1.私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String str){ this.str = str; } public String getStr() { return str; } public void show(){ System.out.print(getStr()+" "); } }