VTD-XML:在初始化对象后,它们仍然引用null

时间:2013-08-01 10:50:31

标签: java vtd-xml

问题是:在构造函数中初始化VTDGen,VTDNav或AutoPilot之后,在另一个方法中,它们引用null并抛出相应的异常。

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

为什么autoPilot会引用null?

2 个答案:

答案 0 :(得分:2)

我的猜测是你正在调用这个构造函数:

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

这不符合你的想法。它尝试创建一个新的Configuration对象,但实际上并没有对它做任何事情。无论该构造函数是否成功完成, this 实例中的所有实例变量都将具有其默认值。

可以链接到另一个构造函数,而不是使用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;
    }
}

答案 1 :(得分: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.
    }
}

您创建了另一个Configuration实例,它为您提供了输出

VTDGEN - true
VTDNAV - true
AUTOPILOT - true

你正在另一个用字段

的默认值初始化的实例上调用方法

修改

正如Jon Skeet所说,你需要抛出异常。构造函数中的吞咽异常是一种不好的做法,因为您从构造函数成功返回并且对象未正确初始化