Подтвердить что ты не робот

Java-сокет/сериализация, объект не будет обновляться

Я пишу небольшую программу на основе сокетов. Я использую класс ModelEvent для передачи информации через сокет. внутри ModelEvent существует переменная obect типа (Object).

Сам объект представляет собой 2D-массив с некоторыми значениями.

object[1][2] = 2;
ModelEvent event = new ModelEvent("allo", object);
dispatchEvent(event);

object[2][3] = 2;
ModelEvent event2 = new ModelEvent("you", object);
dispatchEvent(event2);

Скажем, что объект массива заполняется значением 1. Первое событие (событие) принимается клиентом, а данные являются правильными. Второе событие отправлено, хотя данные неверны. Его данные те же, что и в первой отправке. "allo" и "вы" должны посмотреть, не два раза я не читаю одно и то же событие, а ответ - нет. Строка правильная, но объект отсутствует, событие, если оно было обновлено. Я перебираю массив перед отправкой второго события, чтобы узнать, обновляется ли он на стороне сервера, и это так. Но на стороне клиента он по-прежнему остается таким же, как и в первой отправке, даже если это событие изменяется.

4b9b3361

Ответ 1

См. ObjectOutputStream.reset.

Reset будет игнорировать состояние любых объектов, уже записанных в поток. Состояние reset будет таким же, как новый ObjectOutputStream. Текущая точка в потоке отмечена как reset, поэтому соответствующий ObjectInputStream будет reset в той же точке. Объекты, ранее записанные в поток, не будут упоминаться как уже находящиеся в потоке. Они снова будут записаны в поток.

/* prevent using back references */
output.reset();
output.writeObject(...);

Вызовите reset перед тем, как написать тот же объект, чтобы обеспечить его обновление состояния. В противном случае он просто будет использовать обратную ссылку на ранее написанный объект с его устаревшим состоянием.

Или вы также можете использовать ObjectOutputStream.writeUnshared следующим образом.

Записывает объект "unshared" в ObjectOutputStream. Этот метод идентичен writeObject, за исключением того, что он всегда записывает данный объект в качестве нового уникального объекта в потоке (в отличие от обратной ссылки, указывающей на ранее сериализованный экземпляр).

В частности:

  • Объект, написанный с помощью writeUnshared, всегда сериализуется так же, как вновь появляющийся объект (объект, который еще не был записан в поток), независимо от того, был ли ранее сохранен объект.

  • Если writeObject используется для записи объекта, который ранее был записан с помощью writeUnshared, предыдущая операция writeUnshared обрабатывается так, как если бы это была запись отдельного объекта. Другими словами, ObjectOutputStream никогда не будет генерировать обратные ссылки на данные объекта, записанные вызовами writeUnshared.

При записи объекта через writeUnshared сам по себе не гарантирует уникальную ссылку на объект, когда он десериализован, он позволяет определять один объект несколько раз в потоке, так что несколько вызовов на readUnshared на приемник не будет конфликтовать. Обратите внимание, что правила, описанные выше, применяются только к объекту базового уровня, написанному с помощью writeUnshared, а не к каким-либо транзитным ссылочным под-объектам в графе объектов, которые должны быть сериализованы.

output.writeUnshared(...);

Обратите внимание, что это хорошая практика, чтобы связать это с ObjectInputStream.readUnshared.

Считывает объект "unshared" из ObjectInputStream. Этот метод идентичен readObject, за исключением того, что он предотвращает последующие вызовы readObject и readUnshared от возврата дополнительных ссылок на десериализованный экземпляр, полученный с помощью этого вызова.

В частности:

  • Если readUnshared вызывается для десериализации обратной ссылки (представления потока объекта, который был ранее записан в поток), ObjectStreamException будет выбрано
  • Если readUnshared возвращается успешно, любые последующие попытки десериализации обратных ссылок на дескриптор потока, десериализованные readUnshared, вызовут ObjectStreamException.

Удаление десериализации объекта с помощью readUnshared отменяет дескриптор потока, связанный с возвращенным объектом. Обратите внимание, что это само по себе не всегда гарантирует, что ссылка, возвращаемая readUnshared, уникальна; десериализованный объект может определить метод readResolve, который возвращает объект, видимый для других сторон, или readUnshared может возвращать объект Class или константу enum, доступную в другом месте потока или через внешние средства. Если десериализованный объект определяет метод readResolve, и вызов этого метода возвращает массив, то readUnshared возвращает неглубокий клон этого массива; это гарантирует, что возвращаемый объект массива уникален и не может быть получен во второй раз из вызова readObject или readUnshared на ObjectInputStream, даже если манипулировать базовым потоком данных.

obj = input.readUnshared();

Ответ 2

Я не вижу код dispatchEvent, но из того, что вы написали, я предполагаю следующее: вы пишете тот же объект (только его состояние изменилось), это означает, что он будет писать только ссылку дважды. вы можете видеть в документах потока выходных данных java (для производительности).

вам следует использовать writeUnshared(), который создаст новый объект при каждой записи

Я вижу, что reset был предложен, это приведет вас к одному и тому же результату, но это повлияет на производительность.