文章目录
- 一、枚举(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 枚举的两个抽象方法
本博客知识点收录于:⭐️《JavaSE系列教程》⭐️
一、枚举(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_静态成员变量 {
@Test
public 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_枚举的使用 {
@Test
public 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 {
@Test
public 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_枚举类的构造方法 {
/**
* 枚举的无参构造方法
*/
@Test
public 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 + "】颗星");
}
@Override
public 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_枚举的抽象方法 {
@Test
public void test1() {
// 可以把abstractSeason看做是一个枚举项,在定义枚举项时必须重写枚举类的所有抽象方法
AbstractSeason abstractSeason = new AbstractSeason() {
@Override
public 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(){
@Override
public void fun() {
System.out.println("我是春天~");
}
};
public abstract void fun();
}
- 定义多几个枚举项:
package com.dfbz.demo03_枚举的抽象方法;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public enum Season {
SPRING(){
@Override
public void fun() {
System.out.println("我是春天...");
}
},
SUMMER(){
@Override
public 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:0
Season summer = Season.SUMMER; // ordinal:1
Season autumn = Season.AUTUMN; // ordinal:2
Season winter = Season.WINTER; // ordinal:3
@Test
public void test1() {
System.out.println(spring.compareTo(spring)); // 0-0=0
System.out.println(spring.compareTo(summer)); // 0-1=-1
System.out.println(winter.compareTo(summer)); // 3-1=2
System.out.println(winter.compareTo(spring)); // 3-0=3
}
@Test
public void test2() {
Season spring2 = Season.SPRING;
System.out.println(spring == spring2); // true
System.out.println(spring.equals(spring2)); // 枚举对象的equals方法比较的是内存地址值(返回true)
}
@Test
public void test3() {
Class<Season> clazz = spring.getDeclaringClass();
Class<? extends Season> clazz2 = spring.getClass();
System.out.println(clazz == clazz2); // true
}
@Test
public void test4() {
int hashCode = spring.hashCode();
System.out.println(hashCode); // 2027961269
String name = spring.name();
System.out.println(name); // SPRING
int ordinal_spring = spring.ordinal();
int ordinal_summer = summer.ordinal();
int ordinal_autumn = autumn.ordinal();
int ordinal_winter = winter.ordinal();
System.out.println(ordinal_spring); // 0
System.out.println(ordinal_summer); // 1
System.out.println(ordinal_autumn); // 2
System.out.println(ordinal_winter); // 3
}
@Test
public 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
}