为什么Java允许将空值赋给Enum

时间:2014-04-14 09:17:17

标签: java enums

这更像是一个设计问题。 (所以,没有代码。我可以发布创建Enum的代码并将其指定为null如果你想让我这样做。:))我最近一直在思考这个问题但是不能提出来有一个很好的理由。 Enum常量是隐式静态和最终的。 Enum意味着 - "我可以取一个存在于我身上的常数之一"。为什么允许Enum具有空值?为什么不隐式地将枚举值默认为Enum.DEFAULTEnum.None?这不是一个比允许枚举null更好的方法吗?

5 个答案:

答案 0 :(得分:43)

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

顺便说一下,它不是语言选择。它完全取决于你如何实现你的枚举。您可以在枚举中提供另一个常量,例如DEFAULTUNKNOWN,并避免在代码中为null指定引用。这就是众所周知的Null Object Pattern。但是说null赋值本身应该是编译器错误,那么我会说,因为Enum无论如何编译成Class,所以使用{{1}是完全有效的表示不存在实例。

允许null的一个缺陷是在null中使用enum。即使是switch-case案例,下面的代码也会抛出NPE

default

Java也不允许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 } } } ,产生以下编译错误:

  

枚举开关案例标签必须是枚举常量的非限定名称

答案 1 :(得分:4)

我认为,Enum.DEFAULT表示您的枚举变量包含值,但null不包含值。如果它null可以解释它没有价值,那么你就不能在它上面调用非静态方法。

答案 2 :(得分:2)

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

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

答案 3 :(得分:2)

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

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

无论如何,要开始辩论这一点已经有好几年了。

答案 4 :(得分:0)

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

  

为什么允许Enum具有空值?

我相信很少有用例。例如,我们需要初始化一个枚举变量来告诉我们它实际上不是枚举的一部分,但我们可以稍后更改它的值,以便它是它的一部分。如果无法将枚举变量初始化为null,那么我们将污染枚举定义。所以,在我看来,像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

的内容
相关问题