更改数组中的值不会在传递给对象时更改值

时间:2013-03-28 13:22:50

标签: java arrays object

我正在与这个非常奇怪的问题作斗争,我希望有人可以向我解释原因。

我有这段代码通过Socket连接从文件传输数据。

    byte[] chunk = new byte[Constants.TRANSFER_CHUNK_SIZE];
    try (InputStream fileInputStream = new FileInputStream(sourceFile); BufferedInputStream buffFileInputStream = new BufferedInputStream(fileInputStream)) {
        while (offset < sourceFileSize) {
            int numBytes = buffFileInputStream.read(chunk, 0, Constants.TRANSFER_CHUNK_SIZE);
            Message chunkMessage = new Message(MessageType.SPM_TRANSFER_CHUNK, numBytes, null, chunk);
            this.sendMessage(chunkMessage);
        }
    }

方法sendMessage没有做任何特殊的事情,只需通过ObjectOutputStream发送对象:

private void sendMessage(Message message) {
    try {
       this.conOutputStream.writeObject(message);
       this.conOutputStream.flush();
    } catch (IOException ex) {
            ......
    }
}

Message类本身看起来像:

public class Message implements Serializable {

protected final MessageType type;
protected final int intValue;
protected final String stringValue;
protected byte[] data;
protected final long longValue;

public Message(MessageType type, int intValue, long longValue, String stringValue, byte[] data) {
    this.type = type;
    this.intValue = intValue;
    this.stringValue = stringValue;
    this.data = data;
    this.longValue = longValue;
}

................

}

当我在发送器端打印出块数组时数据没问题,但在接收器端我总是从第一个块接收数据,就像(只打印前三个字节):

RC: 73 68 51
RC: 73 68 51
RC: 73 68 51
RC: 73 68 51
.......

我已经知道的事情:

  • 问题不在传输中。
  • 在周期解决此问题的每个循环中创建一个新数组(但内存效率低,这就是我更改它的原因。)

提前致谢。

2 个答案:

答案 0 :(得分:0)

public SyncPlaneMessage(MessageType type, int intValue, long longValue, String stringValue, byte[] data) {
    // ...
    this.data = data;
    // ...
}

您正在保存对传入的数组的引用。如果在构造函数调用后该数组发生更改,那么this.data也是如此。这就是为什么创建数组的副本可以解决问题。

复制数组会占用更多内存,但您有什么选择?制作副本的正确位置至少在构造函数中,而不是在while循环中。

this.data = Arrays.copyOf(data, data.length);

答案 1 :(得分:0)

终于找到了解决这个问题的方法。 此问题是由序列化缓存引起的。 ObjectOutputStream不会发送相同的对象(即使已更改),如果它之前已经发送到同一个流。

在发送每条消息之前重置 ObjectOutputStream 解决了我的问题,可能会导致性能下降,但问题已解决。现在 ObjectOutputStream 总是发送新数据。

所以在我的情况下我修改了方法sendMessage(),所以它现在在发送消息对象之前重置 ObjectOutputStream

private void sendMessage(Message message) {
    try {
       this.conOutputStream.reset();
       this.conOutputStream.writeObject(message);
       this.conOutputStream.flush();
    } catch (IOException ex) {
            ......
    }
}