Java generics change on class field and serialization

JeanValjean :

I have a Java serialization question that is neither reported nor negated as problematic in Java Docs (for JDK8).

So, suppose I have a class that implements Serializable

private static final long serialVersionUID = 1L;

private List<CharSequence> values;

If I change values to

private List<String> values;

should I change the serialVersionUID?

Andy Turner :

Another way to think of this serialization/deserialization operation is that it's a bit like casting.

Can you cast a List<CharSequence> to a List<String>? Not directly: the compiler will stop you, because generics are invariant. You can force it, however:

List<String> list = (List<String>) (List<?>) listOfCharSequences;
String entry = list.get(0);

and this might work a lot of the time, because, String is the most common CharSequence.

But it's possible that there's something else in there which is a CharSequence, but not a String, for example a StringBuilder. The code above would crash with a ClassCastException.

So, if you can be sure that all of your CharSequences are genuinely Strings, it's safe to make this change. Otherwise, you should either guard against it by changing the serial version id; or, in the case of String, you could simply invoke toString() on all of the elements:

List<String> listOfStrings = listOfCharSequences.stream()
    .map(cs -> Objects.toString(cs, null))
    .collect(toList())

(String.toString() returns itself, so this would return no new instance for elements that are already Strings)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=121939&siteId=1