2013-08-01 73 views
1

問題是:在構造函數中初始化VTDGen,VTDNav或AutoPilot後,在其他方法中引用null,並引發相應的異常。VTD-XML:對象初始化後仍然引用空

public class Configuration { 
public Configuration(String dir, String filename, ResourceBundle resourceBundle) throws IOException, IndexWriteException, IndexReadException { 
    String XMLFilename = filename + ".xml"; 
    String indexFilename = filename + ".vxl"; 
    vtdGen = new VTDGen(); 

    vtdGen.parseFile("D:/Librarian/config/configuration.xml", true); 
    vtdNav = vtdGen.getNav(); 
    autoPilot = new AutoPilot(vtdNav); 
    boolean gen = vtdGen!=null; 
    boolean nav = vtdNav!=null; 
    boolean pilot = autoPilot!= null; 
    System.out.println("VTDGEN - " + gen + "\n" + "VTDNAV - " + nav + "\n" + "AUTOPILOT - " + pilot + "\n"); 
} 

public Configuration(ResourceBundle resourceBundle) { 
    try { 
     new Configuration(defaultDir, defaultFileName, resourceBundle); 
    } catch (IOException | IndexWriteException | IndexReadException e) { 
     e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
    } 
} 

public ArrayList<String> stringValue(String xPathExpression) { 
    try { 
     boolean pilot = autoPilot != null; 
     System.out.println("AUTOPILOT - " + pilot + "\n" + "String.length = " + xPathExpression.length() + "\n" + "String = " + xPathExpression); 
     autoPilot.selectXPath(xPathExpression); 
     int i; 
     while ((i = autoPilot.evalXPath())!=-1) { 
      stringResult.add(vtdNav.toString(i)); 
     } 
    } catch (XPathEvalException | NavException | XPathParseException e) { 
     e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
    } 
    return stringResult; 
} 

public void writeIndex(File indexFile) { 
    try (FileOutputStream fos = new FileOutputStream(indexFile)){ 
     if (parsed) { 
      vtdGen.writeIndex(fos); 
     } 
    } catch (IndexWriteException | IOException e) { 
     e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
    } 
} 

public File createIndexFile(String dir, String filename){ 
    indexFile = new File(dir + filename + ".vxl"); 
    writeIndex(indexFile); 
    return indexFile; 
} 

private final String defaultDir = System.getProperty("user.dir") + "/config/"; 
private final String defaultFileName = "configuration"; 
private final String defaultXMLFile = defaultFileName + ".xml"; 
private final String defaultIndexFile = defaultFileName + ".vxl"; 

private boolean parsed; 
private VTDGen vtdGen; 
private VTDNav vtdNav; 
private AutoPilot autoPilot; 
private File indexFile; 
private ArrayList<String> stringResult; 
} 

結果是:

VTDGEN - true 
VTDNAV - true 
AUTOPILOT - true 
AUTOPILOT - false 
String.length = 30 
String = /configuration/lastMode/text() 

例外:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException 
... 
Caused by: java.lang.reflect.InvocationTargetException 
... 
Caused by: java.lang.NullPointerException 
at core.config.Configuration.stringValue(Configuration.java:45) 
at UI.PrimaryStageController.test(PrimaryStageController.java:77) 
... 57 more 

爲什麼自動駕駛儀指空?

回答

2

我的猜測是,你調用此構造:

public Configuration(ResourceBundle resourceBundle) { 
    try { 
     new Configuration(defaultDir, defaultFileName, resourceBundle); 
    } catch (IOException | IndexWriteException | IndexReadException e) { 
     e.printStackTrace(); 
    } 
} 

這並不做什麼,你認爲它。它試圖創建一個新的對象,但實際上並沒有對它做任何事情。無論該構造函數是否成功完成,這個實例中的所有實例變量都將具有其默認值。

可以鏈其他構造,而不是使用this - 但是你必須聲明,此構造可以拋出同樣的檢查的異常:

public Configuration(ResourceBundle resourceBundle) 
    throws IOException, IndexWriteException, IndexReadException { 
    this(defaultDir, defaultFileName, resourceBundle); 
} 

不能捕獲異常當你鏈接到另一個構造函數。

如果你確實(真的,真的)想要抑制這樣的異常,你應該把它變成一個靜態方法,並確保你返回一個對新構建的實際數據對象的引用。

public static Configuration fromResourceBundle(ResourceBundle resourceBundle) { 
    try { 
     return new Configuration(defaultDir, defaultFileName, resourceBundle); 
    } catch (IOException | IndexWriteException | IndexReadException e) { 
     // Swallowing exceptions? Really? 
     e.printStackTrace(); 
     // At least the caller will get a null reference back instead of 
     // a broken object... 
     return null; 
    } 
} 
0

使用this

public Configuration(ResourceBundle resourceBundle) throws Exception { 
    this(Configuration(defaultDir, defaultFileName, resourceBundle)); 
} 

在構造函數中:

public Configuration(ResourceBundle resourceBundle) { 
    try { 
     new Configuration(defaultDir, defaultFileName, resourceBundle); 
    } catch (IOException | IndexWriteException | IndexReadException e) { 
     e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
    } 
} 

您創建的配置的另一個實例,它給你的輸出

VTDGEN - true 
VTDNAV - true 
AUTOPILOT - true 

而你CAL在另一個實例作爲喬恩斯基特指出其用默認值初始化場

編輯

玲方法,你需要拋出異常。在構造函數中吞吐異常是一種不好的做法,因爲您成功從構造函數返回並且對象未正確初始化。

+0

除了OP不能吞下異常,當然。 –

+0

謝謝你,喬恩!我已經在此添加了一個註釋 – Tala