Как хранить пользовательские объекты в ArrayList

Я делаю игру с карточками, карточками персонажей.

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

Дело в том, что когда я пытаюсь получить класс Card из списка и вызывать его методы getPlayer() и getCharacter (которые возвращают имя игрока и имя персонажа конкретной карты), я получаю исключение nullPointer.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.leonardo.lupusintabula.characters.Card.getCharacter()' on a null object reference

randomButton.setText(characters.get(0).getCharacter() + " / " + characters.get(0).getPlayer());

OnCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_random_assignment);

    //Retrieving
      ...
    //Done retrieving
    initializeVariables();
    createCharacters();
    run();
}

Поскольку проблема, вероятно, в символах, я перечисляю вам весь код, в котором он находится:

// Where the characters are stored
private ArrayList<Card> characters;


public void initDeck() {
    addCharacter(demoniac, demoniacAmount, characters);
    addCharacter(guard, guardAmount, characters);
    addCharacter(medium, mediumAmount, characters);
    addCharacter(mythomaniac, mythomaniacAmount, characters);
    addCharacter(owl, owlAmount, characters);
    addCharacter(werehamster, werehamsterAmount, characters);
    addCharacter(getVillagerBundle(), villagerAmount, characters);
    addCharacter(masonOne, 1, characters);
    addCharacter(masonTwo, 1, characters);
}

public void addCharacter(Card card, int amount, List<Card> cards) {
    if (amount < 0) {
        throw new IllegalArgumentException("Must add a non-negative number of characters for " + card.getCharacter() );
    }

    for (int i = 0; i < amount; i++) {
        cards.add(card);
    }
}



//Pick a random one and display it
public void pick(View view){
    if(characters != null) {
        if (i < characters.size()) {
            randomButton.setText(characters.get(i).getCharacter() + " / " + characters.get(i).getPlayer());
            i++;
        } else {
            randomButton.setText(R.string.play);
        }
    }
}

void run() {
    // initialize the characters
    initDeck();

    // shuffle them
    Collections.shuffle(characters);

    //Display the 1st card
    if(characters != null) {
        randomButton.setText(characters.get(0).getCharacter() + " / " + characters.get(0).getPlayer());
    }
}


private void initializeVariables() {
    ...
    ...

    characters = new ArrayList<Card>();
 }

}

Что я делаю неправильно? Если вам нужна другая часть кода, не стесняйтесь спрашивать, я предоставлю ее вам как можно скорее!

Это может свести вас с ума, но я нашел единственный способ добиться создания персонажей (каждый персонаж расширяет класс Card!):

public void createCharacters() {
    if (demoniacAmount != 0) {
        demoniac = new Demoniac(nameList.get(listIndex));
        listIndex++;
    } else if (guardAmount != 0) {
        guard = new Guard(nameList.get(listIndex));
        listIndex++;
    } else if (mediumAmount != 0) {
        medium = new Medium(nameList.get(listIndex));
        listIndex++;
    } else if (mythomaniacAmount != 0) {
        mythomaniac = new Mythomaniac(nameList.get(listIndex));
        listIndex++;
    } else if (owlAmount != 0) {
        owl = new Owl(nameList.get(listIndex));
        listIndex++;
    } else if (werehamsterAmount != 0) {
        werehamster = new Werehamster(nameList.get(listIndex));
        listIndex++;
    } else if (masonsAmount != 0) {
        masonOne = new Masons(nameList.get(listIndex));
        masonTwo = new Masons(nameList.get(listIndex));
        listIndex += masonsAmount;
    } else if (villagerAmount > 5) {
            villagerSix = new Villager(nameList.get(listIndex));
            villagerBundle.add(villagerSix);

            if (villagerAmount > 6) {
                villagerSeven = new Villager(nameList.get(listIndex));
                villagerBundle.add(villagerSeven);

                if (villagerAmount > 7) {
                    villagerEight = new Villager(nameList.get(listIndex));
                    villagerBundle.add(villagerEight);

                    if (villagerAmount > 8) {
                        villagerNine = new Villager(nameList.get(listIndex));
                        villagerBundle.add(villagerNine);

                        if (villagerAmount > 9) {
                            villagerTen = new Villager(nameList.get(listIndex));
                            villagerBundle.add(villagerTen);

                            if (villagerAmount > 10) {
                                villagerEleven = new Villager(nameList.get(listIndex));
                                villagerBundle.add(villagerEleven);

                                if (villagerAmount > 11) {
                                    villagerTwelve = new Villager(nameList.get(listIndex));
                                    villagerBundle.add(villagerTwelve);

                                    Toast.makeText(RandomAssignment.this, "works", Toast.LENGTH_SHORT).show();
                                }
                            }
                        }
                    }
                }
            }
        }
        listIndex += villagerAmount;
    }

2 ответа

Решение

Из моего другого ответа, из которого вы взяли мой код. initDeck Метод на самом деле читается так

public void initDeck() {
    if (characters == null)
        characters = new ArrayList<String>();

        // addCharacter...

Это по крайней мере позволит избежать нулевого указателя в списке...


Вам нужно добавить больше кода к вашему вопросу, но проблема начинается в этом блоке

addCharacter(demoniac, demoniacAmount, characters);
addCharacter(guard, guardAmount, characters);
addCharacter(medium, mediumAmount, characters);
addCharacter(mythomaniac, mythomaniacAmount, characters);
addCharacter(owl, owlAmount, characters);
addCharacter(werehamster, werehamsterAmount, characters);
addCharacter(getVillagerBundle(), villagerAmount, characters);
addCharacter(masonOne, 1, characters);
addCharacter(masonTwo, 1, characters);

который (примерно) называет этот код

public void addCharacter(Card card, int amount, List<Card> cards) {
    for (int i = 0; i < amount; i++) {
        cards.add(card);
    }
}

Проблема в том, что где-то ЛЮБЫЕ из этих переменных являются нулевыми, и они добавляются в список как таковые

  • demoniac
  • guard
  • medium
  • mythomaniac
  • owl
  • werehamster
  • getVillagerBundle()
  • masonOne
  • masonTwo

Вы можете исправить это, назначив все эти переменные new Card()или избежать проблемы, как это

public void addCharacter(Card card, int amount, List<Card> cards) {
    for (int i = 0; i < amount; i++) {
        if (card != null) {
            cards.add(card);
        } else {
            Log.e("addCharacter", "Hey! Are you sure you meant to add a null card?");
        }
    }
}

Теперь, когда вы показали больше кода, ошибка начинается здесь

if (demoniacAmount != 0) {
    demoniac = new Demoniac(nameList.get(listIndex));
    listIndex++;
} else if (guardAmount != 0) {
    guard = new Guard(nameList.get(listIndex));
    listIndex++;
}

Что, если demoniacAmount а также guardAmount оба не равны нулю? Только сначала, если будет введено условие. А также guard в конечном итоге будет нулевым, потому что он никогда не был инициализирован. Нет смысла делать else-if для совершенно разных переменных!

Надлежащим образом выполняйте проверку if для всех этих условий. (И я оставлю грязный код столько, сколько это беспокоит меня)

if (demoniacAmount != 0) {
    demoniac = new Demoniac(nameList.get(listIndex));
    listIndex++;
} 

if (guardAmount != 0) {
    guard = new Guard(nameList.get(listIndex));
    listIndex++;
}

Согласно вашим журналам: characters.get(0) дает null, и вы пытаетесь вызвать getCharacter(), следовательно, исключение нулевого указателя.

Проверьте, где ваш размер символов получает 0 или по ошибке вы назначаете его новому объекту.

Лучший способ - применить проверку для if(characters.size() > 0), тогда только вы получаете символы.

Вы не инициализировали переменные initializeVariables(); никогда не называется.

Другие вопросы по тегам