0

I'm currently putting together a small client/server pair and I ran into a problem with ArrayLists, which I solved, but want to learn more about. Here's a sample of the code:

public double[] receiveMessage(int messageLength) throws IOException {
    // wait for bytes
    while (this.getInputStream().available() == 0) {
    }

    // read bytes
    List<byte[]> incomingMessage = new ArrayList<byte[]>();

    int byteLength = 8;
    byte[] tempByte = new byte[byteLength];
    while (this.getInputStream().available() != 0) {
        this.getInputStream().read(tempByte, 0, byteLength);
        incomingMessage.add(tempByte);
    } ............

If I were to print tempByte at each loop iteration, I receive the unique array I expected. But, if I were to print each element of the completed list "incomingMessage", I receive the same array (the last tempByte array) "messageLength" times.

This bug was fixed when I placed the tempByte declaration inside the while-loop and added a tempByte=null after the adding it to the list.

While I'm not a programming expert, what is the reason for the original bug I saw?

3 Answers 3

1

You were modifying the same byte[] object each time. You were replacing the elements of the array in each iteration of the while loop then you called read.

The reason that declaring tempByte inside the array fixes the issue is that you are now creating a new, separate byte array during each iteration. Instead of one array being added multiple times, you now have multiple different arrays added.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the specifics! Would you suggest any optimizations?
1

The problem is here:

byte[] tempByte = new byte[byteLength];
while (this.getInputStream().available() != 0) {
    //...
}

tempByte is initialized once and filled several times. In the end, you alter and store the same object reference stored in tempByte into incomingMessage, thus you see the same array several times in the List.

There are two possible solutions for this:

  1. Initialize the variables in the narrowest possible scope. In this case, tempByte scope should be inside the while loop:

    while (this.getInputStream().available() != 0) {
        //declare the variable here
        byte[] tempByte = new byte[byteLength];
        //...
    }
    
  2. Reinitialize the array on each iteration of the while loop:

    byte[] tempByte = new byte[byteLength];
    while (this.getInputStream().available() != 0) {
        //...
        //reinitialize the variable
        tempByte = new byte[byteLength];
    }
    

IMO you should choose 1 over 2 to ease readability of the code.

Comments

1

You are adding the same object (tempByte array) multiple times to the incomingMesage list. And in each iteration you overrite the content of this array.

If you want to store your data like that, you need to copy the tempByte to new Array which will you insert inot your list.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.