Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java SonarQube rule squid:S1948 - how to use serializable lists without being bound to e.g. ArrayList

The SonarQube rule squid:S1948 requires that all fields of a serializable class are either serializable or transient. Another rule states to rather use the interface than the implementation types.

When I have a

public class myClass implements Serializable
{
  List<String> names;
  ...
}

then names should rather be a List<String> than e.g. ArrayList<String>. But then rule S1948 tells us that List isn't serializable.

Solution at a first glance: define an interface SerializableList - maybe like this:

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

If we declare names to be a

  SerializableList<String> names;

the warning from rule S1948 is gone, but an assignment names = new ArrayList<String>(); results in a Type mismatch: cannot convert from ArrayList<String> to SerializableList<String>.

Two questions:

  • why can I declare List<String> names = new ArrayList<String>(); without a warning nor need to cast, but cannot declare SerializableList<String> names = new ArrayList<String>();? I wonder, because ArrayList<E> implements List<E>, Serializable, ... - why isn't it a SerializableList?
  • how to declare names in a way that neither S1948 nor the other rule will give a warning, but I can still be free to use any kind of List that is also Serializable (like ArrayList, ...) and without need for an explicit cast.

Thanks for any hints.

like image 739
outofmind Avatar asked Sep 12 '25 16:09

outofmind


1 Answers

why can I declare List<String> names = new ArrayList<String>(); without a warning nor need to cast, but cannot declare SerializableList<String> names = new ArrayList<String>();? I wonder, because ArrayList<E> implements List<E>, Serializable, ... - why isn't it a SerializableList?

You want to use a structure/feature which does not exist in Java ("a grouping interface"). Right now you introduced a new type SerializableList which extends other types:

List    Serializable
  ↑          ↑
SerializableList

ArrayList also extends both parent types of the SerializableList:

List   Serializable
  ↑         ↑
   ArrayList

but they are no connection between SerializableList and ArrayList. If we define a new type:

public class SerializableListImpl extends ArrayList implements SerializableList

then we have:

   --------→ List ←---------
   |                       |
   |  --→ Serializable ←-- |
   | |                   | |
ArrayList          SerializableList
      ↑                 ↑
      SerializableListImpl 

and finally:

List serializableList = new SerializableListImpl();
System.out.println(serializableList instanceof List); // true
System.out.println(serializableList instanceof Serializable); // true
System.out.println(serializableList instanceof ArrayList); // true
System.out.println(serializableList instanceof SerializableList); // true

List arrayList = new ArrayList();
System.out.println(arrayList instanceof List); // true
System.out.println(arrayList instanceof Serializable); // true
System.out.println(arrayList instanceof ArrayList); // true
System.out.println(arrayList instanceof SerializableList); // false ← not in the hierarchy

how to declare names in a way that neither S1948 nor the other rule will give a warning, but I can still be free to use any kind of List that is also Serializable (like ArrayList, ...) and without need for an explicit cast.

You cannot. Not every implementation of the List interface have to be also Serializable. Anyone can define a new type:

public class MyList implements List {
    ...
}

assign to the names field and then:

List myList = new MyList();
System.out.println(serializableList instanceof List); // true
System.out.println(serializableList instanceof Serializable); // false ← not in the hierarchy

As I wrote at the top such feature as "a grouping interface":

SerializableList == List<String>&&Serializable

does not exist so you have to mark the issue as Won't Fix.

like image 65
agabrys Avatar answered Sep 14 '25 06:09

agabrys