Java - 索引超出界限异常:索引:1,大小:2

时间:2016-01-05 14:01:41

标签: java nullpointerexception indexoutofboundsexception

在处理某个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?

3 个答案:

答案 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