I have read these articles on SO:
Externalizable or Serializable?,
What is the difference between Serializable and Externalizable in Java?.
but my question is what extra customization could be derived by implementing Externalizable as compared to serializable.
It is possible to customize Serialization of a class that implements Serializable by giving our own implementation of writeObject and readObject. Then what is the purpose of using Externalizable and customizing the ReadExternal and writeExternal implementations. what is the real benefit of using Externalizable. I have read various links that says Externalizable supports custom serialization (including the one above). but I do not see an example where Externalizable is a clear winner or something that cannot be done using Serializable. would be nice to see an example on this.
Just to give more clarity, the following snippet, is extracted from here:
When a class implements Serializable interface it gives information to the JVM that the instances of these classes can be serialized. Along with that, there is a special note to the JVM
"look for following two methods in the class that implements Serializable. If found invoke that and continue with serialization process else directly follow the standard serialization protocol"
So this gives us a chance to write these two methods:
private void writeObject(ObjectOutputStream out) throws IOException;,
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
inside the Class that implements Serializable and you get a hook to the serialization process. You can write your custom code inside these two methods and customize the standard behavior of serialization.
The main difference between Serializable and Externalizable is that Serializable automatically takes care of base classes for you. Externalizable leaves the entire job up to you.
Related
What I understand is that I can implement Serializable interface to make my object serializable.
But I don't get where is writeObject method implemented when Serializable is an interface, so it doesn't contain implementation of methods, just a definition?
As you already noticed, the Serializable is a Marker Interface and does not have any methods to implement. Implementing Serializable is just a note that this one is eligible for serialization which is handled using ObjectOutputStream.
Methods you mentioned need to be implemented in a class implementing the Serializable interface and will be picked up automatically. Since there is no obligation for implementing them, they are not included in the interface.
http://docs.oracle.com/javase/8/docs/platform/serialization/spec/serial-arch.html#a4539
Tough all the answers posted so far are right, I wish to add some extra comments:
java.io.Serializable was already part of the Java 1.1 API (among the first versions of Java), and was meant as an easy way for the programmer to mark any class to have a special behaviour.
According to OOP principles, that should have been done through a regular interface, which is what you (and me, and any other programmer) would have expected. Something like this:
public interface Serializable<E>
{
public E read(DataInput input) throws IOException;
public void write(DataOutput output) throws IOException;
}
But, since there are many classes in Java which needed to be serialized, the Java Language designers wished to save troubles to programmers, by some kind of mechanism through which serialization would be performed automatically. But how?
Through an abstract class? Nope. That would have prevented any custom class to have its own hierarchy (since in Java there is only single inheritance).
Making java.lang.Object serializable? Neither so, because that would have prevented programmers to decide which class should be serializable and which should not.
On top of all, there was a hughe problem: Note that method read is supposed to create and return an object of class E from a DataInput stream. An abstract class just can not create instances of its subclasses whithout further information (the abstract class does not know which is the applied subclass).
So, they decided to pass over the OOP and offer Serialization as a special non-oop feature of the serialization classes ObjectOutputStream/ObjectInputStream (credits to EJP for this detail) in the form of a "dummy" interface recognizable by them, at the price of adding somehow some confussion to the class definitions, because an interface with no methods is nonsense (Same approach they adopted for java.lang.Cloneable).
Actually, it adds even more confussion, because custom serialization must be done by implementing private methods readObject and writeObject (as specified by ObjectOutputStream), which is a feature non describible in terms of a Java interface.
Nowadays, these kind of marking can be done through annotations. Well, think of Serializable as an interface which should have been an annotation, but still remains as an interface for those -endless- compatibility reasons.
I have got an object which contains non serializable object inside.
class object BigObject<T extends smallObject> implements Serializable{
private T insideObject;
public BigObject(T insideObject) {this.insideObject = insideObject;}
}
I would like to serializable Big object, but I get java.io.NotSerializableException error for obvious reasons.
I read topics like:Java Serialization with non serializable parts
or https://dzone.com/articles/serializing-java-objects-non
The answers were very interesting, but could not resovle my problem.
First of all insideObject is a class from a library, co I cannot add serializable implementation.
The answer given on the dzone webpage is also interesting (to write your own writeObject methods).
But as you can see, insideObject is a generic class, we can get a few types of insideObject extending on smallObject in bigObject, so this solution is impossible.
So, is it possible to manage with this problem in the other way?
Maybe I can somehow add implementation of serializable on the existing object? Or only external liblaries as Kyro can help me with my problem?
You should try to implement Externalizable Interface rather than Serializable
Then you need to override the writeExternal and readExternal method of Externalizable
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(urObject);
}
This is why java has Transient keyword right?
Declare the variable which is non serializable as transient and your problem will be solved.
i.e.
private transient T insideObject;
Use transient before any field that you don't want to be incorporated into a serialisation.
Standard serialisers will pass over that field.
I think the example from dzone is something that can help you.
One approach is to use BigObject as an abstract base class and create subclasses for each case of smallObject that handles their own serialization/desearialization logic following the example you posted.
The other is sticking to a single BigObject class, but, during the serialization you can also serialize the class name of the concrete smallObject instance. Then during deserialization, you can modify the logic accordingly.
private void writeObject(final ObjectOutputStream out) throws IOException {
out.writeUTF(this.insideObject.getClass().getCanonicalName());
// serialize this.insideObject
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
String insideClassName = in.readUTF();
// choose logic based on class name
}
I would personally go with the first approach, since it will keep the code cleaner and stick to OOP best practices.
This question already has answers here:
What is the difference between Serializable and Externalizable in Java?
(11 answers)
Closed 9 years ago.
I read that
Externalizable provides us writeExternal() and readExternal() method which gives us flexibility to control java serialization mechanism instead of relying on Java's default serialization.
But If i implement Serializable and override readObject(), writeObject(), then does not it also means the same that I am customizing serialization process?
How does it differ?
THanks.
Difference between Externalizable and Serializable
In case of Serializable, default serialization process is used. while in case of Externalizable custom Serialization process is used which is implemented by application.
JVM gives call back to readExternel() and writeExternal() of java.io.Externalizalbe interface for restoring and writing objects into persistence.
Externalizable interface provides complete control of serialization process to application.
readExternal() and writeExternal() supersede any specific implementation of writeObject and readObject methods.
Though Externalizable provides complete control, it also presents challenges to serialize super type state and take care of default values in case of transient variable and static variables in Java. If used correctly Externalizable interface can improve performance of serialization process.
So go for Externalizable interface
When you have special requirements for the serialization of an object. For example, you may have some security-sensitive parts of the object, like passwords, which you do not want to keep and transfer somewhere. Or, it may be worthless to save a particular object referenced from the main object because its value will become worthless after restoring.
Official docs on Bean Persistence
Implement writeObject when you need to exercise greater control over what gets serialized when you need to serialize objects that default serialization cannot handle, or when you need to add data to the serialization stream that is not an object data member. Implement readObject to reconstruct the data stream you wrote with writeObject.
Use the Externalizable interface when you need complete control over your bean's serialization (for example, when writing and reading a specific file format). To use the Externalizable interface you need to implement two methods: readExternal and writeExternal. Classes that implement Externalizable must have a no-argument constructor.
We don't need it if we're implementing Serializable. So why this difference? How does it relate to the actual mechanism of Serialization?
A thorough explanation (although the grammar of the article might be improved) can be found on http://www.jusfortechies.com/java/core-java/externalization.php . The short answer, for future reference in case the linked page goes away:
Externalizable is an interface extending Serializable. Contrary to Serializable, though, objects are not restored by just reading the serialized bytestream, but the public constructor is called and only once the object is thus created, its state is restored. This makes restoring more efficient.
Edit: See also What is the difference between Serializable and Externalizable in Java? .
This is primarily used for caching purposes. In order to deserialize across streams, you will need to spell out how you want your object to be deserialized, hence the two methods provided by the contract in Externalizable interface: writeExternal and readExternal. Note that Externalizable extends Serializable, so you don't necessarily need to implement Serializable interface (although it's a marker interface and there are no methods to be actually implemented).
For a sample implementation, have a look at MimeType.
A public no-arg constructor is needed while using Externalizable interface.
Because in case of Serializable
readObject reads the required information from the ObjectInputStream
Serialization uses reflection mechanism to get the necessary fields and their corresponding values.
Serializable serializes all the data members (except static and transient).
But in case of Externalizable
No reflection mechanism used.
User doesn't serializes all data members.That's why to fetch values of the members which are not externalized public no arg constructor is required.
There is a class I want to serialize, and it implements Serializable, but one of the objects it contains does not implement Serializable.
Is there a way to modify the class at runtime to make it implement the Serializable interface so I can serialize it? I can't change it at compile time because its a third party library.
Maybe I would have to use some sort of bytecode writer or something?
EDIT: Both the containing class and contained class are in the 3rd party library so I don't think i can mark something as transient. The containing class is marked as serializable, but it contains an object that is not.
I'm fine with writing a custom serialization method for the class, not sure how I would do this though, would I have to use reflection to get the values of the private variables?
Reading the javadoc for Serializable, I see:
Classes that require special handling
during the serialization and
deserialization process must implement
special methods with these exact
signatures:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
which you could use to manually serialize the uncooperative fields. You could look into using ASM, but it seems hard to believe that it is a maintainable solution.
Fields can be skipped using the transient modifier. Additional data can be added to the stream by providing readObject and writeObject methods. Classes can be subclassed to make them serialisable (though you will need to manage the superclass data), or use a serial proxy (see Effective Java).
First of all, do you really need to do this? Maybe the class in the third-party library is not serializable by design. Even if it's just an omission rather than a deliberate decision, it's easy enough to write a custom serialization method in a helper class. If you have to do this though (like I had to, for something similar). Take a look at Javassist. You can do something like this:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("mypackage.MyClass");
cc.addInterface(pool.get("java.io.Serializable"))
EDIT: You can use a third-party Serialization API like XStream instead of doing all the dirty work yourself.
If a class is not marked as Serializable that might be of good reasons (take database connections as an example). So first of all make your self clear if you really need to serialize that object as well. If you just need to serialize the surrounding object you may consider marking the contained object as transient.
You could use java.lang.reflect.Proxy to add the Serializable interface to object instances over which you have no life-cycle control (i.e. can't subcalass them) and get them serialized this way. But then you would still not be able to read them back without another hack (i.e. introducing a surrogate class).
I'd recommend to look for an alternative to the Java Serializable mechanism in general. It's pretty much broken by design in several ways.