在处理某个java项目时,我遇到了这个特殊的错误:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 2
如何有一个索引超出范围的例外?索引1表示它试图获取第二个元素,大小2表示有2个元素,所以不应该是一个问题,不是吗?
上下文:
我有以下功能:
public int howManyAgents(){
// cell is a class that can have 0 or multiple objects
// I get a list of cells that contain at least 1 agent
List<Cell> cellsWithAgents = getNonEmptyCells();
// initializing a counter
int agentsCount = 0;
for(int i=0; i<cellsWithAgents.size(); i++){
// For every cell in the list I add to the counter the number of
// agents that cell contains
agentsCount += cellsWithAgents.get(i).howManyAgents();
}
return agentsCount;
}
现在,问题是我在这一行得到了一个空指针异常:
agentsCount += cellsWithAgents.get(i).howManyAgents();
我想调试代码,但是在程序运行时多次调用此函数,并且在不同的时间点(5分钟后1分钟后10秒后)出现空指针异常。所以我尝试在单元格为空时提出一个方法来获得断点,所以我提出了这个代码:
public int howManyAgents(){
// cell is a class that can have 0 or multiple objects
// I get a list of cells that contain at least 1 agent
List<Cell> cellsWithAgents = getNonEmptyCells();
// initializing a counter
int agentsCount = 0;
for(int i=0; i<cellsWithAgents.size(); i++){
int pass;
if (null == cellsWithAgents.get(i))
pass = 1; // breakpoint here
// For every cell in the list I add to the counter the number of
// agents that cell contains
agentsCount += cellsWithAgents.get(i).howManyAgents();
}
return agentsCount;
}
当然,这不是最好的方法。最合乎逻辑的方法是用try / catch包围代码并将断点放在那里。关键是上面的代码没有用。它没有在断点处停止,而是将索引抛出界限处的异常:
if (null == cellsWithAgents.get(i))
为什么呢?如果索引显然在边界内,怎么可能抛出索引超出绑定的异常呢?
编辑:更改了复制代码的错误
更新: 我试图了解为什么空指针异常与try / catch一起出现并在那里放置一个断点。似乎cellsWithAgent有时包含null。这很可能是因为@rlinden所说的并发性。
关于并发性:有些单元格可以包含代理程序。可以在单元格之间移动的代理数量可变。有一个特殊的代理程序试图计算有多少移动代理程序(使用此功能)。 因此,只有一个代理(线程)可以使用此函数,但多个代理可以修改单元格(因此混淆了getNonEmptyCells()和howManyAgents()结果)。
但是,如何才能使索引超出大小2和索引1?由于并发性,这是不可能的,是吗?因为只有这个线程才能更改列表cellsWithAgents。因此,即使列表中的某个元素变为空,列表仍然包含该指针数,因此列表的大小不能更改。或者它可以以某种方式让我想念? 如何解释堆栈跟踪打印索引:1大小:2?
答案 0 :(得分:2)
新主意
尝试更改循环并查看错误是否仍然存在:
int agentsCount = 0;
for(Cell cell : getNonEmptyCells()) {
if(cell != null) {
agentsCount += cell.howManyAgents();
} else {
System.out.println("Found a null cell");
}
}
答案 1 :(得分:1)
我希望看到方法getNonEmptyCells()
的代码。如果您的程序实际上是多线程的,并且此函数返回在每次交互时更改的固定List,则后续执行中的更改可能会影响以前的未完成的。
这是因为行cellsWithAgents = getNonEmptyCells();
不会创建副本,而是对getNonEmptyCells()
的返回值的引用。因此,如果此方法重用了返回对象,则第一次执行可能会认为有两个,但是伴随线程将内容大小更改为小于2.
答案 2 :(得分:1)
问题是,程序在cellsWithType.get(i)
抛出异常。您可以做的是在if (null == cellsWithType.get(i))
放置一个断点并尝试调试它。或者改为,
if (i >= cellsWithType.size())
pass = 1; // breakpoint here