繁体   English   中英

Java SonarQube 规则 squid:S1948 - 如何在不绑定到 ArrayList 的情况下使用可序列化列表

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

SonarQube 规则squid:S1948要求可序列化类的所有字段都是可序列化的或瞬态的。 另一条规则规定宁可使用接口而不是实现类型。

当我有一个

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 ,......)并且不需要显式转换.

感谢您的任何提示。

为什么我可以声明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(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

如何以 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM