抱歉,如果由于我遗漏了一些明显的东西而在某个地方得到了回答,但我已经用谷歌搜索了好几天了,但它似乎没有任何意义。我在 Javascript 方面有 3 年的经验,现在正在学习 Java,所以我并不落后于任何事物的基本概念。
我为此使用了 IntelliJ,但它没有指出问题所在。我的类之间的通信(访问权限和实例化)很好,代码语法和变量类型也很好,所以我真的不知道它是什么。
我有一个数据类,它只保存供其他类使用的“只读”数据。
public class Data {
// snip
public static int[][] specs = {
{6,1,6,40},
{5,2,5,30},
{5,3,4,40},
{4,4,3,60}
};
}
还有另一个类在初始化时必须读取此数据。
public class Soldier {
// snip
public int range;
public Soldier() {
int x = ...; // user input
range = Data.specs[x][1];
}
}
specs 数组本身包含其定义的数据(即数组不为空),x 作为 specs 数组的索引有效(即 0 <= x <= 3),其类型为 int 且 Test 已读取访问 specs 数组(全部通过调试输出语句确认)。然而,当它尝试设置范围的值时(然后并且只有那时,在那个确切的点),我得到了“索引越界”错误。
有人可以告诉我在尝试读取数组时出了什么问题吗?或者我说这真的很奇怪并且我需要发布整个代码是否正确?
注意:一个新的小测试还表明,如果我将代码更改为首先从数组中输出手动选择的值,然后设置范围值,控制台将打印错误语句(并退出程序)并执行以下操作它通过打印手动选择的值来解决,但是分配值然后询问输出范围只会抛出错误......这完全没有意义!
编辑:我已经编辑了上面的代码。名为 Test 的类在我的代码中称为 Soldier(我正在制作基于文本的游戏......)。下面是堆栈跟踪,如果没有完整的代码(太长了)它有什么好处的话。我的程序的基本结构是这样的:
1) Boot包含main方法并实例化一个新的Game
2) 游戏实例化 x 个团队
3) 每个Team实例化一个Army
4) 每个陆军实例化 x 个士兵
类的每个实例都设置为实例化类的一个属性(例如,公共(public)陆军;以及团队构造函数中的陆军实例)。它本质上是级联的构造函数实例化后续类并将它们分配为其属性。
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Army.<init>(Army.java:13)
at Team.<init>(Team.java:19)
at Game.<init>(Game.java:22)
at Boot.main(Boot.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)5
编辑编辑:这是半完整的代码(我省略了与它完全无关的东西,包括导入)。它没有特定的顺序,类位于 IntelliJ 项目中的单独 .java 文件中。游戏继续进行,直到新士兵要求指定其类型(执行用户输入的功能工作正常并验证输入,正如游戏的技术上相同的其他部分所证明的那样)。
public class Boot {
public static void main(String[] args) {
Object[] games = new Object[] {};
if (Lib.userConfirmPrompt("Start the game?") == true) {
do {
games[games.length] = new Game();
}
while (Lib.userConfirmPrompt("Do you want to play again?") == true);
}
System.exit(0);
}
}
public class Game {
public Object[] teams = new Object[] {};
public Game() {
for (int i = 0;i < settings.xbots + 1;i++) {
teams[teams.length] = new Team(this);
}
}
}
public class Team {
public Game game;
public Army army;
public Team(Game p) {
game = p;
army = new Army(this);
}
}
public class Army {
public Team team;
public static Object[] soldiers = new Object[] {};
public Army(Team p) {
team = p;
for (int i = 0;i < team.game.settings.xsoldiers;i++) {
soldiers[soldiers.length] = new Soldier(this);
}
}
}
public class Soldier {
private Army army;
public int sight;
public int range;
public int distance;
public int damage;
public Soldier(Army p) {
army = p;
int type = Lib.userTxtIntOptionsPrompt(Data.isoldiertypes);
// HERE is where it crashes, type is assigned and valid but the array access fails
sight = Data.isoldierspecs[type][0];
range = Data.isoldierspecs[type][1];
distance = Data.isoldierspecs[type][2];
damage = Data.isoldierspecs[type][3];
}
}
public class Data {
public static List isoldiertypes = Arrays.asList("Scout","Private","Machinegunner","Grenadier");
public static int[][] isoldierspecs = {
{6,1,6,40},
{5,2,5,30},
{5,3,4,40},
{4,4,3,60}
};
}
public class Lib {
private static Scanner input = new Scanner(System.in);
// output
// default: 1 query string to print
public static void outBase(String query) {
System.out.print(query);
}
public static void outStd(String query) {
outBase(query + "\n");
}
// end of output
// input
// default: 1 query string to print,
// query and input are in-line (exception: userConfirmPrompt prints query block-wise and default instruction in-line before input),
// keeps user hostage until valid input is given (exception: userPrompt returns blindly)
public static String userPrompt(String query) {
outBase(query);
return input.nextLine();
}
public static String userTxtPrompt(String query) {
String menuinput = null;
do {
if (menuinput != null) {
userHostage();
}
menuinput = userPrompt(query);
} while (menuinput.length() == 0);
return menuinput;
}
public static int userIntPrompt(String query) {
String menuinput = null;
do {
if (menuinput != null) {
userHostage();
}
menuinput = userTxtPrompt(query);
} while(menuinput.matches("^-?\\d+$") == false);
return new Integer(menuinput);
}
// end of input
// options input
// default: takes a List of options as argument,
// prints an enumerated list of these options string-wise,
// prompts for a numeral selection of the desired option and returns the number if valid
public static int userTxtIntOptionsPrompt(List options) {
int choice = 0;
Boolean chosen = false;
do {
if (chosen == true) {
userHostage();
} else {
chosen = true;
}
chosen = true;
for (int i = 0;i < options.size() - 2;i++) {
outStd((i + 1) + ") " + options.get(i) + ",");
}
outStd((options.size() - 1) + ") " + options.get(options.size() - 2) + "\nand " + options.size() + ") " + options.get(options.size() - 1) + ".");
choice = userIntPrompt("Enter the number of the option you'd like to select: ") - 1;
} while(choice < 0 || choice >= options.size());
return choice;
}
// end of options input
// miscellaneous
public static void userHostage() {
outStd("Invalid operation. Please try again.");
}
}
最佳答案
问题出在您的 Army
类中:
public static Object[] soldiers = new Object[] {};
您初始化了一个名为soldiers
的空(长度== 0)数组,但稍后您访问:
soldiers[soldiers.length] = new Soldier(this);
这会导致失败。
根据定义,soldiers.length
超出了数组的边界(因为边界是从 0
到 soldiers.length-1
)
要克服它 - 确保在数组 soldiers
中分配足够的空间或使用动态数组 ( ArrayList
) 代替。您可以使用 ArrayList.add()
将元素附加到 ArrayList
,并且在填充之前不需要知道预期的大小。
关于Java:数组中的索引存在,ArrayIndexOutOfBoundsException:0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12877866/