Java SonarQube规则squid:S1948 - 如何使用可序列化列表而不受绑定例如数组列表

问题描述 投票:0回答:1

SonarQube规则squid:S1948要求可序列化类的所有字段都是可序列化的或瞬态的。 Another rule表示宁愿使用接口而不是实现类型。

当我有一个

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

然后names应该是一个List<String>而不是像ArrayList<String>。但是后来规则S1948告诉我们List不可序列化。

解决方案乍一看:定义一个interface SerializableList - 也许是这样的:

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

如果我们宣布names是一个

  SerializableList<String> names;

规则S1948的警告消失了,但是任务names = new ArrayList<String>();导致Type mismatch: cannot convert from ArrayList<String> to SerializableList<String>

两个问题:

  • 为什么我可以在没有警告的情况下宣布List<String> names = new ArrayList<String>();,也不需要演员,但是不能宣布SerializableList<String> names = new ArrayList<String>();?我想知道,因为ArrayList<E> implements List<E>, Serializable, ... - 为什么它不是SerializableList
  • 如何以一种S1948和其他规则都不会发出警告的方式宣布names,但我仍然可以自由地使用任何类型的List,也就是Serializable(如ArrayList,......),而不需要明确的演员表。

谢谢你的任何提示。

java serialization arraylist sonarqube
1个回答
1
投票

为什么我可以在没有警告的情况下宣布List<String> names = new ArrayList<String>();,也不需要演员,但是不能宣布SerializableList<String> names = new ArrayList<String>();?我想知道,因为ArrayList<E> implements List<E>, Serializable, ... - 为什么它不是SerializableList

您想要使用Java中不存在的结构/功能(“分组界面”)。现在你介绍了一种新型的SerializableList,它扩展了其他类型:

List    Serializable
  ↑          ↑
SerializableList

ArrayList还扩展了SerializableList的两种父类型:

List   Serializable
  ↑         ↑
   ArrayList

但他们在SerializableListArrayList之间没有联系。如果我们定义一个新类型:

public class SerializableListImpl extends ArrayList implements SerializableList

然后我们有:

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

最后:

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(serializableList instanceof List); // true
System.out.println(serializableList instanceof Serializable); // true
System.out.println(serializableList instanceof ArrayList); // true
System.out.println(serializableList instanceof SerializableList); // false ← not in the hierarchy

如何以S1948和其他规则都不会发出警告的方式声明名称,但我仍然可以自由地使用任何类型的List,也就是Serializable(如ArrayList,...),而不需要显式演员。

你不能。并非每个List接口的实现都必须是Serializable。任何人都可以定义一个新类型:

public class MyList implements List {
    ...
}

分配到names字段,然后:

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

正如我在顶部写的“分组界面”这样的功能:

SerializableList == List<String>&&Serializable

不存在所以你必须将问题标记为Won't Fix

© www.soinside.com 2019 - 2024. All rights reserved.