当前位置: 首页 > 知识库问答 >
问题:

枚举是否比公共静态最终常量更难维护?

王辉
2023-03-14

我最近和一个朋友讨论了枚举和公共静态最终常量。我告诉他公共静态最终常量比枚举更容易维护,有时更快(Android开发者文档证实了这一点),也更方便。我还说当你使用枚举时,你也会失去功能:

  1. 不能扩展枚举

然后他说,如果需要实例化或扩展枚举,就不应该使用枚举。然后我回答说,这就是为什么我们应该只使用常量,因为它更易于维护;如果在项目中期我们需要实例化一个枚举或扩展它呢?那我们就必须改变一切。

我举了一个例子来演示枚举与常量,以说明我的观点:

public enum WeekDay {
/*
 * We will start at 1 for demonstration
 */
SUNDAY("Sunday", 1), MONDAY("Monday", 2), TUESDAY("Tuesday", 3), WEDNESDAY(
        "Wednesday", 4), THURSDAY("Thursday", 5), FRIDAY("Friday", 6), SATURDAY(
        "Saturday", 7);
/*
 * Notice we cannot do this...This is where enums fail.
 */
// LUNES("lunes",1), MARTES("martes",2);

private String dayName;
private int dayIndex;

private WeekDay(String dayName, int dayIndex) {
    this.dayName = dayName;
    this.dayIndex = dayIndex;
}

public String getDayName() {
    return dayName;
}

public void setDayName(String dayName) {
    this.dayName = dayName;
}

public int getDayIndex() {
    return dayIndex;
}

public void setDayIndex(int dayIndex) {
    this.dayIndex = dayIndex;
}

@Override
public String toString() {
    return this.dayName + ":  " + this.dayIndex;
}

}

如果我们也需要西班牙工作日呢?枚举不足,因为无法扩展它(必须执行一些复制和粘贴操作)。

将枚举与此进行对比:

public class WeekDayClass {

    private int dayIndex;
    private String dayName;

    public WeekDayClass(int dayIndex, String dayName) {
        super();
        this.dayIndex = dayIndex;
        this.dayName = dayName;
    }

    public int getDayIndex() {
        return dayIndex;
    }

    public void setDayIndex(int dayIndex) {
        this.dayIndex = dayIndex;
    }

    public String getDayName() {
        return dayName;
    }

    public void setDayName(String dayName) {
        this.dayName = dayName;
    }

    @Override
    public String toString() {
        return this.dayName + ":  " + this.dayIndex;
    }

    abstract static class Constants {

    }


    public static void main(String[] args) {
        WeekDayClass init = new WeekDayClass(10, "I can init new days here");

    }
}

然后我可以扩展它,让美国人的工作日:

public class AmericanWeekDay extends WeekDayClass {
    public AmericanWeekDay(int dayIndex, String dayName) {
        super(dayIndex, dayName);
    }

    static class AmericanConstants extends Constants {
        public static final WeekDayClass SUNDAY = new WeekDayClass(1, "Sunday");
        public static final WeekDayClass MONDAY = new WeekDayClass(2, "Monday");
        /*
         * And so on...
         */
    }

}

或者西班牙周:

 public class SpanishWeekDays extends WeekDayClass {

    public SpanishWeekDays(int dayIndex, String dayName) {
        super(dayIndex, dayName);
    }

    static class SpanishConstants extends Constants {
        public static final SpanishWeekDays LUNES = new SpanishWeekDays(2, "lunes");
        /*
         * And so on...
         */
    }

}

更进一步说:

public class WeekDayClass {

    private int dayIndex;
    private String dayName;

    public WeekDayClass(int dayIndex, String dayName) {
        super();
        this.dayIndex = dayIndex;
        this.dayName = dayName;
    }

    public int getDayIndex() {
        return dayIndex;
    }

    public void setDayIndex(int dayIndex) {
        this.dayIndex = dayIndex;
    }

    public String getDayName() {
        return dayName;
    }

    public void setDayName(String dayName) {
        this.dayName = dayName;
    }

    @Override
    public String toString() {
        return this.dayName + ":  " + this.dayIndex;
    }

    static class AmericanConstants {
        /*
         * Insert Constants Here
         */

    }

    static class SpanishConstants {
        /*
         * Insert Constants Here
         */
    }

}

我理解使用枚举可以使用数据结构(列表)来解决这个问题,但是为什么要这么麻烦呢?通过使用公共静态常量,我从基类中获得了继承、更干净的代码、可能更短的代码和更容易的可运维性。

我还了解到,可以使用enum更好地设计“输入参数”,但也可以使用如上所示的公共静态最终常量。

枚举的优点是可以在switch语句中使用,并具有继承的枚举方法,如values()。如果需要,这些方法也可以在“公共静态最终常量”类中复制。除了切换,我看不出enum有任何优势。

总之,枚举真的比公共静态最终常量好吗?如果是的话,我错在哪里了?他们是我错过的东西吗?

编辑:不能在枚举中使用泛型。

共有3个答案

严劲
2023-03-14

如果枚举没有用,它们就不会存在——常量也是如此。就像螺丝刀可以拆卸螺丝,而锤子可以拆卸钉子一样——程序员“工具箱”中的不同工具可以用于独特而重要的目的。我建议阅读更多关于枚举和常量的内容,我想你会发现它们为什么存在以及何时使用它们。

巫马英豪
2023-03-14

我认为你把枚举的用法带到了很远的地方,然后得出结论,它们没有用。

枚举只是告诉你有有限的和预定义的选项可供选择。仅此而已。例如,当您看到一个参数是枚举(比如说状态),并且它有三个值(挂起、正在进行、关闭),您知道某个对象的状态可以有其中一个值,也只能有一个值。

枚举提供了一种验证使用了正确值的简单方法,因为编码时无法轻松选择不正确的值。它们也是一种记录方式,因为你可以很容易地看到哪些选项可用。

於宾白
2023-03-14

枚举比你认为的要多得多,虽然有时需要常量,但这种情况可能是枚举的胜利。

首先,“英国工作日”和“西班牙工作日”之间没有真正的区别,它们代表相同的价值观。因此,最好的解决方案是通过某种本地化方法,独立于值的实际内容,将其转换为字符串。这些值不随语言的变化而变化,它们的表示形式会发生变化。

这完全可以用枚举快速轻松地完成。就像这样写(一点伪代码-y):

public enum Weekday {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    ...;

    public String toLocalizedString(Language l) {
        // interact with localization files
    }
}

你把外在表现和内在表现混为一谈。你的数据应该尽可能同质,因为只有一个星期一。它可能被称为不同的东西,但它仍然是相同的价值。

Enum还免费为您提供了很多好处,从长远来看,这使您的代码更清晰,更易于维护。类型检查,==比较,以及开关中的可用性都是少数,没有样板可谈。

 类似资料:
  • 问题内容: 这段代码: 编译并按预期工作。看起来这与以下内容相同: Java接口中的常量的“公共静态最终”是否多余?Java 1.1、1.2、1.3、1.4,…,1.8是否适用于Java,或者在Java版本中已更改? 问题答案: 在Interface中声明的变量是隐式的。这就是JLS 9.3 所说的: 接口主体中的每个字段声明都是隐式的 public,static和final 。可以为此类字段多余

  • 问题内容: [已更新,对更改感到抱歉,但现在是真正的问题] 对于getCanonicalPath()方法中的异常,我无法在其中包括try-catch- loop。我试图通过方法来解决问题,然后在其中声明值。问题是它是最终版本,我无法更改。因此,如何将startingPath作为“ public staticfinal”。 问题答案: 这个名字很好。您忘记声明类型了。 解决这个问题,您当然会意识到如

  • 问题内容: 我一直想知道Java中的单例。按照惯例,单例设置如下: 最近,我切换到使用以下内容: 由于没有空检查,因此它更短,更快捷,而且打字对我来说比打字好。有什么理由不能使第二种方法成为主流呢? 问题答案: 第一个版本在第一次实际需要时创建实例,而第二个版本(较短的版本)在初始化类后立即运行构造函数 类或接口类型T将在以下任何一种首次出现之前立即初始化: T是一个类,并创建T的实例。 T是一个

  • 问题内容: 我正在查看公司其他部门维护的一些Java代码,顺便说一下,这是一些前C和C ++开发人员所维护的。普遍存在的一件事是使用静态整数常量,例如 除了缺少“最终”限定符外,这种代码也让我有些不安。我本来希望看到的是,从学校开始主要接受Java的培训,这会更像 但是,论点使我失望。为什么要比后者更好呢? 问题答案: 为什么要比后者更好呢? 这样做要好得多,因为它可以为您提供类型安全性并具有自记

  • 问题内容: Java中的静态和非静态枚举有什么区别?两种用法是相同的。 正确吗 所有静态的都在启动时加载到内存中,非静态的则按需加载 ? 如果是,那么哪种方法更好?将某些数据始终保留在内存中还是每次使用服务器资源加载它们? 问题答案: 所有的都是有效的。如果您有嵌套的枚举,则它与相同。 所有类都是延迟加载的(枚举或其他),但是在加载时,它们会一次全部加载。也就是说,您不能加载一些常量,而不能加载其

  • 问题内容: 给定下面的Java代码,您可以在Ruby类中最接近地表示这两个变量吗?而且,在Ruby中是否可以像Java中那样区分和变量? 问题答案: Ruby中确实没有等效的构造。 但是,您似乎犯了一个经典的移植错误:您有一种使用语言A 的 解决方案 ,然后尝试将其翻译为语言B,这时您真正应该做的就是找出 问题 ,然后找出解决方法使用语言B。 我不能完全确定您要从那个小的代码段中解决什么问题,但是