Serialization with default methods in interface (BWC) - java

I have an interface A, and implementation of this interface AImpl
Interface has 1 method which is implemented in AImpl.
Implementation AImpl has few members and no serialVersionUID.
Question what will happen If new default method will be added to interface A, without overriding it in AImpl ? Have I did break here? Will I have same result of serialization/deserialization ?

Not only are methods not serialized, but interfaces are not serialized either.
The purpose of serialization is to write the data associated with an object, not it's behaviour (unless this is explicitly encoded as data as well, e.g. GregorianCalendar's TimeZone)
There is no way to see in a serialized object what interfaces or methods the class has so changing them has no effect.
(You might infer about the methods used for serialization only)
Java serialization does encode the super-class hierarchy of a class so you can't change that easily.
However, most serialization libraries don't do this and you can't see this information nor does it matter if you change them. The downside is that many serialization libraries don't support having the same field name multiple times in your class hierarchy but Java serialization does.

Related

Serialization not implemented?

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.

Are Java annotations serializable?

The Java Annotation interface does not extend Serializable. However, Java annotation values are serializable (implemented using java.lang.reflect.Proxy, with a serializable invocation handler).
Is this guaranteed anywhere? My search-foo is failing to find a reference. Or if I need to serialize annotation instances safely, do I need to create my own serialization proxies?
Annotation objects returned by methods of java.lang.reflect.AnnotatedElement are Serializable. This is what API says: This interface allows annotations to be read reflectively. All annotations returned by methods in this interface are immutable and serializable.
All classes capable of returning annotation objects (Class, Constructor, Field, Method, Package, Parameter) implement AnnotatedElement and are obliged to create / return Serializable objects by the above contract.
Annotations are part of the class definition, and thus would never be written to a serialization stream (at least not with standard java serialization) when serializing an instance of a class which has annotations.
UPDATE:
I guess i missed the point of the original question which was referring to specifically serializing an instance of an actual Annotation.

ObjectOutputStream doesn't correctly save fields of superclasses unless they're Serializable, why no error or warning?

Say I have an ArrayList<B> array of objects from a certain class B, which extends A. B has an instance field bb and A a field aa. I know that saving array to a .dat-file using ObjectOutputStream requires that B (not just ArrayList!) implement Serializable. I've found, however, that when loading the object back from the file (using an ObjectInputStream):
arrayLoaded = (ArrayList<B>)myObjIn.readObject();
the loaded array isn't identical to the original array: In the particular case, arrayLoaded.get(0).bb has the same value as in array, but arrayLoaded.get(0).aa is "zeroed". It has a default initialization value, regardless of its value when array was saved to file. However, this problem is solved by letting also A implement Serializable.
What bothers me is that this error is so subtle: no exception, no warning (in eclipse), nothing. Is there a reason for this or is this simply an oversight by the java developers? Do I just have to accept it and think hard about which classes in the hierarchy implement Serializable every time I want to use object IO streams?
Just because B implements Serializable, that does not retroactively include the fields of the non-serializable superclass in what gets serialized. (This makes sense, especially when you consider that being able to serialize private and package-private fields of any class just by extending it and implementing Serializable would violate its encapsulation.)
A field declared in A will behave the same as a field declared as transient in B. There is a workaround however. From the documentation for Serializable:
To allow subtypes of non-serializable classes to be serialized, the
subtype may assume responsibility for saving and restoring the state
of the supertype's public, protected, and (if accessible) package
fields. The subtype may assume this responsibility only if the class
it extends has an accessible no-arg constructor to initialize the
class's state.
So you will need to implement writeObject and readObject in B to handle the serialization/deserialization of A.aa.
What bothers me is that this error is so subtle: no exception, no warning (in eclipse), nothing. Is there a reason for this or is this simply an oversight by the java developers?
It is by design. (See #Paul Bellora's answer). The alternatives would be to:
Make it illegal to declare a class Serializable unless its superclass is Serializable. That's obviously unworkable.
Automatically serialize the superclasses fields which breaks if the should or can't be serialized. (Note that we can't rely on transient here, because if the designer of the superclass didn't intend the it to be serializable, he/she won't have labelled the fields.)
Do I just have to accept it and think hard about which classes in the hierarchy implement Serializable every time I want to use object IO streams?
Basically, yes. In particular, you need to think hard when you write a Serializable subclass of an existing non-Serializable class.
I guess it is possible to write FindBugs / PMD / etc rules to flag this particular usage as potentially problematic.

Why does implementing Externalizable need a default public 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.

With out implementing a Serializable interface is it possible to make a class persistable in java?

In Java we implement an interface Serializable that defines no method (also called a marker interface).
But suppose I have an interface without any method just like a Serializable interface, can I make it work just like that, meaning that I would be able to use my interface instead of the Serializable?
Thanks
Only Serializable will mark an object as being compatible with Java's built-in serialization machinery.
You can create other empty interfaces, but they won't mean the same thing. Each interface is distinct, even if it defines the same set of methods.
No. If you want to be able to use Java Serialization, your objects need to implement Serializable.
If you want to use other serialization tools, (ie: Hibernate, SimpleXML, XStream), that is always a possibility, but those generally involve adding annotations, xml files, or other configurations.
If you want your object be serializable it must implement java.io.Serializable.
You could also create your own interface or class that extend from Serializable and then another class/interface extend from that one.
No. Serializable is a special interface, and you can't use a different one with the built-in serialization mechanism. You could roll your own entire system, but it'd be a big job.
If you don't implement Serializable you will not be able to use Java serialization to persist it. But you are more than welcome to implement your own persistence that is not relying on Java serialization.
Serializable is called a marker, but only because classes like ObjectOutputStream and ObjectInputStream use the reflection API to check for it. There is no special magic there; if you wanted to implement your own alternative serialization strategy, you could also create your own interface and use that as the marker you wished to respect. Although, you should consider whether it would actually be better design to use the existing Java marker (Serializable). I believe some other alternatives to the built-in Object stream do this.
If you merely wish to take complete control over how your objects are serialized into bytes, you can do so without rewriting the ObjectXXXStream classes, by using Serializable subclass Externalizable. And in fact, this is commonly done, since the automatic serialization afforded by Serializable ungracefully dies with the smallest change to the SerialVersionUID, which, unless supplied, is calculated automatically from various signatures of the class - making Serializable unsuitable for must persistent storage, since most kinds of changes (i.e. during a routine upgrade) to the underlying class will prevent reloading the serialized data.

Categories