欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Java 列举了最完整的解释,这些好处你无法想象

最编程 2024-04-15 22:20:27
...

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

1、枚举的意义

我们在很多时候会拿枚举和常量来做对比,可实际我们在程序中大量使用枚举的地方就是为了代替常量。因为相对于静态的常量,枚举类显得更加直观,类型也相对更加安全。

1.1 安全性

若一个方法中要求传入方向这个参数,用常量的话,形参就是int类型,开发者传入任意类型的int类型值就行,但是如果是枚举类型的话,就只能传入枚举类中包含的对象。

1.2 命名空间

开发者要在命名的时候以SEASON_开头,这样另外一个开发者再看这段代码的时候,才知道这四个常量分别代表方位。

2、枚举的应用

枚举是JDK1.5新增的一个特性,它使用关键字enum来定义。枚举具有以下几个特点:

2.1 特点:
  • enum和class、interface的地位一样
  • 使用enum定义的枚举类默认继承了java.lang.Enum,而不是继承Object类,并且枚举类可以实现一个或多个接口。
  • 枚举类的所有实例都必须放在第一行展示,不需使用new 关键字,不需显式调用构造器。自动添加public static final修饰。
  • 使用enum定义、非抽象的枚举类默认使用final修饰,不可以被继承。
  • 枚举类的构造器只能是私有的。
2.2 使用:

前面我们说了枚举通常当参数使用,Java5新增了enum关键字,同时扩展了switch,在switch...case结构中的case表达式中直接写入枚举值,且不需加入枚举类作为限定。

image-20210818235841012

3、枚举的特殊玩法

那除了代替常量,枚举还有什么特殊的玩法呢?当然有啦,比如以下:

3.1 单例模式

单例模式可以说是每个java开发者必须掌握的一个设计模式了,通常我们说它的实现,有饱汉式和饿汉式,也有经常说的双重判断,今天我们介绍另外一种方式,借助枚举来实现:

public enum SingleEnum {
    INSTANCE;

    public void print(String word) {
        System.out.println(word);
    }
}
@Test
public void testSingle() {
    SingleEnum.INSTANCE.print("hello world");
}

如上,用枚举实现单例模式真的非常简单,将类声明为枚举,内部只定义一个值即可。这样做主要是基于枚举的三个特性,即:枚举类不能new,因此保证单例、枚举类不能被继承、类不加载时,不会实例化

使用枚举类创建的单例还有一个好处,就是使用了反射也无法打破它的单例性质,这是相比较于其他的实现方式的一个优点。但是在实际的项目中这种写法并不常见,这是因为我们习惯了将枚举作为常量来使用,很少在举类中,添加复杂的业务逻辑。

3.2 策略模式

除了轻松实现上面的单例模式之外,枚举还可以非常简单的实现策略模式,比如下面这个例子:

我现有一个接口,通过接受的参数,来决定最终的数据存在什么地方,如果按照正常的写法,可能就是很多的if/else

public void save(String type, Object data) {
    if ("db".equals(type) {
        // 保存到db
        saveInDb(data);
    } else if ("file".equals(type)) 
        // 保存在文件
        saveInFile(data);
    } else if ("oss".eqauls(type)) {
        // 保存在oss
        saveInOss(type);
    }
}

以上写法虽说简单直观,但是当type类型多了之后,这个if/else的代码行数就会越来越多了,而且看起来也不美观。如果我们换成枚举,基于策略模式的思想来解决上面的if/else问题,就会好的多。

public enum SaveStrategyEnum {
    DB("db") {
        @Override
        public void save(Object obj) {
            System.out.println("save in db:" + obj);
        }
    },
    FILE("file") {
        @Override
        public void save(Object obj) {
            System.out.println("save in file: " + obj);
        }
    },
    OSS("oss") {
        @Override
        public void save(Object obj) {
            System.out.println("save in oss: " + obj);
        }
    };

    private String type;

    SaveStrategyEnum(String type) {
        this.type = type;
    }

    public abstract void save(Object obj);

    public static SaveStrategyEnum typeOf(String type) {
        for (SaveStrategyEnum strategyEnum: values()) {
            if (strategyEnum.type.equalsIgnoreCase(type)) {
                return strategyEnum;
            }
        }
        return null;
    }
}

public void save(String type, Object data) {
    SaveStrategyEnum strategyEnum = SaveStrategyEnum.typeOf(type);
    if (strategyEnum != null) {
        strategyEnum.save(data);
    }
}

以上主要利用的是抽象类 + 枚举来完成不同的策略具体实现,这种实现方式,相比较与前面的单例模式,还是更常见一点,虽然整体看下来没有什么难度,但是仔细看一看,会有两个发现:抽象方法的使用 (在模板设计模式中,更能体会抽象方法的使用妙处),利用枚举原生提供的values(),来实现遍历,找到目标

以上就是我对枚举的的理解,在实际使用中还有很多想不到的好处,使用起来真的非常灵活方便!欢迎大家一起留言探讨~