简体   繁体   English

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

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

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.如果您希望我这样做,我可以发布创建 Enum 并将其分配给null代码。 :)) :))

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 常量是隐式的staticfinal Enum is meant to say - "I can take a value of one of the constants present in me". Enum 的意思是 - “我可以取一个存在于我中的常量的值”。 Why allow Enum to have a null value?为什么允许 Enum 具有null值? Why not implicitly default the Enum's value to a Enum.DEFAULT or Enum.None ?为什么不将 Enum 的值隐式默认为Enum.DEFAULTEnum.None Isn't this a better approach than allowing the Enum to be null ?这不是比允许 Enum 为null更好的方法吗?

Firstly null means non-existence of an instance.首先, null表示实例不存在。 Providing a default constant like DEFAULT or NONE , will change that meaning.提供像DEFAULTNONE这样的默认常量会改变这个含义。 Secondly, why would you need something default to represent what seems to be non-existent?其次,为什么你需要一些默认的东西来代表似乎不存在的东西? That is the purpose of null .这就是null的目的。 Basically, you would have to initialize and store an extra object, which shouldn't even exist whatsoever.基本上,您必须初始化并存储一个额外的对象,该对象甚至不应该存在。

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 UNKNOWN in your enum, and avoid the assignment of null to the reference in your code.您可以在枚举中提供另一个常量,如DEFAULTUNKNOWN ,并避免将null分配给代码中的引用。 This is famously known as Null Object Pattern .这就是众所周知的空对象模式 But saying that the null assignment should itself be compiler error, then I would say, since an Enum is anyways compiled to a Class , so it would be perfectly valid to use null to represent non-existence of an instance.但是说null赋值本身应该是编译器错误,那么我会说,因为无论如何Enum被编译为Class ,所以使用null来表示实例的不存在是完全有效的。

One pitfall of allowing null though is with the usage of enum in switch-case .允许null一个陷阱是在switch-case使用enum The below code will throw NPE , even with a default case:即使使用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 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 标签必须是枚举常量的非限定名称

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. Java 允许任何引用为空,并且对枚举的引用并没有那么特殊,以至于需要进行特殊情况来阻止它,或者提供已经明确指定和易于理解的另一个版本的行为。 Null is already a perfectly adequate sentinel value: we don't need another one. 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.无论如何,现在开始辩论这个问题已经晚了几年。

I think, Enum.DEFAULT means that your enum variable contains a value, but null doesn't.我认为, Enum.DEFAULT意味着您的 enum 变量包含一个值,但null不包含。 If it's null it can be interpreted that it has no value, you can't invoke non-static methods on it for example.如果它为null则可以将其解释为没有值,例如,您不能在其上调用非静态方法。

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.您可以向您的枚举添加行为(域驱动设计),例如添加一个名为 prettyPrint() 的公共方法,该方法根据您的枚举值返回一个字符串。 How a default / null value can provide an implementation of this custom method?默认值/空值如何提供此自定义方法的实现?

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() 自定义实现来明确这一点。

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.例如,我们需要初始化一个 enum 变量来告诉我们它实际上不是 enum 的一部分,但是我们可以稍后更改它的值,使其成为它的一部分。 If there was no way to initialize an enum variable as null , then we would pollute the enum definition.如果无法将枚举变量初始化为null ,那么我们将污染枚举定义。 So, in my opinion, fields such as LibEnum.NONE messes libraries.因此,在我看来,诸如LibEnum.NONE字段会LibEnum.NONE库。 For example, you don't want one to use LibEnum.NONE as parameters for methods, between others.例如,您不希望将LibEnum.NONE用作方法的参数,等等。

I found it useful in my lexical scanner, among with keywords and punctuators.我发现它在我的词法扫描器中很有用,包括关键字和标点符号。 Suppose you've an identifier "blah" .假设您有一个标识符"blah" You then want to check if it's any keyword.然后你想检查它是否是任何关键字。

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东西

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

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