0

我正在設計一個分佈式系統,它將股票的ArrayList持久化到文件中。我正在寫入股票的文件,並在閱讀該文件時,我收到一個空指針異常錯誤。使用XML拋出空指針異常的持久性

這是A類的字段:

private static StockList instance = null; 

這是我的方法的getInstance(),A類,它檢索從文件中的股票列表。

public static StockList getInstance(){ 
    if (instance==null){ 
     try { 
      XMLDecoder d = new XMLDecoder(
        new BufferedInputStream(
        new FileInputStream("Stock.xml"))); 
      instance = (StockList) d.readObject(); 
      d.close(); 
     } catch (IOException ex) { 
      instance= new StockList(); 
      Logger.getLogger(StockList.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
    return instance; 
} 

這是A類的構造函數,它被稱爲如果(一個IOException中的getInstance):

public StockList(){ 
    stock.put("APL", new Stock("APL","Apple","Apple",3200)); 
    System.out.println(""); 
} 

這是我的方法writeStockList,A類,這寫股票的文件:

public void writeStockList() 
    { 
     try { 
      XMLEncoder e = new XMLEncoder(
       new BufferedOutputStream(
       new FileOutputStream("Stock.xml"))); 
     e.writeObject(getInstance()); 
     e.flush(); 
     e.close();    
    } catch (IOException ex) {    
     Logger.getLogger(StockList.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

這是我的主要方法,在B類,其初始化當服務器運行stocklist:

public static void main(String[] args){ 
    try { 
     //Make sure all lists are initialised 
     StockList.getInstance(); 
     //delete after first run 
     //StockList.getInstance().addStock(new Stock("APL2","Apple2","Apple",3200)); 
     //StockList.getInstance().writeStockList(); 
     System.out.println(StockList.getInstance().getStock("APL").name);   
     System.out.println(StockList.getInstance().getStock("APL2").name); 

     System.out.println("registered ok"); 
    } catch (RemoteException ex) { 
     Logger.getLogger(ClientServer.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    System.out.println("finished server setup"); 
} 

出於測試目的,第一次運行該程序,其中包含以下行註釋掉:

//StockList.getInstance().addStock(new Stock("APL2","Apple2","Apple",3200)); 
//StockList.getInstance().writeStockList(); 

這應該添加一個新的股票(APL2)到列表,並將其寫入文件。

下面的行,正確打印 - 證明兩個股發現:

System.out.println(StockList.getInstance().getStock("APL").name);   
System.out.println(StockList.getInstance().getStock("APL2").name); 

然後,當我們運行的第二時間,上述行評論的,但是上面的System.out.println引發以下錯誤:

Exception in thread "main" java.lang.NullPointerException at food.stockticker.priceserver.ClientServer.main(ClientServer.java:46) 
Java Result: 1 

作爲第二項被寫入到文件中的上述不應該發生,並且讀回stocklist時的getInstance()被調用。如果我打印第一個項目(APL),它會返回它。當打印APL2時,發生錯誤。

看起來好像Stock.xml文件被覆蓋,或者第一次運行所做的更改沒有寫入xml文件。有任何想法嗎?

編輯:

的XML:

<?xml version="1.0" encoding="UTF-8"?> 
<java version="1.6.0_41" class="java.beans.XMLDecoder"> 
<object class="food.stockticker.priceserver.StockList"/> 
</java> 
+0

XML是什麼樣的?我們能否看到'StockList'類的其餘部分 - 主要是'get'方法。 – 2013-03-07 18:27:57

+0

我添加了XML文件以及在發生IOException時調用的構造函數。沒有其他方法與上述相關 - 我現在添加了所有內容。 – 2013-03-07 18:38:41

+0

如果發佈完整的代碼會更容易。同時,也可以使用這個log4j或類似的結構:logger.error(「{msg}」,{ex})其中{ex}是Exception。這將產生完整的堆棧跟蹤。還可以使用日誌記錄而不是與System.out.println()混合。 – 2013-03-07 18:38:57

回答

1

如果我的理解是正確的,該文件是在第一次運行後刪除,然後被註釋掉的線是在帶回在這種情況下,該文件在此處不存在,讀者將不會初始化,並且許多事情將爲空,包括實例 - 因此NullPointerException

另外注意的是,如果這是專爲分佈式(多線程併發)系統:

如果有應該是一個且只有一個主要的股票對象的實例,使用Singleton pattern和,在這種情況下,當數據正在從文件中讀取時,請在加載程序中加鎖(並使其成爲不同的方法)。在這種情況下,通常建議在靜態{}加載時執行此操作,以確保只能執行一次,並且不需要double-check locks,這對高併發系統無效。

private static synchronized void load() 
{ 
// return if file is already loaded, unless you meant to re-load 
// load the file here... 
} 

否則多個併發線程可以同時調用的getInstance,股票對象仍然會執行/ null的,他們會走到另一個。設計和代碼也存在許多問題,超出了這個問題,但希望這能夠解決NPE問題。