【问题标题】:When is it OK to use an Enum's name()什么时候可以使用枚举的 name()
【发布时间】:2018-09-14 06:43:41
【问题描述】:

变量的名称可以更改,不会影响逻辑。但是 Enum 中的 name() 方法返回一个常量名称作为值,因此它可以破坏现有代码。我应该避免使用name()吗?

例如,

public enum Example1 {FOO, BAR}

将FOO 名称重构为FOO2 将制动Example1.FOO.name().equals("FOO")。

public enum Example2 {
    FOO("FOO"),
    BAR("BAR");

    String code;

    private Example2(final String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }
}

在这种情况下,将FOO 名称更改为FOO2 不会制动Example2.FOO.getCode().equals("FOO")。

【问题讨论】:

  • 你写Example1.FOO.name().equals("FOO")是为了什么?
  • name() 方法返回枚举值的名称。如果您想要一个可读的字符串,请使用toString()(默认情况下返回名称)。
  • But name() method in Enum returns a variable name as a value so it can break existing code.你认为你可以改变“FOO”的名字吗?
  • @ruakh 例如从 URL 参数读取值
  • 鉴于javadoc 中的内容,我避免使用.name()

标签: java enums anti-patterns


【解决方案1】:
  • 业务逻辑应该使用枚举值,而不是直接使用name()。原因:即使名称改变,语义(与之前相同的枚举值)保持不变。
  • 序列化/反序列化值时使用name()。这会影响数据库(使用名称进行 O/R 映射时)、存储在文件中或通过网络传输的序列化数据(JSON/XML/YAML/...序列化)、日志条目等。
    更改名称可能需要数据迁移或在 3rd 方代码中进行调整。

【讨论】:

  • valueOf 和 toString 方法是否同样适用?
  • valueOf 直接与 name 耦合,name() 和 valueOf() 都不能被覆盖,所以:是的。另一方面,toString 可以被覆盖并用于显示枚举的附加信息/字段。
【解决方案2】:

您怀疑一般使用它是不明智的,因为它泄露了实现细节是正确的。如果你有一个颜色enum 和一个RED 值,那么使用colour.name() 向程序用户报告某物的颜色是错误的,因为用户可能需要英语以外的语言的消息,并且所有CAPS 文本通常不合适。

在程序员用来帮助调试问题的代码中使用它是可以的。比如异常消息,因为they should not be presented to normal program users。

【讨论】:

    【解决方案3】:

    当使用枚举类型时,我总是比较枚举本身而不是枚举的名称(字符串)。

    Example2.FOO.equals(Example2.getEnumByName("FOO"));
    

    【讨论】:

    • 我从 URL 参数中获取了字符串值。它可以转换为枚举值,但参数很容易被客户端调整。所以在这种情况下我选择比较字符串。
    • 问题是关于重命名源代码中的枚举常量(也就是重构它)而不破坏任何依赖该名称的代码。在这里,代码将以与使用 Example1.FOO.name().equals("FOO") 时相同的方式被破坏。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2010-10-11
    • 2019-10-10
    • 1970-01-01
    • 2011-02-24
    • 2012-10-28
    • 2012-07-09
    相关资源
    最近更新 更多