【问题标题】:Java compiler calls java.lang.ArrayIndexOutOfBoundsException without any reasonJava 编译器无故调用 java.lang.ArrayIndexOutOfBoundsException
【发布时间】:2016-07-13 13:37:08
【问题描述】:

我是 Java 新手。我正在尝试为自定义 PriorityQueue 创建一个方法,该方法必须使用一个数组,该数组合并 2 个 PriorityQueue。

问题是,虽然我的代码没有错误,但每当我在 main 中调用该方法时,Eclipse 中的 Java 编译器都会调用 java.lang.ArrayIndexOutOfBoundsException。

关于合并方法: 它基本上是一种将 2 个数组的元素合并到一个数组中的方法。然后它使用 extractMax 方法擦除第二个数组的所有元素:

到目前为止,我的代码是这样的:

//Custom Priority Queue
class PriorityQueue {
    private int capacity;
    private int queue[];
    private int i;

    public PriorityQueue() {
        capacity = 100;
        queue = new int[100];
        i = 0;
    }

    public PriorityQueue(int size) {
        capacity = size;
        queue = new int[size];
        i = 0;
    }

    protected void quickSort(int left, int right) {
        int i = left, j = right;
        int pivot = queue[(left + right) / 2];

        while (i <= j) {
            while (queue[i] > pivot)
                i++;
            while (queue[j] < pivot)
                j--;
            if (i <= j) {
                int temp = queue[i];
                queue[i] = queue[j];
                queue[j] = temp;
                i++;
                j--;
            }
        }
        if (left < j)
            quickSort(left, j);
        if (i < right)
            quickSort(i, right);
    }

    public boolean insert(int number) {
        if(i < capacity) {
            queue[i] = number;
            quickSort(0, i++);
            return true;
        }
        return false;
    }

    public int extractMax() {
        if(i == 0)
            return -1;
        else {
            int tempQueue[] = new int[i-1];
            int temp = queue[0];

            for(int j=0; j<i-1; j++)
                tempQueue[j] = queue[j+1];
            queue = tempQueue;
            i--;
            return temp;
        }
    }

    public boolean merge(PriorityQueue myPriorityQueue) {
        if(i + myPriorityQueue.i < capacity) {
            for(int j=0; j<myPriorityQueue.i; j++)
                queue[i++] = myPriorityQueue.extractMax();
            quickSort(0, i-1);
            return true;
        }       
        return false;
    }

//Test Class
class PriorityQueueTest
{
    public static void main(String args[])
    {
        PriorityQueue PQ1 = new PriorityQueue();
        PriorityQueue PQ2 = new PriorityQueue();

        PQ1.insert(1);
        PQ1.insert(3);
        PQ1.insert(5);
        PQ2.insert(2);
        PQ2.insert(4);
        PQ2.insert(6);

        PQ1.merge(PQ2);     
    }
}

所以每当我在 Eclipse 中运行它时,我都会得到:

java.lang.ArrayIndexOutOfBoundsException: 2
at PriorityQueue.merge(PriorityQueue.java:89)
at PriorityQueueTest.main(PriorityQueueTest.java:22)

我试图弄清楚它为什么会这样,但它没有任何意义。 在本例中,2 个 PriorityQueue 的长度不超过 PriorityQueue1 的容量。当我尝试访问 PriorityQueues 元素时一定有问题。

谢谢,感谢任何帮助。

【问题讨论】:

  • 第 89 行是哪一行?
  • sry,实际上是第 88 行,第 88 行是:Queue[i++] = myPriorityQueue.extractMax();
  • 你试过逐行调试你的代码吗?
  • 只是为了澄清-编译器不会调用异常,这发生在运行时,正确的术语是“抛出”异常。编译器为您做其他事情,例如检查您尝试访问的索引是否为整数,但它不知道该索引是否存在。只有在程序运行时才能对此进行验证。至此,编译器已经完成了它的工作,已经不在了。

标签: java arrays eclipse merge queue


【解决方案1】:

问题出在这里:

for(int j=0; j<myPriorityQueue.i; j++)
            Queue[i++] = myPriorityQueue.extractMax();
        QuickSort(0, i-1);
        return true;

更具体地说,由于您使用Queue[i++] 递增i - 这是您的类变量i,而不是本地变量 - j 将始终小于myPriorityQueue.i。因此,此循环将一直运行直到j 超过capacity 并在您尝试访问大于其长度的Queue[] 元素时抛出ArrayIndexOutOfBounds 异常。在这样的循环中,您通常会使用j 来访问循环内数组中的元素:

for(int j=0; j<myPriorityQueue.i; j++)
            Queue[j] = myPriorityQueue.extractMax();
        QuickSort(0, i-1);

这种方式只会访问Queue[]i 中的元素,并且j 在循环的每次迭代结束时自动递增。

如果您选择使用 i 作为类变量之一来跟踪队列中有多少东西,而不是像 queuedstored 这样更具描述性的东西,那么事情会变得更加混乱因为ij 经常在循环中使用;当你的类也已经有一个变量i 时,你实际上确实在你的快速排序循环中使用了i。对循环计数器之外的变量使用不具描述性的名称是不好的做法,并且会使代码更难理解。

【讨论】:

  • 所以当我改变变量“i”时,我也改变了变量“myPriorityQueue.i”......你是对的,非常感谢!!!!
猜你喜欢
  • 1970-01-01
  • 2014-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 2012-11-10
相关资源
最近更新 更多