Skip to main content
gamedev.net
🔒 Locked

[java] implementing Serializable

Started by bballmitch May 24, 2006 at 6:56 PM 3 replies 1k views
Original Post
bballmitch
bballmitch
I have a few classes that all implement Serializable and they all need to keep track of each other. I'm making the game multiplayer so I need network programming. So when I wrote the writeOutputStream and readIntputStream methods (maybe not the exact name of the methods) I need to write/read all of the fields in that class. It seems to me, though, that if i do this, it will go into an infinite loop. i.e. board keeps track of pieces and pieces keeps track of board, and so an infinite loop will occur when reading and writing to the input/output stream. Am I mistaken? If not, can someone indicate what to do to solve this problem?
Mitchen Games
Fred304
Fred304
Quote:
Original post by bballmitch
I have a few classes that all implement Serializable and they all need to keep track of each other.

This smells like bad design. Information flow should be one-directional.

Quote:

So when I wrote the writeOutputStream and readIntputStream methods (maybe not the exact name of the methods) I need to write/read all of the fields in that class.

You normally do not have to do that. Simply writing "class Foo implements Serializable" is enough. The fields will be serialized correctly. Serializable is a mark up interface with no operations. It just tells Java that it is ok to be serialized.

Quote:

It seems to me, though, that if i do this, it will go into an infinite loop.

No it does not. Java is very clever ;) It uses a mark algorithm to determine what has already been serialized.

Quote:

If not, can someone indicate what to do to solve this problem?

As already pointed out, you do not have a problem with Serializable. You do not need to implement extra methods. The only case I am aware of that need extra treating is the Singleton pattern (do you use it?). In that case you need to override the readResolve() method.

What seems problematic though is your cyclomatic dependency between the board and the pieces.
Lucidquiet
Lucidquiet
You need to watch out for "static" variables -- those will not serialize. That is probably an indicator of "bad design" (in my opinion).

And it is NOT bad to have things pointing to one another (or referencing one another). It can complicate matters, and fail to communicate the design of the software, and there might be a simpler design. Yet, bi-directional graphs are a usefull data structure in some circumstances.

"Information should flow only one way" is a drastic generalization. An opposing example would be a Robot with Sensors, that requires a GuidanceSystem. The Robot must communicate to the GuidanceSystem what it's Sensors identify. It can allow the Sensors to report that information directly to the GuidanceSystem, or through the Robot to the GuidanceSystem. Then the GuidanceSystem can make changes to how it is controlling the Robot. So they reference each other -- the mistake would be to make part of this system static.

L-
"Education is when you read the fine print; experience is what you get when you don't." -Pete Seegerwww.lucid-edge.net
LorenzoGatti
LorenzoGatti
Probably there is no need to implement the object input/output methods: in most cases one only needs to stick "implements Serializable" in all involved classes and declare some member "transient" if it is reconstructed or overwritten or not required after deserialization.
The main reason for customizing serialization and deserialization is overriding the representation and/or the value of specific members, not tracking references.
See the Java Tutorial for a longer explanation.
Omae Wa Mou Shindeiru
haegarr
haegarr
Although it is in fact sufficient to let the VM do the actual de-/serializing, its usefullness is a question of two points:
(1) how long durates the persistence of the serialized objects, and
(2) how frequently are implementation changes expected?
(Where (1) could be reduced to (2) in the sense "is it expectable that the implementation changes during the persistence exists?)

IMHO, it is best practice to use Externalizable, fetching _once_ the serial UID by and writing it statically to the class, implementing readExternal and writeExternal, and reading/writing a short version number at the very first. E.g. this is a principle implementation skeleton as I use it since years in my commercial applications:
public class MyClassextends Objectimplements Externalizable {   static final long serialVersionUID = -4743736664363201163L;   // current chunk version (started w/ 1, but then an implementation   // change of fields has occured, so using 2 now)   private static final short CHUNK_VERSION = 2;   public void writeExternal(ObjectOutput out)   throws IOException {      out.writeShort(CHUNK_VERSION);      // here the fields follow   }   public void readExternal(ObjectInput in)   throws IOException,ClassNotFoundException {      final short version = in.readShort();      if(version>CHUNK_VERSION) {         // being not able to handle this deserialization      }      // here reading the fields that were existent in version 1      // any fields of version 1 that doesn't exist any more are to be read and dropped      if(version>=2) {         // here reading the fields that were added in version 2      } else {         // constructing defaults for version 2 fields      }   }}

It has the advantage of having control over changing the implementation. It also allows to do type conversion, statics handling, etc... And still being able to work with older persistent versions.


As the replies above already have mentioned: Java tracks the serialized objects, so loops are detected and handled accordingly.

[Edited by - haegarr on May 30, 2006 3:30:53 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.