问题是:在构造函数中初始化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?
答案 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所说,你需要抛出异常。构造函数中的吞咽异常是一种不好的做法,因为您从构造函数成功返回并且对象未正确初始化