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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23056324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 20:20:11  来源:igfitidea点击:

Why does Java allow null value to be assigned to an Enum

javaenums

提问by TheLostMind

This is more of a design question. (So, No code. I could post code of creating an Enum and assigning it to null if you want me to do it. :)) I've been thinking a lot about this lately but can't come up with one good reason. The Enum constants are implicitly static and final. Enum is meant to say - "I can take a value of one of the constants present in me". Why allow Enum to have a null value?. Why not implicitly default the Enum's value to a Enum.DEFAULTor Enum.None? Isn't this a better approach than allowing the Enum to be null?

这更像是一个设计问题。(所以,没有代码。如果您希望我这样做,我可以发布创建 Enum 并将其分配给 null 的代码。:))我最近一直在思考这个问题,但找不到一个好的理由. Enum 常量是隐式静态和最终的。Enum 的意思是 - “我可以取一个存在于我中的常量的值”。为什么允许 Enum 具有空值?。为什么不将 Enum 的值隐式默认为 aEnum.DEFAULTEnum.None?这不是比允许 Enum 更好的方法null吗?

采纳答案by Rohit Jain

Firstly nullmeans non-existence of an instance. Providing a default constant like DEFAULTor NONE, will change that meaning. Secondly, why would you need something default to represent what seems to be non-existent? That is the purpose of null. Basically, you would have to initialize and store an extra object, which shouldn't even exist whatsoever.

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

BTW, it's not a language choice. It's completely on you how you implement your enum. You can provide another constant like DEFAULT, or UNKNOWNin your enum, and avoid the assignment of nullto the reference in your code. This is famously known as Null Object Pattern. But saying that the nullassignment should itself be compiler error, then I would say, since an Enumis anyways compiled to a Class, so it would be perfectly valid to use nullto represent non-existence of an instance.

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

One pitfall of allowing nullthough is with the usage of enumin switch-case. The below code will throw NPE, even with a defaultcase:

允许的一个陷阱null是使用enumin switch-caseNPE即使有一个default案例,以下代码也会抛出:

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 does not allow a case null:either, producing the following compile error:

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

an enum switch case label must be the unqualified name of an enumeration constant

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

回答by Philip Voronov

I think, Enum.DEFAULTmeans that your enum variable contains a value, but nulldoesn't. If it's nullit can be interpreted that it has no value, you can't invoke non-static methods on it for example.

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

回答by zenbeni

You can add behaviour to your enums (Domain Driven Design), for instance add a public method named prettyPrint() that returns a String based on your enum value. How a default / null value can provide an implementation of this custom method?

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

If you want to represent null with an enum, then you'll have to explicit this by using a null object pattern manually with a NONE value and a custom implementation for prettyPrint() based on NONE value.

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

回答by user207421

Java allows any reference to be null, and references to enums aren't so special that a special case needs to be made to prevent it, or to provide another version of behaviour that is already well-specified and well-understood. Null is already a perfectly adequate sentinel value: we don't need another one.

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

Neither of your suggestions is convincing, as they would both require addition of yet further features to support them.

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

In any case it is several years too late to start debating the point.

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

回答by Hydroper

Old, I know. I'm half-in Java.

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

Why allow Enum to have a null value?

为什么允许 Enum 具有空值?

There are few use cases, I believe. For example, we need to initialize an enum variable to tell us it's not really part of the enum, but we can change its value later, so that it is part of it. If there was no way to initialize an enum variable as null, then we would pollute the enum definition. So, in my opinion, fields such as LibEnum.NONEmesses libraries. For example, you don't want one to use LibEnum.NONEas parameters for methods, between others.

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

I found it useful in my lexical scanner, among with keywords and punctuators. Suppose you've an identifier "blah". You then want to check if it's any keyword.

我发现它在我的词法扫描器中很有用,包括关键字和标点符号。假设您有一个 identifier "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;
}

Thanks to null, it's then easy to verify whether the identifier is not a keyword.

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

id == null

Otherwise we'd have to define something like Keywordv.__NULL

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