Исключение нулевого указателя в Java Enum - PullRequest
0 голосов
/ 19 июня 2019

Я изучаю концепцию Enum в Java и столкнулся с проблемой во время практики.

Вот фрагмент кода,

public class MyClass {
    private String cardColor = CARDS.SPADE.cardColor; #Causes Null Pointer #Default Value
    private MyClass(CARDS card){
        this.cardColor = card.cardColor;
    }
    public static enum CARDS{
        SPADE("Black"),
        CLUB("Black"),
        DIAMOND("Red"),
        HEART("Red");
        private String cardColor = null;
        private MyClass obj = null;
        CARDS(String color){
            this.cardColor = color;
            obj = new MyClass(this);         #Trying to create object for MyClass 
        }
        public String getCardColor(){
            return this.cardColor;
        }
    }
    public static void main(String args[]) {
        System.out.println(CARDS.SPADE);
    }
}

Я пытаюсь создать объект MyClass, приватный для enum в его конструкторе. Здесь значение CARDS.SPADE равно нулю, и я получаю исключение пустого указателя.

Если я не создаю объект в конструкторе enum, все работает отлично,

obj = new MyClass (this);

Я не понимаю, почему статическое перечисление не инициализируется, и я запутался с потоком управления здесь. Может кто-нибудь объяснить мне, что здесь не так?

1 Ответ

1 голос
/ 19 июня 2019

У вас круговая зависимость: инициализация перечисления CARDS и экземпляра MyClass зависят друг от друга.
CARDS конструктор создает экземпляр MyClass, но конструктор MyClass полагается на CARDS.SPADE состояние, которое еще не полностью инициализировано, как в ожидающем конструкторе перечисления.

Либо прервите этот цикл, либо сделайте что-нибудь два раза.Инициируйте перечисление без двунаправленного отношения и после вызовов конструктора установите значение перечисления на экземпляр MyClass через установщик.

Обратите внимание, что "настоящая" причина NullPointerException заключается в том, что вы не ссылаетесь на текущий экземпляр, созданный в конструкторе enum (this), но ссылаетесь на значение enum из самого класса enum: MyClass.CARD.SPADE.
Первый имеет состояние, а второй еще нет, поскольку конструктор enum еще не вернулся.

Передав экземпляр enum в конструктор MyClass, он будет «работать»:

CARDS(String color){
        this.cardColor = color;
        obj = new MyClass(this);    
    }
}

// ...
public MyClass(CARDS cards){
     cardColor = cards.cardColor;
}

Но в общем случае передача this во время тела конструктора другому объекту /класс не очень хорошая идеяЭто может просочиться в несогласованное состояние, если состояния объекта изменяются между этим временем и окончанием вызова конструктора.

...