I have read that generally abstract classes should not be made Serializable in Java. The subclasses should be serializable (with custom read, write methods if required, for eg. when abstract classes have fields).
What is the reason behind this? Why is it considered bad design?
Update1: I have an abstract class with some fields and three subclasses. As of now, I am using the following approach.
I have made all the subclasses serializable with custom read, write methods. In the abstract class I have the following methods.
void writeFields(ObjectOutputStream out)throws IOException { .... }
void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... }
In the custom read, write methods in the subclasses I call these methods to (de) serialize the fields in the abstract class. Is this approach correct? Or is there a different better approach?
Update 2: I took Tom's advice and made my abstract class Serializable. (I want all subclasses to be Serializable and I have data in the abstract class) This is an aside, but just to complete the story I am using reflection to change final fields as advised by Jeremy Manson.
I think the reason is that if an Abstract class implements Serializable, there is no way to say that a sub type should NOT be Serializable. Better to let each concrete type declare for itself...
I don't know that it is necessarily bad design. Serialisation is effectively an implementation issue (note, Josh Bloch disagrees with me), so doesn't make sense for interfaces. If the abstract class has state, then you would want to make it serialisable. If it doesn't have state, there isn't really any reason to make it so.
Let's take an example. java.security.cert.Certificate is an abstract serialisable class, with a "type" serialisable field. If it wasn't serialisable it would not be possible for a subclass to be serialisable and set that field. You would be forced in to a hack.
Note that java.io.Serializable is a hack. It shouldn't have been an interface. An annotation (or language evolution like transient) would have been more appropriate.
As always, it's best to prefer composition to inheritance and not to make random class serialisable.
Let's take the oposite position. If you were to De-Serialize the object, what would be its type?
By definition, an abstract class can't be instantiated. If you can serialize it, that implies that it can also be deserialized and that would get you an instance of the abstract class. That contradicts the definition of an abstract class and therefore can't be done.
It's only bad design because it's a forced decision, what if you want a subclass that has non-serializable members.
That's why.
E.g. List is not Serializable, but every major list implementation is. (I know list is a Interface, but a abstract class with no members =/= a interface)
If abstract class contains important for serialization fields and you are not going to implement custom object reader/writer it is essential to declare that base class as Serializable.
Declaring base class (or interface) as Serializable makes all sub-classes Serializable including any transitive path.
Latter makes sense if you implement some framework: you ease life your users automatically propagating interface, otherwise you should document that you work with Serializable only or implement runtime checks for user supplied classes.
I added base class for entities (to unify naming standard, for fields like id, createdDate, updatedDate) and forgot to mark it as Serializable. As a result any Entity kept in session store (Redis) had null id values upon deserialization )) You don't want this.
UPDATE Serializable requires public no-arg constructor for deserialization. Declaration of inheritance doesn't create no-arg constructor for sub-classes nor for super-class, it's a users' chore. Superclass without default constructor breaks deserialization for all sub-classes ))
UPDATE 2 There is a way to declare that subclass is not designed for serialization even if it is inherited from base class that is Serialazable although it is runtime feature:
private void writeObject(ObjectOutputStream out) throws IOException
{ throw new NotSerializableException(); }
private void readObject(ObjectInputStream in) throws IOException
{ throw new NotSerializableException(); }
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 am now studying a java and I'm at the part of Abstract.
I read sorta strange part to me that there is an abstract class
which does not include any abstarct method.
Why do they use this kind of class?
To prevent instantiation of that class and use it only as a base class. Child classes can use the general methods defined in the abstract class.
For example it doesn't make sense to create an instance of AbstractVehicle. But All vehicles can reuse a common registerMileage(int) method.
A common reason to do this is to have the abstract class provide exploding implementations of the abstract methods as a convenience to subclasses who don't have to implement all the abstract methods, just those they want to - the remaining ones will still explode but it won't matter if those execution paths aren't exercised.
HttpServlet is an example of this pattern in action. It has default implementations for all methods that handle the different request types, but they all throw an exception. The subclass must override these if they want to do something meaningful. It's OK to leave some handler methods not overridden as long as they are never called.
Yes, we can have abstract class without any abstract method.
Best example of abstract class without any abstract method is HttpServlet
If this class extends another abstract class and don't have implementation of inherited abstract methods.
This class contains some common logic for all its inheritors, but itself does not represent usable entity (in terms of particular application)
These type of classes are used for a implement a general logic which can be implemented by other classes. Making it abstract prevents from instantiating it. But other classes can inherit the class and its methods.
Say you have a set of related classes, but no related (shared) code, yet. If we make all of these classes extend a base class with no abstract methods, that then if we wan't all of these classes to have an identical method/feature in the future, that can be done in one shot by putting it in the base class. So code is not repeated and it reflects in all child classes by including it in just one place.
Another example for having such class is when you implement creation helpers. These classes are used to ease the client in the creation of objects, which are related in topic but decoupled depending on the need. By nature, the methods of this creator classes are all static and they can be seen as utility classes as well.Obviously, instatntation of this classes is futile and hence the abstractkeyword.
To mention a recent example I met was the Sftpclass from org.springframework.integration.dsl.sftp which is basically an easy way to require objects (e.g: adapters, gateways) from the sftp api.
I develop a abstract class to prevent instantiation of that class and use it only as a base class. because, These type of classes are used for a implement a general logic which can be implemented by other classes. Sometimes, I have a default implementation for every method in abstract class. In the manner, it doesn't force the sub-class to override all of method, but also it implement everyone that is need.It means implicitly you have to override at least one method to make scene using this abstract class.
I can't think of any good reason to use it. It could be used as "marker" but an interface would be a better choice.
Abstract class without abstract method means you can create object of that abstract class.
See my Example.
abstract class Example{
void display(){
System.out.println("Hi I am Abstract Class.");
}
}
class ExampleDemo
{
public static void main(String[] args)
{
Example ob = new Example(){};
ob.display();
}
}
If you write one abstract method inside abstract class then it will not compile.
Which means if you create abstract class without abstract method then you can create Object of that Abstract Class.
I'm defining an interface to handle different kind of input sources like CSV files, SQL Tables and so on, so that I can easily copy data from one to the other.
In order to achive this I have an interface for a reader and one for a writer. Since they have some common attributes I wanted to define an abstract interface of ICommonContainer.
The common container interface is incomplete, because it only defines a subset, so I figured that, if I add abstract, it shouldn't be instantiatable when applied to a class, but it is.
So is there some way to declare an interface as incomplete similar to an abstract class?
So the interfaces looks like this:
public interface ICommonContainer
{
public void foo();
};
public interface Reader extends ICommonContainer
{
public data read();
};
public interface Writer extends ICommonContainer
{
public void write(data objects);
};
where reader and writer should be complete, but base is not.
There is no such thing as Abstract interface. We make a class abstract in order to make it non-instantiable. And any interface by nature is non-instantiable only.
As far as your issue is concerned, you can make your class implement any number of interfaces. In your case, since your interfaces are a part of same inheritance hierarchy, you don't need to implement both Base interface, and Reader or Writer interface. So, let it implement either Reader or Writer interface.
On the other hand, if you want to make a class which only implements ICommonContainer interface, non-instatible, just make that class abstract. That will be enough.
public abstract class SomeClass implements ICommonContainer {
// Either define the method in interface or leave it.
}
As in the above example, your SomeClass cannot be instantiated, as it is defined abstract.
The common container interface is incomplete, because it only defines
a subset, so I figured that, if I add abstract, it shouldn't be
instantiatable when applied to a class, but it is.
No, you can't instantiate the interface.
And no, there is no way of preventing some class to implement that interface.
It is your job to implement Reader and Writer (Your example names with applied Java naming conventions) and you don't have to implement Base.
No you can't declare an interface abstract.
And you cannot prevent the world to have a class which implements your inteface and isn't abstract (if it is public).
I think this is ok, if someone can write a complete class using just your ICommonContainer, there is no problem.
You could make the interface package private which might accomplish what you want, but the bigger question is why?
In the Java library there are many interfaces that are "incomplete"; or a better way to explain it is they are partially complete. List being one of them.
A List can be considered partially complete, because typically you need something more. Such as ordering (ArrayList), or assurance of fast inserts (LinkedList). The concrete classes take care of the completeness.
What you are trying to do goes against decent design principles. I consider this poor design principles because you should you design your Interfaces as being enough for some level. Given the list example, for some classes, knowing that there is an iteratable collection of objects is enough. Which makes for a good interface design. The user of the interface is loosely coupled from the implementation of such.
You can have a "partial" interface the has to do with reading and another for writing, and another interface for the "missing" functionality. Each user of your concrete class will then cast it to the interface it needs.
I have a superclass like this which I expect alot of classes to inherit:
public abstract class Super {
protected Object myField; //Not used anywhere in this class
//a load more code here which does useful stuff
}
All these classes will need to use an instance of myField. However the superclass does not. Have I made a bad design decision somewhere?
Not necessarily. If all the subclasses need the same field for the same reason, then that's no different than providing any other common functionality in a base class. as your classes grow you may find that you add common functionality which uses this field (e.g. referencing it in an equals/hashCode method).
Now, if the field is of type Object and each sub-class shoves something completely different into it, i would consider that a code smell.
Well IMHO, a field should not be present in a class if it's not really used by that class. What it seems to me that you really want here is to have a base class that tells its subclasses "you should ALL have some way of keeping state for X but I (the base class) will not modify that X state, in which case you should make an abstract method in order to convey that message, something like this:
public abstract class Super {
protected abstract Object getMyField();
}
It's hard to say with such a vague description, but it would seem like you could do some generalization and push some common code up into your superclass. If your subclasses are doing something similar with the field then some commonality could be found (using template methods or strategies to handle subclass-specific differences), otherwise if every subclass is doing something different with it then what's the point of using a common field?
No, I don't think so. Abstract class serve that purpose (Have common functionality in base class and let subclass implement only specific required functionality).
So, if you don't use that field in class Super - why do you need it there?
Perhaps your super class would provide an interface to interact with this field in generic way, for example:
public abstract class Super<T> {
protected T myField;
public T getField() {
return myField;
}
}
public class Child extends Super<String> {
public Child( String label ) {
super.myField = label;
}
}
As stated in this tuturial
A protected field or method is accessible to the class itself, its subclasses, and classes in the same package.
This means that the protected fields have been designed precisely to have these characteristics.
Just on a lighter note The only thing common in your hirarchy is one field then you should get rid of abstract class and Create one Marker Interface.
I've got a class Thing:
public abstract class Thing {
// prevent instantiation outside package. Indeed, no Things will
// ever actually have a runtime class of Thing
Thing(){};
public static Thing create() {
return new SpecialThing1();
}
public static Thing createSpecial() {
return new SpecialThing2();
}
}
final class SpecialThing1 extends Thing {/* etc etc */}
final class SpecialThing2 extends Thing {/* etc etc */}
Basically I want the objects the client ends up using to be Serializable, and the client to know that they will be Serializable. So which class(es) needs to implement Serializable? And which need the serialVersionUIDs?
You only need to mark Thing as Serialiable and this will be inherited by SpecialThing1 and SpecialThing2. You don't have to add serial version UIDs to any of the classes but it's recommended that you do; that way you can control versioning of classes between client and server code - See related question here.
At least the most derived class of each instance will need to implement Serializable. Base classes should implement Serializable if there fields should be serialised. You may want to design the serial format for future change (see Effective Java for some discussion on that),
Ever class that implements Serializable, whether directly or indirectly, should define serialVersionUID.
(Note: Outside package will be able to create instances of your class (by deserialisation - a serial proxy may be in order). It may be a good idea to move the creation methods outside of the base class to cause less confusion.)