Как хранить пользовательские объекты в 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(); никогда не называется.