Java:为什么for循环和while循环之间的内存使用有差异?

时间:2014-11-11 21:19:33

标签: java loops memory java-8

我正在阅读XML文件并将其内容推送到ByteArrayOutputStream,如下所示:

static final MY_XML_FILE = new File("...");

byte[] buffer = new byte[(int) MY_XML_FILE.length()];
    int bytesRead;
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    while ((bytesRead = fileInputStream.read(buffer)) != -1)
        output.write(buffer, 0, bytesRead);

工作正常。

我不希望在bytesRead循环之外显示while的范围,因此我将其更改为for循环:

for (int bytesRead = fileInputStream.read(buffer); bytesRead != -1; )
    output.write(buffer, 0, bytesRead);

但是这会引发以下错误:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)

我的问题是:两种循环方式不一样吗?如果没有,那么我想知道forwhile循环在Java中的内存使用情况有何不同。

4 个答案:

答案 0 :(得分:7)

在for循环中,您只需设置一次bytesRead,而不是像while中那样设置每次迭代。 for - 相当于你的while循环:

for( int bytesRead; (bytesRead = fileInputStream.read(buffer)) != -1; )

或者以不同的方式:

for( int bytesRead = fileInputStream.read(buffer); bytesRead != -1; bytesRead = fileInputStream.read(buffer) )

答案 1 :(得分:2)

因为您永远不会在bytesRead循环中更新成为无限内存请求的for;

for (int bytesRead = fileInputStream.read(buffer); bytesRead != 1; )
    output.write(buffer, 0, bytesRead);

应该是(并检查bytesRead不是-1)

for (int bytesRead = fileInputStream.read(buffer); bytesRead != -1; ) {
    output.write(buffer, 0, bytesRead);
    bytesRead = fileInputStream.read(buffer);
}

我真的建议您尝试write dumb code

答案 2 :(得分:0)

for循环中,您正在检查是否bytesRead != 1;在while循环中,您正在检查是否bytesRead != -1

答案 3 :(得分:0)

当你在for中将第一个读取分配给bytesRead时,你将为bytesRead放置一个起始值。永远不会再被召唤。 Ence,你一遍又一遍地写,直到你的内存不足,因为bytesRead永远不会是-1。

更准确地说,想象一下典型的:for(int i =0;i<x;i++)。正如您从典型的int中看到的那样i = 0只被调用一次。将for读取内容并将bytesRead作为0。