Как снова добавить объект после фильтрации массива с ненулевым объектом - PullRequest
1 голос
/ 29 апреля 2020

Я строю классическую игру Nim , используя только массив , и обнаружил, что после тестирования обнаружена ошибка. Если я успешно создаю игрока, я назначу новый объект массиву. Однако при удалении проигрывателя из массива я фильтрую массив с ненулевыми объектами, потому что у меня есть другие функции, такие как editplayer, displayplayer, для итерации всего массива без NullPointerException.

И есть вероятность, что это произойдет: addplayerremoveplayeraddplayer. Это означает, что я всегда получу IndexOutOfBound, когда попытаюсь присвоить новый объект массиву, уже заполненному ненулевыми объектами.

Я искал всю информацию, которую мог, но есть нет такого обсуждения по этому поводу. Есть ли способ избежать одновременно NullPointerException и IndexOutOfBound?

Здесь приведен соответствующий код Nimsys:

public class Nimsys {

public static void addPlayer(String [] name) {
    if (name != null && name.length == 3) {
        for (int i = 0; i < NimPlayer.getCounter(); i++) {
            String userCheck = NimPlayer.getPlayer()[i].getUserName();
            if (userCheck.contains(name[0])) {
                System.out.println("The player already exists.\n");// Test if player has been created
                return;
            }
        }
        NimPlayer.createPlayer(name[0], name[1], name[2]);
        System.out.println("The player has been created.");
        return;
    } 
    System.out.println("Not Valid! Please enter again!");   
}

public static void searchAndRemovePlayer(String user) {
    NimPlayer [] playerList = NimPlayer.getPlayer();
    for (int i = 0; i < playerList.length; i++) {
        String userName =playerList[i].getUserName().trim();
        if (userName.equals(user)) {
            playerList[i] = null;
            System.out.println("Remove successfully!");
            NimPlayer.setPlayerList(playerList);
            return;
        }
    }
    System.out.println("The player does not exist.\n");

}
}

Это часть класса NimPlayer :

public class NimPlayer {
private String userName;
private String familyName;
private String givenName;
private int score;
private int gamePlayed;

private static int counter;
private static final int SIZE = 10;
private static NimPlayer[] playerList = new NimPlayer[SIZE]; // set an array here


//define NimPlayer data type
public NimPlayer(String userName, String surName, String givenName) {
    this.userName = userName;
    this.familyName = surName;
    this.givenName = givenName;

}
// create new data using NimPlayer data type
public static void createPlayer(String userName, String familyName, String givenName) {
    if (counter < SIZE) {
        playerList[counter++] = new NimPlayer(userName, familyName, givenName);
    } else {
        System.out.println("Cannot add more players.");
    }
}
public static int getCounter() {
    return counter;
}
public static NimPlayer [] getPlayer() {      
    return playerList;
}
public static void setPlayerList(NimPlayer [] newplayerList) {
    playerList = Arrays.stream(newplayerList).filter(Objects::nonNull).toArray(NimPlayer[]::new);
    counter = playerList.length;  //update the counter
}
    //setters and getters of the other variables
}

Ответы [ 2 ]

1 голос
/ 29 апреля 2020
  1. Вместо объяснения этих исключений я рекомендую вам go в документации NullPointerException и ArrayIndexOutOfBoundsException . Нетрудно справиться с этими исключениями, когда они возникают. Однако самое важное - это предотвратить их, то есть вы должны понять, что является причиной и работать над ними. Мы все знаем, «Профилактика лучше лечения». .
  2. Вы всегда должны стараться скрыть как можно больше информации от класса, например, тогда у вас уже есть public static void createPlayer, почему вы создали конструктор public? Почему вы создали public getter для counter, который предназначен для использования только внутри класса, NimPlayer?
  3. Вместо того, чтобы выставлять playerList для установки извне, вы должны удалите его public setter и создайте public static void removePlayer аналогично public static void createPlayer.

на примечании (потому что это не повлияет на выполнение программы), имя идентификатора должно быть самоочевидным, например, ваш метод getPlayer должен называться getPlayerList, поскольку он возвращает playerList, а не одного игрока.

Ниже приведен код, включающий эти комментарии:

import java.util.Arrays;
import java.util.Objects;

class NimPlayer {
    private String userName;
    private String familyName;
    private String givenName;
    private int score;
    private int gamePlayed;

    private static int counter;
    private static final int SIZE = 10;
    private static NimPlayer[] playerList = new NimPlayer[SIZE];

    private NimPlayer(String userName, String surName, String givenName) {
        this.userName = userName;
        this.familyName = surName;
        this.givenName = givenName;
    }

    public static void createPlayer(String userName, String familyName, String givenName) {
        if (counter < SIZE) {
            playerList[counter++] = new NimPlayer(userName, familyName, givenName);
        } else {
            System.out.println("Cannot add more players.");
        }
    }

    public static void removePlayer(NimPlayer player) {
        int i;
        for (i = 0; i < playerList.length; i++) {
            if (playerList[i] != null && playerList[i].getUserName().equals(player.getUserName())) {
                break;
            }
        }
        for (int j = i; j < playerList.length - 1; j++) {
            playerList[j] = playerList[j + 1];
        }
        counter--;
    }

    public static NimPlayer[] getPlayerList() {
        return Arrays.stream(playerList).filter(Objects::nonNull).toArray(NimPlayer[]::new);
    }

    public String getUserName() {
        return userName;
    }

    public String getFamilyName() {
        return familyName;
    }

    public String getGivenName() {
        return givenName;
    }

    @Override
    public String toString() {
        return userName + " " + familyName + " " + givenName;
    }
}

class NimSys {

    public static void addPlayer(String[] name) {
        if (name != null && name.length == 3) {
            NimPlayer[] playerList = NimPlayer.getPlayerList();
            for (int i = 0; i < playerList.length; i++) {
                String userCheck = playerList[i].getUserName();
                if (userCheck.contains(name[0])) {
                    System.out.println("The player, " + name[0] + " already exists.\n");
                    return;
                }
            }
            NimPlayer.createPlayer(name[0], name[1], name[2]);
            System.out.println("The player, " + name[0] + "  has been created.");
            return;
        }
        System.out.println("Not Valid! Please enter again!");
    }

    public static void searchAndRemovePlayer(String user) {
        NimPlayer[] playerList = NimPlayer.getPlayerList();
        for (int i = 0; i < playerList.length; i++) {
            String userName = playerList[i].getUserName().trim();
            if (userName.equals(user)) {
                NimPlayer.removePlayer(playerList[i]);
                System.out.println("The player, " + user + " removed successfully!");
                return;
            }
        }
        System.out.println("The player, " + user + "  does not exist.\n");
    }

    public static void displayPlayerList() {
        NimPlayer[] playerList = NimPlayer.getPlayerList();
        StringBuilder sb = new StringBuilder();
        for (NimPlayer player : playerList) {
            sb.append(player.getUserName()).append(" ").append(player.getFamilyName()).append(" ")
                    .append(player.getGivenName()).append(System.lineSeparator());
        }
        System.out.println(sb);
    }
}

public class Main {
    public static void main(String[] args) {

        NimSys.addPlayer(new String[] { "Harry", "Potter", "Harry" });
        NimSys.displayPlayerList();

        NimSys.searchAndRemovePlayer("Harry");
        NimSys.displayPlayerList();

        NimSys.addPlayer(new String[] { "Manny", "Richard", "Canty" });
        NimSys.displayPlayerList();

        NimSys.addPlayer(new String[] { "Arvind", "Kumar", "Avinash" });
        NimSys.displayPlayerList();

        NimSys.searchAndRemovePlayer("Manny");
        NimSys.displayPlayerList();

        NimSys.addPlayer(new String[] { "Ken", "Ken", "Thompson" });
        NimSys.displayPlayerList();

        NimSys.searchAndRemovePlayer("Ken");
        NimSys.displayPlayerList();

        NimSys.addPlayer(new String[] { "Ken", "Ken", "Thompson" });
        NimSys.displayPlayerList();

        NimSys.searchAndRemovePlayer("Ken");
        NimSys.displayPlayerList();

        NimSys.addPlayer(new String[] { "Ken", "Ken", "Thompson" });
        NimSys.displayPlayerList();
    }
}

Вывод:

The player, Harry  has been created.
Harry Potter Harry

The player, Harry removed successfully!

The player, Manny  has been created.
Manny Richard Canty

The player, Arvind  has been created.
Manny Richard Canty
Arvind Kumar Avinash

The player, Manny removed successfully!
Arvind Kumar Avinash

The player, Ken  has been created.
Arvind Kumar Avinash
Ken Ken Thompson

The player, Ken removed successfully!
Arvind Kumar Avinash

The player, Ken  has been created.
Arvind Kumar Avinash
Ken Ken Thompson

The player, Ken removed successfully!
Arvind Kumar Avinash

The player, Ken  has been created.
Arvind Kumar Avinash
Ken Ken Thompson
1 голос
/ 29 апреля 2020

Чтобы ответить на ваш вопрос: «Есть ли способ избежать и NullPointerException, и IndexOutOfBound одновременно?»

Да, вы можете сделать это, используя следующие две вещи.

Сначала вы можете получить длину массива, используя его свойство length. length - количество элементов в массиве (включая те, чье значение равно null). С этой информацией вы никогда не должны индексировать вне границ (если вы не пишете параллельный код, который изменяет длину массива).

Во-вторых, вам нужно проверить, что вы вынимаете из массива, чтобы увидеть если это ноль. Вы можете просто сделать это с помощью оператора if.

Вот как это будет выглядеть:

// create an array with 5 elements. 0, 2, and 4 are null. 1 and 3 are not null.
String[] myArray = new String[5];
myArray[1] = "abc ";
myArray[3] = "def";

// myArray.length will be '5'
for (int i = 0; i < myArray.length; i++){
  String value = myArray[i];

  if (value != null) {
    // prints "ABC DEF" and doesn't result in a NullPointer
    System.out.print(value.toUpperCase());
  }
}

Итак, в вашем случае:

public static void addPlayer(String [] name) {
    if (name != null && name.length == 3) {
        for (int i = 0; i < NimPlayer.getPlayer().length; i++) {
            NimPlayer player = NimPlayer.getPlayer()[i];

            if (player != null && player.getUserName().contains(name[0]))
                System.out.println("The player already exists.\n");
                return;
            }
        }
        NimPlayer.createPlayer(name[0], name[1], name[2]);
        System.out.println("The player has been created.");
        return;
    } 
    System.out.println("Not Valid! Please enter again!");   
}

И просто добавить , В объектно-ориентированном программировании вы, как правило, хотите следовать принципу инкапсуляции - поэтому вы, вероятно, хотите переместить методы из NimSys в NimPlayer, поскольку они работают с данными в NimPlayer.

Полагаю, вы новичок в Java и программирование. Удачи в обучении!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...