Подтвердить что ты не робот

Почему Java разрешает присвоение нулевого значения Enum

Это скорее вопрос дизайна. (Итак, нет кода. Я мог бы опубликовать код создания Enum и присвоить ему значение null, если вы хотите, чтобы я это сделал.:)) Я много думал об этом в последнее время, но не могу придумать одну вескую причину, Константы Enum неявно статичны и окончательны. Enum должен сказать: "Я могу принять значение одной из констант, присутствующих во мне". Зачем разрешать Enum иметь нулевое значение?. Почему бы не косвенно использовать значение Enum для параметра Enum.DEFAULT или Enum.None? Разве это не лучший подход, чем разрешение Enum на null?

4b9b3361

Ответ 1

Во-первых, null означает отсутствие экземпляра. Предоставление константы по умолчанию, такой как DEFAULT или NONE, изменит это значение. Во-вторых, зачем вам нужно что-то по умолчанию для представления того, что кажется несуществующим? Это цель null. По сути, вам придется инициализировать и хранить дополнительный объект, который вообще не должен существовать.

Кстати, это не выбор языка. Это полностью на вас, как вы реализуете свой enum. Вы можете указать другую константу, например, DEFAULT или UNKNOWN в вашем перечислении, и избежать присвоения null ссылки в вашем коде. Это известно как Нулевой Объектный Образец. Но говоря, что null присваивание само по себе должно быть ошибкой компилятора, тогда я бы сказал, поскольку Enum в любом случае компилируется в Class, так что было бы совершенно правильно использовать null для представления несуществования экземпляра.

Одна из ловушек, допускающих использование null связана с использованием enum в switch-case. Приведенный ниже код будет выбрасывать NPE, даже с регистром по 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 не позволяет case null: либо, что приводит к следующей ошибке компиляции:

метка регистра переключателя перечисления должна быть безусловным именем константы перечисления

Ответ 2

Я думаю, Enum.DEFAULT означает, что ваша переменная enum содержит значение, но null - нет. Если он null, его можно интерпретировать так, что он не имеет значения, вы не можете ссылаться на негостатические методы, например, на него.

Ответ 3

Вы можете добавить поведение в свои перечисления (Domain Driven Design), например, добавить открытый метод с именем prettyPrint(), который возвращает строку, основанную на вашем значении перечисления. Как значение по умолчанию /null может обеспечить реализацию этого пользовательского метода?

Если вы хотите представить нуль с перечислением, то вам нужно будет указать это с помощью шаблона нулевого объекта вручную с значением NONE и специальной реализацией для prettyPrint() на основе значения NONE.

Ответ 4

Java допускает, чтобы любая ссылка была нулевой, а ссылки на перечисления не столь особенны, что необходимо предусмотреть специальный случай, чтобы предотвратить ее, или предоставить другую версию поведения, которая уже хорошо указана и понятна. Null уже является вполне адекватным дозорным значением: нам не нужен другой.

Ни одно из ваших предложений не является убедительным, поскольку они оба потребуют добавления дополнительных функций для их поддержки.

В любом случае слишком поздно, чтобы начать обсуждение точки.

Ответ 5

Старый, я знаю. Я наполовину на Java.

Зачем разрешать Enum иметь нулевое значение?

По-моему, мало случаев использования. Например, нам нужно инициализировать переменную enum, чтобы сообщить нам, что она не является частью enum, но мы можем позже изменить ее значение, чтобы она была частью этого. Если бы не было возможности инициализировать переменную enum как null, мы бы загрязнили определение перечисления. Итак, на мой взгляд, такие поля, как LibEnum.NONE messes libraries. Например, вы не хотите использовать 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