我正在设计一个分布式系统,它将库存的ArrayList保存到文件中。我正在写文件到文件,并在读取该文件时,我收到空指针异常错误。
这是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类构造函数,如果getInstance()中存在IOException,则调用它:
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
当调用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 :(得分:1)
如果我理解正确,文件在第一次运行后就被删除了,那么注释掉的行被带回来。在这种情况下,文件此时不存在,读者不会初始化和很多东西将为null,包括实例 - 因此为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,stock对象仍然会执行/ null并且它们将相互遍历。设计和代码也存在许多问题,超出了这个问题,但希望这能解决NPE问题。