💗推荐阅读文章💗
- 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》
- 🌺MySQL系列🌺👉2️⃣《MySQL系列教程》
- 🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》
- 🌻SSM框架系列🌻👉4️⃣《SSM框架系列教程》
🎉本博客知识点收录于🎉👉🚀《JavaSE系列教程》🚀—>✈️18【枚举、类加载器、动态代理】✈️
文章目录
- 一、枚举(Enum)
- 1.1 枚举概述
- 1.2 定义枚举类型
- 1.2.1 静态常量案例
- 1.2.2 枚举案例
- 1.2.3 枚举与switch
- 1.3 枚举的用法
- 1.3.1 枚举类的成员
- 1.3.2 枚举类的构造方法
- 1)枚举的无参构造方法
- 2)枚举的有参构造方法
- 1.3.3 枚举中的抽象方法
- 1.4 Enum 类
- 1.4.1 Enum类中的方法
- 1.4.2 测试方法功能
- 1.4.3 枚举的两个抽象方法
一、枚举(Enum)
1.1 枚举概述
枚举(enum),全称enumeration
,是JDK 1.5 中引入的新特性。Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。
在JDK1.5 之前,我们定义常量都是: public static fianl
。有了枚举之后,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
1.2 定义枚举类型
1.2.1 静态常量案例
我们使用静态常量来设置一个季节类:
package com.dfbz.demo01_静态成员变量;/*** @author lscl* @version 1.0* @intro:*/
public class Season {public static final Integer SPRING = 1;public static final Integer SUMMER = 2;public static final Integer AUTUMN = 3;public static final Integer WINTER = 4;
}
1/2/3/4分别代表不同的含义
测试类:
package com.dfbz.demo01_静态成员变量;import org.junit.Test;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_静态成员变量 {@Testpublic void test1() {method(Season.SPRING);method(Season.WINTER);}public void method(Integer season) {switch (season) {case 1:System.out.println("Spring!"); // 具体的逻辑break;case 2:System.out.println("Summer!"); // 具体的逻辑break;case 3:System.out.println("Autumn!"); // 具体的逻辑break;case 4:System.out.println("Winter!"); // 具体的逻辑break;}}
}
1.2.2 枚举案例
Java 枚举类使用enum
关键字来定义,各个常量使用逗号来分割。
package com.dfbz.demo02;/*** @author lscl* @version 1.0* @intro:*/
public enum Season {SPRING,SUMMER,AUTUMN,WINTER
}
Tips:定义枚举类的关键字是enum,而不是Enum,在Java中所有关键字都是小写的!
其中SPRING
、SUMMER
、AUTUMN
、WINTER
都是枚举项,它们都是本类的实例,本类一共就只有四个实例对象。并且只能通过这四个关键字获取Season类的实例对象,不能使用new来创建枚举类的对象
package com.dfbz.demo02_枚举的使用;import org.junit.Test;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_枚举的使用 {@Testpublic void test1() {// 通过枚举项来获取枚举实例Season spring = Season.SPRING;Season spring2 = Season.SPRING;// 通过相同的枚举项获取的枚举实例是一样的System.out.println(spring == spring2); // true// 不同的枚举项获取的枚举实例是不一样的Season autumn = Season.AUTUMN;System.out.println(spring == autumn); // false}
}
1.2.3 枚举与switch
使用枚举,能让我们的代码可读性更强。
package com.dfbz.demo02_枚举的使用;import org.junit.Test;/*** @author lscl* @version 1.0* @intro:*/
public class Demo02_枚举与switch {@Testpublic void test1() {Season season = Season.AUTUMN;switch (season){case SPRING:System.out.println("春天~");break;case SUMMER:System.out.println("夏天!");break;case AUTUMN:System.out.println("秋天@");break;case WINTER:System.out.println("冬天&");break;default:System.out.println("错误的季节");}}
}
1.3 枚举的用法
1.3.1 枚举类的成员
枚举类和正常的类一样,可以有实例变量,实例方法,静态方法等等
- 定义枚举类:
package com.dfbz.demo02_枚举的使用;/*** @author lscl* @version 1.0* @intro:*/
public enum Color {// 在枚举常量后面还有其他成员时,分号是必须的。枚举常量必须在枚举类中所有成员的上方声明RED, GREEN, BLUE;public String aaa = "AAA"; // 普通成员变量public static String bbb = "BBB"; // 静态成员变量private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public static void method() {System.out.println("enum hello~");}
}
Tips:当枚举项后面有其他成员(构造方法、成员变量、成员方法)时,最后一个枚举项必须加分号;
- 测试类:
package com.dfbz.demo02_枚举的使用;/*** @author lscl* @version 1.0* @intro:*/
public class Demo03_枚举类的成员 {public static void main(String[] args) {// 访问静态成员变量System.out.println(Color.bbb);// 访问静态成员方法Color.method();// 通过枚举项获取实例Color red = Color.RED;// 通过枚举实例调用成员方法red.setName("红色");// 通过枚举实例调用成员方法System.out.println(red.getName()); // 红色}
}
1.3.2 枚举类的构造方法
1)枚举的无参构造方法
枚举类也可以有构造方法,构造方法默认都是private修饰,而且只能是private。因为枚举类的实例不能让外界来创建!
默认情况下,所有的枚举项的创建都是调用枚举类的无参构造方法,并且在获取任何一个枚举实例时,其他实例都将会被创建
package com.dfbz.demo03;/*** @author lscl* @version 1.0* @intro:*/
public enum Direction {// 在枚举常量后面还有其他成员时,分号是必须的。枚举常量必须在枚举类中所有成员的上方声明FRONT,BEHIND,LEFT,RIGHT;// 枚举类的构造方法都是private修饰的,可写可不写Direction(){System.out.println("Direction创建了...");}
}
Tips:
- 1:当枚举项后面有其他成员(构造方法、成员变量、成员方法)时,最后一个枚举项必须加分号;
- 2:所有的枚举类的构造方法都是私有的(private关键字可加可不加)
测试类:
package com.dfbz.demo02_枚举的使用;import org.junit.Test;/*** @author lscl* @version 1.0* @intro:*/
public class Demo04_枚举类的构造方法 {/*** 枚举的无参构造方法*/@Testpublic void test1() {// 运行代码将会创建四个枚举实例Direction behind = Direction.BEHIND;}}
运行结果:
Tips:一旦创建了枚举实例,便会初始化里面的所有枚举项;创建枚举项就等同于调用本类的无参构造器,所以FRONT、BEHIND、LEFT、RIGHT四个枚举项等同于调用了四次无参构造器
2)枚举的有参构造方法
枚举项就是枚举类的实例,在创建定义枚举项时其实就是创建枚举类的实例,因此在定义枚举项就要传递实际的参数
- 定义枚举项:
package com.dfbz.demo02_枚举的使用;/*** @author lscl* @version 1.0* @intro:*/
public enum Week {// 枚举项就是枚举类的实例,在创建定义枚举项时其实就是创建枚举的实例,因此在定义枚举项就要传递实际的参数MONDAY("星期一",1),TUESDAY("星期二"),WEDNESDAY,THURSDAY("星期四",3),FRIDAY("星期五",4),SATURDAY("星期六",5),SUNDAY("星期六",4);private String name;private Integer loveLevel;// 注意: 枚举类的构造方法只能是私有(默认情况下也是私有)Week() { // 空参构造}Week(String name) { // 有参构造this.name = name;}Week(String name, Integer loveLevel) { // 有参构造this.name = name;this.loveLevel=loveLevel;}public void show() {System.out.println("我是【" + name + "】,我的喜好程度是【" + loveLevel + "】颗星");}@Overridepublic String toString() {return "Week{" +"name='" + name + '\'' +", loveLevel=" + loveLevel +'}';}
}
- 测试类:
/*** 枚举的有参构造方法*/
@Test
public void test2() {// 获取第一个枚举实例时,将会创建所有的枚举实例Week friday = Week.FRIDAY;friday.show();System.out.println(friday);System.out.println("---------------");Week saturday = Week.SATURDAY;saturday.show();System.out.println(saturday);System.out.println("---------------");Week tuesday = Week.TUESDAY;tuesday.show();System.out.println(tuesday);System.out.println("---------------");Week wednesday = Week.WEDNESDAY;wednesday.show();System.out.println(wednesday);System.out.println("---------------");
}
- 运行效果如下:
1.3.3 枚举中的抽象方法
枚举类中可以包含抽象方法,但是在定义枚举项时必须重写该枚举类中的所有抽象方法;
我们前面说过,每一个枚举项其实都是枚举类的实例对象,因此如果当前枚举类包含抽象方法时,在定义枚举项时就需要重写此枚举类的所有抽象方法,这跟我们以前使用的匿名内部类很相似;
- 首先定义一个抽象类(包含了抽象方法):
package com.dfbz.demo03_枚举的抽象方法;/*** @author lscl* @version 1.0* @intro:*/
public abstract class AbstractSeason {public abstract void fun();
}
- 实例化这个抽象类的时候,我们必须抽象其所有的抽象方法:
package com.dfbz.demo03_枚举的抽象方法;import org.junit.Test;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_枚举的抽象方法 {@Testpublic void test1() {// 可以把abstractSeason看做是一个枚举项,在定义枚举项时必须重写枚举类的所有抽象方法AbstractSeason abstractSeason = new AbstractSeason() {@Overridepublic void fun() {System.out.println("重写了这个抽象类的所有抽象方法");}};}
}
当枚举类中含有抽象方法的时候,定义枚举项时,必须重写该枚举类中所有的抽象方法,像下面这种就是一种错误的定义:
package com.dfbz.demo03_枚举的抽象方法;/*** @author lscl* @version 1.0* @intro:*/
public enum Season {SPRING; // 编译报错,定义枚举项时必须重写枚举类包含的所有抽象方法public abstract void fun();
}
- 正确写法:
package com.dfbz.demo03_枚举的抽象方法;/*** @author lscl* @version 1.0* @intro:*/
public enum Season {SPRING(){@Overridepublic void fun() {System.out.println("我是春天~");}}; public abstract void fun();
}
- 定义多几个枚举项:
package com.dfbz.demo03_枚举的抽象方法;/*** @author lscl* @version 1.0* @intro:*/
public enum Season {SPRING(){@Overridepublic void fun() {System.out.println("我是春天...");}}, SUMMER(){@Overridepublic void fun() {System.out.println("我是夏天~");}}; public abstract void fun();
}
- 测试类:
@Test
public void test2() {Season spring = Season.SPRING;Season summer = Season.SUMMER;spring.fun();summer.fun();
}
1.4 Enum 类
1.4.1 Enum类中的方法
Java中,所有的枚举类都默认继承与java.lang.Enum
类,这说明Enum中的方法所有枚举类都拥有。另外Enum也继承与Object,因此所有的枚举类都拥有与Object类一样的方法;
Enum类中的方法如下:
Tips:枚举类除了不能拥有Object中的clone、finalize方法外,其他方法都能拥有;
Enum类新增(或重写Object)的方法:
int compareTo(E e)
:比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序(ordinal值)boolean equals(Object o)
:比较两个枚举常量是否相等;Class<E> getDeclaringClass()
:返回此枚举类的Class对象,这与Object中的getClass()类似;int hashCode()
:返回枚举常量的hashCode
;String name()
:返回枚举常量的名字;int ordinal()
:返回枚举常量在枚举类中声明的序号,第一个枚举常量序号为0;String toString()
:把枚举常量转换成字符串;static T valueOf(Class enumType, String name)
:把字符串转换成枚举常量。
1.4.2 测试方法功能
- 定义一个枚举类:
package com.dfbz.demo07;/*** @author lscl* @version 1.0* @intro:*/
public enum Season {SPRING,SUMMER,AUTUMN,WINTER;
}
- 测试类:
package com.dfbz.demo04_Enum;import org.junit.Test;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_Enum类的方法使用 {Season spring = Season.SPRING; // ordinal:0Season summer = Season.SUMMER; // ordinal:1Season autumn = Season.AUTUMN; // ordinal:2Season winter = Season.WINTER; // ordinal:3@Testpublic void test1() {System.out.println(spring.compareTo(spring)); // 0-0=0System.out.println(spring.compareTo(summer)); // 0-1=-1System.out.println(winter.compareTo(summer)); // 3-1=2System.out.println(winter.compareTo(spring)); // 3-0=3}@Testpublic void test2() {Season spring2 = Season.SPRING;System.out.println(spring == spring2); // trueSystem.out.println(spring.equals(spring2)); // 枚举对象的equals方法比较的是内存地址值(返回true)}@Testpublic void test3() {Class<Season> clazz = spring.getDeclaringClass();Class<? extends Season> clazz2 = spring.getClass();System.out.println(clazz == clazz2); // true}@Testpublic void test4() {int hashCode = spring.hashCode();System.out.println(hashCode); // 2027961269String name = spring.name();System.out.println(name); // SPRINGint ordinal_spring = spring.ordinal();int ordinal_summer = summer.ordinal();int ordinal_autumn = autumn.ordinal();int ordinal_winter = winter.ordinal();System.out.println(ordinal_spring); // 0System.out.println(ordinal_summer); // 1System.out.println(ordinal_autumn); // 2System.out.println(ordinal_winter); // 3}@Testpublic void test5() {Season s = Season.valueOf("SPRING"); // 通过枚举项的名称获取枚举项System.out.println(s == spring); // true(返回的还是同一个枚举项)}
}
1.4.3 枚举的两个抽象方法
每个枚举类都有两个静态方法,而且这两个方法不是父类中的方法。这又是枚举类特殊的地方;
-
static T[] values()
:返回本类所有枚举项; -
static T valueOf(String name)
:通过枚举项的名字返回枚举项;
- 测试类:
@Test
public void test6() {// 获取这个枚举类中所有的枚举项Season[] values = Season.values();for (Season value : values) {System.out.println(value);}// 通过枚举项的名称获取枚举项Season s = Season.valueOf("SPRING");System.out.println(s == spring); // true
}