Java: how to ensure serializable collections

25,454

Solution 1

What you essentially ask for is a type definition joining two types:

<type-def> a = null;

What you need is a replacement of <type-def> with a specification, making sure that the object referenced by a implements both Serializable as well as Collection<? extends Serializable>. Such a type definition is not supported by the Java language.

As you already wrote, the most obvious solution may be to declare your own interface, joining these two other interfaces:

interface SerializableCollection<T extends Serializable> extends Collection<T>, Serializable {}

Seems ok, until you try something like this:

SerializableCollection<String> a = new ArrayList<String>();

This won't however compile. Even if ArrayList<String> implements both Collection<? extends Serializable> and Serializable, the class does not implements SerializableCollection<String>.

Now, you can if you would, circumvent even this problem by declaring a new class:

SerializableArrayList<T extends Serializable> extends ArrayList<T> implements SerializableCollection<T> {}

Now you have essentially combined everything you need and would be able to fulfill the original requirement:

SerializableCollection<String> a = new SerializableArrayList<String>();

Is it worth the effort? In your case, you must decide, but I would say no. My argument is that since the Serializable marker is just a non-formal 'label', ensuring that both your collection and its content implement Serializable still does not guarantee that the collection and its content actually can be serialized.

Solution 2

Serializable isn't a great interface. It should have been an annotation, if those were available when it was implemented.

How would you handle a List of a List of something not Serializable. You would need to ensure no object is non-serialisable transitively down the object graph. Not all objects that implement Serializable can actually be serialised.

Solution 3

An approach for cloning a collection and contained objects is

import org.apache.commons.lang3.SerializationUtils;
...
ClonedArrayList = SerializationUtils.deserialize(SerializationUtils.serialize(OriginalArrayList))

(for example via using ArrayList<Type>(collection) because SerializationUtils need the Serializable interface)

Regards, Gunnar

Share:
25,454

Related videos on Youtube

MrD
Author by

MrD

Updated on July 10, 2022

Comments

  • MrD
    MrD almost 2 years

    In Java, the Collection-interfaces do not extend Serializable for several good reasons. In addition, most common implementations of these interfaces implement Serializable.

    So objects which implement one of the Collection-interfaces are serializable if the implementation itself is serializable (which is usually the case) and if the objects in the collection are all serializable.

    But how can I ensure that these two conditions are met? I don't want to run into a runtime-error since the compiler could check these conditions. I'm thinking about some obvious interface like (showcase for the List-interface):

    public interface SerializableList<T extends Serializable> extends Serializable, List<T> {}
    

    I'm wondering if no one else is facing this problem and came up with this easy solution. Up to now I wasn't able to find any solution or even discussion on this, which makes me doubt on my idea.

    • Rohit Jain
      Rohit Jain almost 11 years
      You can make your List reference as - List<T extends Serializable>, if I understand your question correctly. You don't need to roll out your own interface.
    • JB Nizet
      JB Nizet almost 11 years
      The compiler can't check that. Every class implementing Serializable could contain a non-transient, non-serializable field, which would lead to a runtime exception. And an ArrayList<Object> could be serializable if the actual objects it contains are serializable. If that's really important, use unit tests.
    • MrD
      MrD almost 11 years
      @RohitJain: Your proposal does only guarantee that the objects in the list are serializable, but not the the List-implementation itself.
    • MrD
      MrD almost 11 years
      @JBNizet: Of course, the concrete implementation of the SerializableList could contain some not serializable attribute in addition to the objects-array which holds the added objects. But in this case I would say this is a bug in the implementation. On the other hand, if only serializable objects can be added to the list, the attribute holding the objects (e.g. an array) should be serializable, too.
    • JB Nizet
      JB Nizet almost 11 years
      You didn't catch me. Even an ArrayList<Serializable> could not be serializable. ArrayList is Serializable. It contains only instances of Serializable. But as soon as one of these contained objects contains a non-serializable field, it's not serializable anymore. Whatever the number of generic bounds you add, you can have errors at runtime. So use tests.
    • MrD
      MrD almost 11 years
      @JBNizet Thanks for your comment. I think I got it now. But anyway - if an objects implements Serializable and contains some non-serializable fields, I would classify this as a bug. Of course, it isn't always that easy - see the ArrayList which is serializable out-of-the-box but may become not serializable if someone adds not serializable objects. But from my point of view, this is at least very strange. Tom Hawtin posted almost the same concern in his answer below.
    • JB Nizet
      JB Nizet almost 11 years
      Yes. And using a non-serializable collection when you want it serializable is also a bug. Catch bugs by writing tests.
  • Narendra Pathai
    Narendra Pathai almost 11 years
    So is there no way to make a compile time check for that?
  • Narendra Pathai
    Narendra Pathai almost 11 years
    interface SerializableCollection<T extends Collection<? extends Serializable>>{} can something like this be done?
  • MrD
    MrD almost 11 years
    A List of objects which are not Serializable cannot be added to the SerializableList since this List does not implement Serializable. Of course, I could add an ArrayList (which is serializable) containing some not serializable objects - but only if I use it as a raw type. If it is parametrized, the compiler should complain about this.
  • MrD
    MrD almost 11 years
    Ok, I got it now. With ArrayList it is possible to add non-serializable objects which lead to runtime-errors. See the comments on the question.
  • MrD
    MrD almost 11 years
    Thank you. I think everything is clear for me now. As you and JB Nizet stated, I cannot rely that objects implementing the Serializable-interface are really serializable (it's a pity). I think this is the point: is it worth the effort? I will think about it if it is applicable in my case.