【问题标题】:Java why a Map of Map (ex: Map<String,Map<String,String>>) not serializeableJava 为什么 Map 的 Map(在:Map<String,Map<String,String>>)不可序列化
【发布时间】:2017-01-15 20:34:03
【问题描述】:

我们在JDK 1.7 中使用HashMap,我在使用SonarQube 进行代码审查时遇到了一些问题。

请考虑以下示例:

public class SerializationTest implements  Serializable {

   private Map<String,String> test1=new HashMap<>(); //Serializeable
   private Map<ANEnum,String> test2=new HashMap<>(); //Serializeable
   private Map<String,ASerializeableObject> test3=new HashMap<>();  //Serializeable 

   private Map<String,Map<String,String>> test4=new HashMap<>(); //Not Serializeable
   private Map<ANEnum,Map<String,String>> test5=new HashMap<>(); //Not Serializeable
   private Map<String,Map<String, ASerializeableObject>> test6=new HashMap<>(); //Not Serializeable

Sonar 将最后三个 HashMaps 标记为不是 serializeable。声纳错误是 (Make "test4" transient or serializable)

据我猜测,HashMapserializeable,如果它的键和值是 serializeable。但似乎如果我将一个HashMap 值设置为另一个HashMap,那么原来的HashMap 根本不会是serializeable

这个声纳问题正确吗?!如果是我该如何解决?!

【问题讨论】:

  • 要测试某些东西是否可序列化,请将其序列化。 Sonar 无法知道您的地图在运行时实际包含的内容是否可序列化。如果您询问声纳违规行为,请发布准确完整的消息和规则名称。
  • Sonarqube 方面的工作相当糟糕,因为变量是在同一个语句中声明和初始化的。
  • @EJP SOnar 不能保证地图是可序列化的,因为它包含Map 的实例,而Map 是不可序列化的。在运行时,它可能是,但在编译时,你不能保证内部映射是可序列化的。
  • @JBNizet 规则名称为:Fields in a "Serializable" class should either be transient or serializable (squid:S1948)。
  • 亲爱的@JBNizet 似乎对于前三个示例,Sonar 保证了序列化,因为您不会在那里看到错误报告 :) 这可能是声纳中的错误。因为,Sonar 保证 Map&lt;String,ASerializeableObject&gt; 是可序列化的(您将在代码审查中看到没有错误),但是当您将 ASerializeableObject 替换为已经提到的 serializeableMap&lt;String,ASerializeableObject&gt; 时,最终结果 Map&lt;String,Map&lt;String,ASerializeableObject&gt;&gt; 是标记为不是serializeable

标签: java serialization hashmap sonarqube


【解决方案1】:

让我们逐行查看:

private Map<String,String> test1=new HashMap<>();

键类型 String 是可序列化的。值类型 String 是可序列化的。具体的 Map 类型 HashMap 是可序列化的。所以一切都是可序列化的。

private Map<ANEnum,String> test2=new HashMap<>(); 

密钥类型 ANEnum 是可序列化的。值类型 String 是可序列化的。具体的 Map 类型 HashMap 是可序列化的。所以一切都是可序列化的。

private Map<String,ASerializeableObject> test3=new HashMap<>();

键类型 String 是可序列化的。值类型 ASerializeableObject 是可序列化的。具体的 Map 类型 HashMap 是可序列化的。所以一切都是可序列化的。

private Map<String,Map<String,String>> test4=new HashMap<>();

键类型 String 是可序列化的。具体的 Map 类型 HashMap 是可序列化的。 但是值类型 Map 不是必要可序列化的。 Map 的一些具体实现(如 HashMap)是可序列化的。其他一些则不是。所以 Sonar 不能保证这个字段是可序列化的,并发出警告。如果您确定您只会将可序列化的映射存储为值,那没问题。如果存储不可序列化的映射,则序列化将在运行时失败。

private Map<ANEnum,Map<String,String>> test5=new HashMap<>(); //Not Serializeable

和之前的解释一样

private Map<String,Map<String, ASerializeableObject>> test6=new HashMap<>();

和之前的解释一样

请记住,Sonar 只是一种工具,它有时可以提供帮助,但有时会妨碍您。您应该控制自己,并决定警告是否应该让您改变事情。

【讨论】:

  • Map 的一些具体实现(如 HashMap)是可序列化的。其他一些则不是......这是我不知道的!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 2020-08-01
  • 2013-05-24
相关资源
最近更新 更多