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:
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?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.
why can I declare
List<String> names = new ArrayList<String>();without a warning nor need to cast, but cannot declareSerializableList<String> names = new ArrayList<String>();? I wonder, becauseArrayList<E> implements List<E>, Serializable, ...- why isn't it aSerializableList?
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
Listthat is alsoSerializable(likeArrayList, ...) 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With