声明收集瞬态是否有问题? 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自动声明的,程序根本不起作用。
答案 0 :(得分:2)
您的问题与集合没有任何关系。 &#34;暂态&#34;告诉Java您不希望存储字段值,因此当您重新加载存储的对象时,瞬态字段将设置为null
(或0或其他相应的默认值)。因此,在您的cars.put(key, object)
示例代码中,您实际上是在尝试null.put(key, object)
。
containsKey
当然因为同样的原因而失败了 - 你试图在null
的某个地方调用它。
如果您不想序列化您的收藏集,则必须在反序列化后执行cars = new HashMap<>()
之类的操作。
这意味着问题也与equals
和hashCode
无关,但是您的计划信息中断的信息是&#39;当你有Netbeans生成它们表明你可能有其他问题。有关equals
和hashCode
的详细信息可以在此相关的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
对象添加到非现有集合。