我正在构建一个经典的尼姆游戏,只使用数组,测试后发现有一个bug。如果我成功创建了一个玩家,我会为数组分配一个新对象。然而,当删除数组中的播放器时,我会用非null对象过滤数组,因为我有其他函数,如editplayer
、displayplayer
,可以在没有NullPointerException
的情况下迭代整个数组。
这种情况有可能发生:addplayer
→removeplayer
→addplayer
。这意味着当我试图将一个新对象分配给已经充满非null对象的数组时,我总是会得到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
}
- 与其解释这些异常,我建议您查看NullPointerException和ArrayIndexOutOfBoundsException的文档。当这些异常发生时,处理它们并不是什么大不了的事。然而,最重要的是预防它们,即你应该了解根本原因并采取措施。我们都知道,"预防胜于治疗。">
- 您应该始终尝试从类中隐藏尽可能多的信息,例如,您已经有了
public static void createPlayer
,那么,为什么要创建public
构造函数呢?为什么为counter
创建了一个public
getter,它只能在类NimPlayer
中内部使用 - 您应该删除其
public
setter并创建类似于public static void createPlayer
的public static void removePlayer
,而不是从外部公开要设置的playerList
附带说明(因为它不会影响程序的执行(,标识符的名称应该是不言自明的,例如,您的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
要回答您的问题:"有没有办法同时避免NullPointerException和IndexOutOfBound?">
是的,你可以通过使用以下两件事来做到这一点。
首先,可以使用数组的length
属性来获取数组的长度。length
是数组中元素的数量(包括值为null
的元素(。有了这些信息,您就不应该索引越界(只要您没有编写修改数组长度的并发代码(。
其次,您需要检查从数组中取出的内容,看看它是否为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中,因为它们对NimPPlayer中的数据进行操作。
我猜你是Java和编程的新手。祝你学习好运!