繁体   English   中英

为什么 Java 允许将空值分配给 Enum?

[英]Why does Java allow null value to be assigned to an Enum?

这更像是一个设计问题,所以没有代码。 如果您希望我这样做,我可以发布创建 Enum 并将其分配给null代码。 :))

我最近一直在思考这个问题,但想不出一个很好的理由。 Enum 常量是隐式的staticfinal Enum 的意思是 - “我可以取一个存在于我中的常量的值”。 为什么允许 Enum 具有null值? 为什么不将 Enum 的值隐式默认为Enum.DEFAULTEnum.None 这不是比允许 Enum 为null更好的方法吗?

首先, null表示实例不存在。 提供像DEFAULTNONE这样的默认常量会改变这个含义。 其次,为什么你需要一些默认的东西来代表似乎不存在的东西? 这就是null的目的。 基本上,您必须初始化并存储一个额外的对象,该对象甚至不应该存在。

顺便说一句,这不是语言选择。 如何实现枚举完全取决于您。 您可以在枚举中提供另一个常量,如DEFAULTUNKNOWN ,并避免将null分配给代码中的引用。 这就是众所周知的空对象模式 但是说null赋值本身应该是编译器错误,那么我会说,因为无论如何Enum被编译为Class ,所以使用null来表示实例的不存在是完全有效的。

允许null一个陷阱是在switch-case使用enum 即使使用default情况,以下代码也会抛出NPE

public class Demo {
    enum Color {
        WHITE, BLACK;
    }

    public static void main(String[] args) {
        Color color = null;

        switch (color) {    // NPE here
        case WHITE: break;
        case BLACK: break;
        default: break;     // null value does not fall into the default
        }
    }
}

Java 不允许case null:或者,产生以下编译错误:

枚举 switch case 标签必须是枚举常量的非限定名称

Java 允许任何引用为空,并且对枚举的引用并没有那么特殊,以至于需要进行特殊情况来阻止它,或者提供已经明确指定和易于理解的另一个版本的行为。 Null 已经是一个完全足够的哨兵值:我们不需要另一个。

您的建议都没有说服力,因为它们都需要添加更多功能来支持它们。

无论如何,现在开始辩论这个问题已经晚了几年。

我认为, Enum.DEFAULT意味着您的 enum 变量包含一个值,但null不包含。 如果它为null则可以将其解释为没有值,例如,您不能在其上调用非静态方法。

您可以向您的枚举添加行为(域驱动设计),例如添加一个名为 prettyPrint() 的公共方法,该方法根据您的枚举值返回一个字符串。 默认值/空值如何提供此自定义方法的实现?

如果您想用枚举表示 null,那么您必须通过手动使用带有 NONE 值的空对象模式和基于 NONE 值的 PrettyPrint() 自定义实现来明确这一点。

老了,我知道。 我是 Java 的一半。

为什么允许 Enum 具有空值?

我相信,用例很少。 例如,我们需要初始化一个 enum 变量来告诉我们它实际上不是 enum 的一部分,但是我们可以稍后更改它的值,使其成为它的一部分。 如果无法将枚举变量初始化为null ,那么我们将污染枚举定义。 因此,在我看来,诸如LibEnum.NONE字段会LibEnum.NONE库。 例如,您不希望将LibEnum.NONE用作方法的参数,等等。

我发现它在我的词法扫描器中很有用,包括关键字和标点符号。 假设您有一个标识符"blah" 然后你想检查它是否是任何关键字。

private Keywordv getKeywordValue(String id)
{
    switch (id.length())
    {
        case 2:
        {
            switch (id)
            {
                case "do": return Keywordv.DO;
                case "if": return Keywordv.IF;
                case "is": return Keywordv.IS;

                // ...
            }

            break;
        }

        // ...
    }

    return null;
}

多亏了null ,很容易验证标识符是否不是关键字。

id == null

否则我们必须定义类似Keywordv.__NULL东西

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM