When does it make sense that the Java object is Serializable but not Cloneable?

If the Java class implements the Serializable interface but does not have the public clone() method, you can usually create such a deep copy:

 class CloneHelper { @SuppressWarnings("unchecked") public static <T extends Serializable> T clone(T obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); oos.close(); byte[] bytes = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); T copy = (T) ois.readObject(); ois.close(); return copy; } catch (ClassNotFoundException ex) { // Shouldn't happen throw new Error(ex); } catch (IOException ex) { // Probably a bug in T custom serialization methods throw new RuntimeException(ex); } } } 

I often come across third-party library classes like this, and resort to hacks like the ones described above. I even extended ObjectOutputStream to make the copy smaller. This never caused serious problems other than being inefficient (slow encoding / decoding, and serialization timelines can consume a lot of memory.)

And if it is unsafe to use this technique, the class probably should not have been declared Serializable .

So, what would I like to know if your class is Serializable , which might prevent you from defining a public clone() method (using either the Cloneable interface or the copy constructor?)


Related: Copy Object in Java

+7
java serialization serializable deep-copy
source share
7 answers

Well, you say that the serialization mechanism is one way of indirectly cloning objects. This, of course, is not its main function. It is commonly used for programs to transfer objects over a network, or storage, and then read them. You can expect the object to be used this way and implement Serializable, not expecting the code to clone objects locally, rather than implement Cloneable.

The fact that the code works on this serialization path assumes that the code uses the object in a way that the author did not intend to, which can either be the author or the one causing the “error,” but that does not mean that the common Serializable and Cloneable go together .

Separately, I'm not sure that clone () is “broken”, how difficult it is to implement correctly. The copy constructor is more natural to use and gets the right IMHO.

+1
source share

I would rather use the copy constructor rather than use the above mechanism. You can more accurately determine what you need to copy deeply or finely, and make copying an object different from serializing the object. The copy constructor may (for example) allow two objects to share a link to the main object, while this may not be acceptable for an object serialized and transmitted over the network.

Note that the Cloneable method is widely considered now broken. See this article with Joshua Bloch for more information. In particular, it does not have a clone() method!

+5
source share

Brian points to Cloneable very well, but even if Cloneable is working correctly, there are still instances where you might want the object to be serializable but not cloned.

If an object has a unique identifier outside the scope of the process, for example, in a database representation in memory, you do not want it to be cloned, because this is equivalent to creating a new record with identical attributes, including attributes related to identification, such as a key databases that are almost never correct. At the same time, you may have a system that is divided into several processes for stability or for other reasons, so you may have one process talking to the database and generating these ENTITY objects (see Erica’s Domain-Managed Project) Evans for more information on ensuring the consistency of the identity of objects in a data-enabled application), but a separate process can use these objects to perform business logic operations. An entity must be serializable in order to be passed from one process to another.

+4
source share

I think the Serializable and Cloneable interfaces should be used for completely different purposes. And if you have a complex class, then implementing each of them is not so simple. So in general, it depends on the goals.

+2
source share

One of the biggest problems with Serializable is that they cannot easily be made immutable. Serialization forces you to compromise here.

I will be tempted to create copy constructors on the object graph. This is just a bit more crude work.

+1
source share

This strikes me as a bit of a risk, as there are a number of errors for serialization (although most of them are unlikely, I would still like to test them if I serialized objects in 3d libraries). Most likely, this is not a problem, but it is possible to have an object with a variable variable as part of its state, which can be part of the cloning operation (not that it is a good design, only this is possible), and such a field will not be copied during serialization / deserialization . Another problem that comes to mind is enumerations, constants, and the possibility of getting multiple copies of such things if you cannot cope with them during deserialization.

Again, the edges, but what you would like to keep track of.

0
source share

I just thought of another case - When is enum .

Or, in general, when your class implements readResolve . This means that the object you are returning from readObject is not the one that was read from the stream, and therefore it is not necessarily a copy of the object that was originally written to the stream.

0
source share

All Articles