2017-06-16 36 views
0

聲明集合瞬態有什麼問題嗎? transient Map<String, Car> cars = new HashMap<>()是在Owner實例中聲明的,但是該序列化的類不是Car類。已聲明的瞬態isMap在對象被反序列化後無法工作

當程序首次Owner實例中運行它創建Car並將其插入收集Cars,但是運行程序第二遍的時候,Owner進行反序列化,它正確地創建Car實例,但添加到收藏cars.put(key, object)時,它會導致NullPointerException。也只有在反序列化後運行cars.containsKey(regNumIn)會導致異常而不是給出真或假。看起來在Owner重新創建後,第二次運行創建了新的hashMap

是否必須對hasCode()和equals()做任何事情?我沒有宣佈這些,如果它們由Netbeans IDE自動聲明,該程序根本不起作用。

+0

Java中的'transient'關鍵字用於指示不應序列化字段。所以反序列化後,你有'null'而不是你的地圖 – ByeBye

回答

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

你的問題與收藏無關。 「transient」告訴Java你不想存儲字段值,所以當你重新加載存儲對象時,瞬態字段被設置爲null(或者0或者其他相應的默認值)。因此,在您的示例代碼cars.put(key, object)中,您基本上正在嘗試執行null.put(key, object)

containsKey當然因爲同樣的原因失敗 - 你試圖在null上調用它。

如果你不想序列化你的集合,你必須在反序列化它之後去做類似cars = new HashMap<>()的事情。

這意味着這個問題也與equalshashCode無關,但當您的Netbeans生成它們時,程序「中斷」的信息表明您可能有其他問題。關於equalshashCode良好的信息可以在此與SO問題發現:反序列化對象時

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

-1

我刪除transient聲明,我實現Serializable接口的類Car,和它的作品。我認爲問題是transient集合在第一次運行後沒有保存,而在第二次運行時Owner對象被反序列化,因此不會調用非參數構造函數,因此該構造函數中的新集合cars未創建。因此在第二次運行中,它試圖將car對象添加到非現有集合中。