在反序列化对象后,hasMap声明的瞬态不起作用

时间:2017-06-16 10:34:05

标签: java serialization

声明收集瞬态是否有问题? transient Map<String, Car> cars = new HashMap<>()在序列化的Owner实例中声明,但Car类未序列化。

当程序第一次运行Owner实例时,它会创建Car并将其插入集合Cars,但是当第二次运行程序时,Owner被反序列化,它正确创建了Car个实例,但在添加到集合cars.put(key, object)时会导致NullPointerException。此外,仅在反序列化后运行cars.containsKey(regNumIn)导致异常而不是给出true或false。似乎在重新创建Owner之后的第二次运行中创建了新的hashMap

它是否必须对hasCode()和equals()做任何事情?我没有声明这些,如果它们是由Netbeans IDE自动声明的,程序根本不起作用。

3 个答案:

答案 0 :(得分:2)

您的问题与集合没有任何关系。 &#34;暂态&#34;告诉Java您不希望存储字段值,因此当您重新加载存储的对象时,瞬态字段将设置为null(或0或其他相应的默认值)。因此,在您的cars.put(key, object)示例代码中,您实际上是在尝试null.put(key, object)

containsKey当然因为同样的原因而失败了 - 你试图在null的某个地方调用它。

如果您不想序列化您的收藏集,则必须在反序列化后执行cars = new HashMap<>()之类的操作。

这意味着问题也与equalshashCode无关,但是您的计划信息中断的信息是&#39;当你有Netbeans生成它们表明你可能有其他问题。有关equalshashCode的详细信息可以在此相关的SO问题中找到:

What issues should be considered when overriding equals and hashCode in Java?

答案 1 :(得分:0)

在反序列化对象时,Java不会调用默认构造函数。因此,您的代码

transient Map<String, Car> cars = new HashMap<>();

不会被执行。

要完成此操作,您可以覆盖班级的readObject方法:

public class ... implements Serializable {
    ...
    private transient Map<String, Car> cars = new HashMap<>();
    ...
    private void readObject(ObjectInputStream stream)
              throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        // Important! recreate transient field cars as empty HashMap
        this.cars = new HashMap<>();
    }
    ...
}

答案 2 :(得分:-1)

我删除了transient语句,并在Car类中实现了Serializable接口,它可以工作。我认为问题是第一次运行后没有保存集合transient,而在反序列化Owner对象的第二次运行中,没有调用非参数构造函数,因此新的{{1没有创建该构造函数中的集合。因此,在第二次运行中,尝试将cars对象添加到非现有集合。