2012-09-09 20 views
11

Tôi đang viết một chương trình dựa trên socket nhỏ. Tôi đang sử dụng một lớp ModelEvent để truyền thông tin thông qua socket. bên trong ModelEvent, có một obect biến kiểu (Object).Ổ cắm/tuần tự Java, đối tượng sẽ không cập nhật

Đối tượng chính nó là một mảng 2D có một số giá trị.

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

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

Giả sử đối tượng mảng được lấp đầy với giá trị 1. Sự kiện đầu tiên (sự kiện) được khách hàng nhận và dữ liệu là đúng. Sự kiện thứ hai được gửi mặc dù dữ liệu không đúng. Dữ liệu của nó giống như trong công văn đầu tiên. "allo" và "you" là để xem nếu tôi không đọc cùng một sự kiện hai lần và câu trả lời là không. Chuỗi là đúng, nhưng đối tượng không phải là, sự kiện nếu nó đã được cập nhật. Tôi lặp qua mảng trước khi gửi sự kiện thứ hai để xem nó có được cập nhật ở phía máy chủ hay không. Nhưng về phía khách hàng, nó vẫn giữ nguyên như trong công văn đầu tiên, ngay cả khi bản thân sự kiện được thay đổi.

+0

Bạn đang đọc nó ở phía khách hàng như thế nào? –

+0

ObjectInputStream.readObject và tôi truyền nó – maniak

Trả lời

20

Xem ObjectOutputStream.reset.

Đặt lại sẽ bỏ qua trạng thái của bất kỳ đối tượng nào đã được ghi vào luồng. Trạng thái được đặt lại thành giống như ObjectOutputStream mới. Điểm hiện tại trong luồng được đánh dấu là đặt lại để tương ứng ObjectInputStream sẽ được đặt lại tại cùng một điểm. Các đối tượng được ghi trước đó vào luồng sẽ không được tham chiếu đến như đã có trong luồng. Họ sẽ được ghi vào luồng một lần nữa.

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

Gọi reset trước khi viết cùng một đối tượng để đảm bảo trạng thái cập nhật của nó là tuần tự. Nếu không, nó sẽ chỉ sử dụng một tham chiếu trở lại đối tượng đã viết trước đó với trạng thái cũ của nó.

Hoặc, bạn có thể sử dụng cách khác ObjectOutputStream.writeUnshared như sau.

Ghi đối tượng "không được chia sẻ" vào ObjectOutputStream. Phương thức này giống hệt với writeObject, ngoại trừ việc nó luôn ghi đối tượng đã cho dưới dạng một đối tượng mới, duy nhất trong luồng (trái ngược với tham chiếu ngược trỏ đến một thể hiện được tuần tự hóa trước đó).

Cụ thể:

  • Một đối tượng bằng văn bản thông qua writeUnshared luôn đăng theo cách tương tự như một đối tượng mới xuất hiện (một đối tượng mà chưa được ghi vào dòng nào), không phân biệt hay không đối tượng đã được viết trước đó.

  • Nếu writeObject được sử dụng để viết một đối tượng đã được viết trước đó bằng writeUnshared, thì thao tác writeUnshared trước đây được coi như là viết một đối tượng riêng biệt. Nói cách khác, ObjectOutputStream sẽ không bao giờ tạo lại tham chiếu đến dữ liệu đối tượng được viết bằng các cuộc gọi đến writeUnshared.

Trong khi viết một đối tượng thông qua writeUnshared không tự nó đảm bảo một tham chiếu duy nhất cho các đối tượng khi nó được deserialized, nó cho phép một đối tượng duy nhất được xác định nhiều lần trong một dòng, do đó nhiều cuộc gọi đến readUnshared bởi người nhận sẽ không xung đột.Lưu ý rằng các quy tắc được mô tả ở trên chỉ áp dụng cho đối tượng cấp cơ sở được viết bằng writeUnshared và không cho bất kỳ đối tượng phụ được tham chiếu quá mức nào trong biểu đồ đối tượng được tuần tự hóa.

output.writeUnshared(...); 

Lưu ý đó là thực hành tốt để cặp vợ chồng này với ObjectInputStream.readUnshared.

Đọc đối tượng "không được chia sẻ" từ ObjectInputStream. Phương thức này giống hệt với readObject, ngoại trừ việc nó ngăn các cuộc gọi tiếp theo đến readObjectreadUnshared từ trả về các tham chiếu bổ sung cho cá thể được deserialized thu được thông qua cuộc gọi này.

Cụ thể:

  • Nếu readUnshared được gọi để deserialize một back-tài liệu tham khảo (đại diện dòng của một đối tượng mà đã được viết trước đó vào dòng), một ObjectStreamException sẽ được ném
  • Nếu readUnshared lợi nhuận thành công, sau đó bất kỳ nỗ lực tiếp theo nào để deserialize tham chiếu ngược lại đến xử lý luồng được deserialized bởi readUnshared sẽ gây ra một ObjectStreamException để được ném.

Deserializing một đối tượng qua readUnshared làm mất hiệu lực xử lý luồng được liên kết với đối tượng được trả về. Lưu ý rằng chính điều này không phải lúc nào cũng đảm bảo rằng tham chiếu được trả về bởi readUnshared là duy nhất; đối tượng deserialized có thể xác định phương thức readResolve trả về đối tượng hiển thị cho các bên khác hoặc readUnshared có thể trả về đối tượng Class hoặc enum không đổi có thể đạt được ở nơi khác trong luồng hoặc thông qua phương tiện bên ngoài. Nếu đối tượng deserialized định nghĩa một phương thức readResolve và việc gọi phương thức đó trả về một mảng, thì readUnshared trả về một bản sao nông của mảng đó; điều này đảm bảo rằng đối tượng mảng được trả về là duy nhất và không thể lấy được lần thứ hai từ một lệnh gọi readObject hoặc readUnshared trên ObjectInputStream, ngay cả khi luồng dữ liệu cơ bản đã được thao tác.

obj = input.readUnshared(); 
+1

Tôi muốn hôn bạn ngay bây giờ! * không có đồng tính * Cảm ơn. Chỉ cần hiểu, khi một đối tượng được gửi hai lần vào luồng, nó nhớ trạng thái trước đó của nó và sử dụng một đối tượng cũ? – maniak

+0

Có nó không :)! Tôi nghĩ rằng đó là vì lý do biểu diễn, nhưng nó không phù hợp với việc sử dụng bạn muốn làm cho nó. – Flawyte

3

Tôi không thấy mã dispatchEvent, nhưng từ những gì bạn đã viết tôi giả sử như sau: bạn viết cùng một đối tượng (chỉ trạng thái của nó đã thay đổi), điều này có nghĩa là nó sẽ viết chỉ tham chiếu hai lần . bạn có thể thấy trong tài liệu luồng đầu ra java (để thực hiện).

bạn nên sử dụng writeUnshared(), mà sẽ tạo ra một đối tượng mới trên mỗi viết

tôi thấy reset đã được đề xuất, điều này sẽ giúp bạn có được kết quả tương tự, nhưng nó có tác động hiệu quả.

+0

+1 để chỉ ra tác động hiệu suất. Tôi đã sửa đổi câu trả lời của mình để bao gồm 'writeUnshared' khi bạn đăng. – oldrinb

+1

-1 cho 'tác động hiệu suất'. Sự khác biệt duy nhất giữa writeUnshared() và reset()/writeObject() là trong trường hợp đầu tiên các đối tượng được tham chiếu vẫn có thể được gửi dưới dạng các chốt.Đó là một sự khác biệt lớn * chức năng *, và nó có thể không phải là những gì OP muốn ở tất cả. Giảm tất cả điều đó thành một 'tác động hiệu suất' chỉ là hoàn toàn không chính xác và hoàn toàn gây hiểu nhầm. – EJP

Các vấn đề liên quan