迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Java >

在 Java 中扩展枚举

作者:迹忆客 最近更新:2023/07/20 浏览次数:

本文介绍如何在 Java 中扩展枚举功能。


在 Java 中扩展枚举

我们可以将枚举视为一种编译器魔法,因为在字节码中,枚举表示为具有多个静态成员的类,并且继承自抽象 java.lang.Enum。

这就是枚举不能扩展任何其他类或枚举的原因。 正如我们无法在 Java 中扩展枚举一样,任何类也不可能扩展枚举。 让我们使用以下示例代码来学习,看看会发生什么。

示例代码:

package jiyik;

enum Cars {Audi, BMW, Marcedes}

public class Example extends Cars {

    public static void main(String... args) {

    }
}

上面的代码有一个名为 Cars 的枚举,Example 类正在尝试扩展它。 查看输出:

/Example.java:5: error: cannot inherit from final Cars
public class Example extends Cars {
                             ^
/Example.java:5: error: enum types are not extensible
public class Example extends Cars {
       ^
2 errors

正如我们所看到的,类不能扩展枚举。 那么如果无法扩展枚举,我们还能扩展它的功能吗?

功能可以定义为枚举中实现的方法。 例如,上面代码中的枚举 Cars 可以为每个成员声明抽象方法; 参见示例:

enum Cars {
    Audi { @Override public void drive() { } },
    BMW { @Override public void drive() { } },
    Mercedes { @Override public void drive() { } },
    ;
    public abstract void drive();
}

正如我们所看到的,每个成员都可以重写drive()方法。 但不幸的是,并不总是可以在枚举中创建方法,因为:

  1. 如果枚举属于第三方库或其他团队,则它将不允许实现抽象方法。
  2. 如果它属于不具有drive()方法所需的依赖项的模块。
  3. 如果枚举被其他函数和数据重载,它将变得不可读。

提供了一些解决方案可以解决这些问题并扩展 Java 中枚举的功能。

解决方案1:Java中的镜像枚举

顾名思义,我们需要使用相同的数据创建另一个枚举。 这个新的枚举也将实现drive()方法,所以我们现在有两个枚举:

枚举 Cars 的示例代码:

enum Cars {
    Audi { @Override public void drive() { } },
    BMW { @Override public void drive() { } },
    Mercedes { @Override public void drive() { } },
    ;
    public abstract void drive();
}

枚举 DriveCars 的示例代码:

enum DriveCars {
    Audi { @Override public void drive() { } },
    BMW { @Override public void drive() { } },
    Mercedes { @Override public void drive() { } },
    ;
    public abstract void drive();
}

第二个枚举是第一个枚举的镜像。 现在我们可以通过扩展功能来使用这两个枚举; 我们需要使用内置枚举方法 name()valueof()

请参阅以下示例了解如何使用它:

Cars cars = ...
DriveCars.valueOf(cars.name()).drive();

上面的代码显示了如何在枚举 DriveCars 中使用枚举 Cars 功能。 这意味着功能得到了扩展。

上面代码中的 name() 方法是final的,不能被重写,而valueOf方法将由编译器生成。 这两种方法非常适合,在扩展操作中不会出现功能错误。

上面的代码有一个问题,如果枚举Cars改变了,枚举DriveCars将不知道任何想法,并且会导致trick的名称和值失败。 为了解决这个问题,我们必须让DriveCars知道它的父镜像是Cars。

为此,我们可以使用静态初始化程序来比较 DriveCars 和 Cars,如果两个枚举不匹配,则会抛出异常。 这是 enumus 库中的一个示例:

enum DriveCars {
    ....
    static {
        Mirror.of(Cars.class);
    }
}

该实用程序类将检查两个枚举是否匹配。 此方法将验证 name() 和 valueOf() 技巧。

解决方案 2:Java 中的映射枚举

如果您不想创建另一个仅包含一种方法的枚举。 在这种情况下,我们可以使用接口来代替枚举; 请参见下面的示例:

public interface Driver {
    void drive();
}

现在要使用此接口 Drive 和枚举 Cars,我们可以在它们之间创建映射。 这是地图的示例:

Map<Cars, Driver> drivers = new EnumMap<>(Cars.class) {{
    put(Audi, new Driver() { @Override public void driver(){}})
    put(BMW, new Driver() { @Override public void driver(){}})
    put(Mercedes, new Driver() { @Override public void driver(){}})
}}

现在要使用它们,请使用这段简单的代码:

drivers.get(Cars).drive();

上面代码中使用的 EnumMap 将保证每个枚举成员仅出现一次,但它不保证每个成员都有一个条目。

我们可以检查映射的大小是否等于枚举成员的数量:

drivers.size() == Cars.values().length

enumus 库还为这种情况提供了一个实用程序:如果地图不适合汽车,它将抛出 IllegalStateException。 这是实用程序:

EnumMapValidator.validateValues(Cars.class, map, "Cars map");

上述两种方法都展示了如何通过扩展枚举的功能来使枚举变得强大。 虽然不可能直接扩展枚举,但我们可以使用这些技巧来扩展它们的功能。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

如何在 Java 中延迟几秒钟的时间

发布时间:2023/12/17 浏览次数:217 分类:Java

本篇文章主要介绍如何在 Java 中制造程序延迟。本教程介绍了如何在 Java 中制造程序延时,并列举了一些示例代码来了解它。

如何在 Java 中把 Hashmap 转换为 JSON 对象

发布时间:2023/12/17 浏览次数:187 分类:Java

它描述了允许我们将哈希图转换为简单的 JSON 对象的方法。本文介绍了在 Java 中把 Hashmap 转换为 JSON 对象的方法。我们将看到关于创建一个 hashmap,然后将其转换为 JSON 对象的详细例子。

如何在 Java 中按值排序 Map

发布时间:2023/12/17 浏览次数:171 分类:Java

本文介绍了如何在 Java 中按值对 Map 进行排序。本教程介绍了如何在 Java 中按值对 Map 进行排序,并列出了一些示例代码来理解它。

如何在 Java 中打印 HashMap

发布时间:2023/12/17 浏览次数:192 分类:Java

本帖介绍了如何在 Java 中打印 HashMap。本教程介绍了如何在 Java 中打印 HashMap 元素,还列举了一些示例代码来理解这个主题。

在 Java 中更新 Hashmap 的值

发布时间:2023/12/17 浏览次数:146 分类:Java

本文介绍了如何在 Java 中更新 HashMap 中的一个值。本文介绍了如何在 Java 中使用 HashMap 类中包含的两个方法-put() 和 replace() 更新 HashMap 中的值。

Java 中的 hashmap 和 map 之间的区别

发布时间:2023/12/17 浏览次数:79 分类:Java

本文介绍了 Java 中的 hashmap 和 map 接口之间的区别。本教程介绍了 Java 中 Map 和 HashMap 之间的主要区别。在 Java 中,Map 是用于以键值对存储数据的接口,

在 Java 中获取用户主目录

发布时间:2023/12/17 浏览次数:218 分类:Java

这篇文章向你展示了如何在 Java 中获取用户主目录。本教程介绍了如何在 Java 中获取用户主目录,并列出了一些示例代码以指导你完成该主题。

Java 中 size 和 length 的区别

发布时间:2023/12/17 浏览次数:179 分类:Java

这篇文章教你如何知道 Java 中大小和长度之间的区别。本教程介绍了 Java 中大小和长度之间的区别。我们还列出了一些示例代码以帮助你理解该主题。

Java 中的互斥锁

发布时间:2023/12/17 浏览次数:111 分类:Java

了解有关 Java 中互斥锁的一切,在计算机科学领域,互斥或互斥被称为并发控制的属性。每台计算机都使用称为线程的最小程序指令序列。有一次,计算机在一个线程上工作。为了更好地理解,

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便