简体   繁体   English

Java-索引越界异常:索引:1,大小:2

[英]Java - Index Out Of Bounds Exception: Index: 1, Size: 2

While working on some java project I encountered this peculiar error: 在某些Java项目上工作时,我遇到了这个奇怪的错误:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 2

How can there be an index out of bounds exception? 怎么会有索引超出范围异常? Index 1 means it tries to get the second element, Size 2 means there are 2 elements, so there shouldn't be a problem, no? 索引1表示它试图获取第二个元素,大小2表示有2个元素,所以应该没有问题,不是吗?

Context: 语境:

I have the following function: 我有以下功能:

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;
}

Now, the problem was that I got a null pointer exception at the line: 现在的问题是,我在该行得到了一个空指针异常:

agentsCount += cellsWithAgents.get(i).howManyAgents();

I want to debug the code, but this function is called many times while the program is running and the null pointer exceptions comes up at different points in time (after 10 seconds after 1 minute after 5 minutes). 我想调试代码,但是在程序运行时会多次调用此函数,并且空指针异常会在不同的时间点出现(5分钟后的1分钟后为10秒)。 So I tried to come up with a method to have e breakpoint when the cell is null so I came up with this code: 因此,我尝试提出一种在单元格为null时具有e断点的方法,因此我想出了以下代码:

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;
}

Of course, it is not the best method. 当然,这不是最好的方法。 The most logical way is jut to surround the code with try/catch and put the breakpoint there. 最合乎逻辑的方法是,用try / catch包围代码,然后在其中放置断点。 The point is that the code above didn't work. 关键是上面的代码不起作用。 It did not stop at the breakpoint but instead it threw the index out of bounds exceptions at the line: 它并没有在断点处停止,而是将索引超出了该行的界限异常:

if (null == cellsWithAgents.get(i))

Why? 为什么? How can it be possible to throw an index out of bound exception if apparently the index is in bounds? 如果索引显然在边界内,怎么可能将索引抛出边界异常?

Edit: changed a mistake in copying the code 编辑:更改了复制代码时的错误

Update: I have tried to see why the null pointer exception appears with a try/catch and put a breakpoint there. 更新:我试图看看为什么空指针异常会出现try / catch并在其中放置一个断点。 It seems that cellsWithAgents sometimes contains a null. 似乎cellsWithAgents有时包含null。 This is, most probably because of concurrency as @rlinden stated. 这很可能是由于@rlinden指出的并发性。

About concurrency: there are some cells that can contain agents. 关于并发:有些单元格可以包含代理。 There is a variable number of agents that can move between the cells. 可以在单元之间移动的代理数量不固定。 There is a special agent that tries to count how many moving agents there are (using this function). 有一个特殊的座席试图计算有多少座席(使用此功能)。 So, only one agent (thread) can use this function, but multiple agents can modify cells (and thus mess with getNonEmptyCells() and howManyAgents() results). 因此,只有一个代理(线程)可以使用此功能,但是多个代理可以修改单元格(从而使getNonEmptyCells()和howManyAgents()结果混乱)。

Still, how it is possible to get index out of bounds with size 2 and index 1? 但是,如何才能使索引超出大小2和索引1的范围? It is not possible because of the concurrency, is it? 因为并发,所以不可能吗? Because only this thread can change the list cellsWithAgents. 因为只有该线程才能更改列表cellsWithAgents。 So, even if one of the elements in the list becomes null, the list still contains that number of pointers, so the size of the list cannot change. 因此,即使列表中的元素之一变为空,列表仍然包含该数量的指针,因此列表的大小无法更改。 Or can it in some way that I miss? 还是可以以某种我想念的方式? And how can it be explained that the stack trace prints Index:1 Size: 2? 以及如何解释堆栈跟踪打印索引:1大小:2?

New Idea 新思路

Try changing the loop and see if the error persists: 尝试更改循环,看看错误是否仍然存在:

int agentsCount = 0;
for(Cell cell : getNonEmptyCells()) {
    if(cell != null) {
       agentsCount += cell.howManyAgents();
    } else {
       System.out.println("Found a null cell");
    }
}

I would like to see the code of the method getNonEmptyCells() . 我想看一下getNonEmptyCells()方法的代码。 If your program is actually multithreaded and this function returns a fixed List that is changed at every interaction, then it is possible that changes in following executions have affected the previous, unfinished ones. 如果您的程序实际上是多线程的,并且此函数返回一个固定的List,该列表在每次交互时都会更改,则后续执行中的更改可能会影响之前未完成的执行。

This is due to the fact that the line cellsWithAgents = getNonEmptyCells(); 这是由于以下事实: cellsWithAgents = getNonEmptyCells(); does not create a copy, but a reference to the return value of getNonEmptyCells() . 不会创建副本,而是创建对getNonEmptyCells()返回值的getNonEmptyCells() So, if this method reuses the return object, it is possible that the first execution would believe there was two, but the concomitant thread changed the content size to less than 2. 因此,如果此方法重用了返回对象,则第一次执行可能会相信有两个,但是伴随的线程将内容大小更改为小于2。

The problem is, program is throwing exception at cellsWithType.get(i) . 问题是,程序在cellsWithType.get(i)cellsWithType.get(i)异常。 What you can do is either put a breakpoint at if (null == cellsWithType.get(i)) and try debug it. 您可以做的是在if (null == cellsWithType.get(i))处设置一个断点,然后尝试对其进行调试。 Or change it to, 或更改为

if (i >= cellsWithType.size())
        pass = 1; // breakpoint here

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM