java构造函数中的异常处理
老实说,我对异常处理不太有经验,因为我常常因为懒惰而倾向于不处理异常。这是一个非常基本的问题。
我想知道使用异常处理方法来完成这种情况的最干净的方法是什么:
我有一个类(ConfigManager),它在其构造函数中读取文件,并且需要该文件存在才能正确构造,以构造函数的形式给出范围。 如果该文件不存在,我想捕获 FileNotFoundException,使用一些默认值创建文件,然后使用现在可用的默认配置文件继续创建 ConfigManager 对象。
这是一些代码:
class ConfigManager{
ConfigManager(String file){
try{
builder = builderFactory.newDocumentBuilder();
document = builder.parse (new FileInputStream(file));
....
}catch (FileNotFoundException e) {
File configFile = new File (file);
try {
configFile.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(this.defaultConfig);
writer.close();
return new ConfigManager(string); //Here's the problem. I can't do that but I need to try build ConfigManager again. How do that?
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
创建默认配置文件后,如何构造新的 ConfigManager 对象? 这是处理此类异常的正确方法吗?
提前致谢
honestly I'm not very experienced with exception handling, because often for my laziness I tend to not handle exceptions. So here's a very basic question.
I would like to know what's the cleanest way to accomplish this situation, with an exception handling approach:
I have a class (ConfigManager) that reads a file within its constructor, and need that file to exists to be constructed correctly, given as the constructor parameter.
If the file doesn't exist, I would like to catch the FileNotFoundException, create the file with some defaults values, and continue the creation of the ConfigManager object with the default config file now available.
Here's some code:
class ConfigManager{
ConfigManager(String file){
try{
builder = builderFactory.newDocumentBuilder();
document = builder.parse (new FileInputStream(file));
....
}catch (FileNotFoundException e) {
File configFile = new File (file);
try {
configFile.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(this.defaultConfig);
writer.close();
return new ConfigManager(string); //Here's the problem. I can't do that but I need to try build ConfigManager again. How do that?
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
How to construct a new ConfigManager object, after the default config file has been created?
Is that the rigth way to handle such type of exception?
thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您可以做的是在尝试解析文件之前确保该文件存在。
What you can do is ensure the file exists before attempting to parse it.
不要在构造函数中读取文件,创建一个方法(可能是私有的)来读取文件并在 ConfigManager 上设置值。
然后在构造函数中,您尝试再次调用构造函数,只需调用该方法即可。
即不要再次调用构造函数。
更新——我会这样组织代码:
这显然不是工作代码,而且我不知道你具体在做什么,所以据我所知。但它比你现在拥有的更具可读性,并且更有组织性。另外,如果指定的默认配置文件不存在,您真的要创建一个新的默认配置文件吗?为什么不弹出警告说配置不存在,因此您使用默认值,但不写入默认文件?您可能有理由编写默认值,如果这是真的那么就可以,但如果您不需要,请不要添加更多工作......
don't do the reading file in the constructor, create a method (possibly private) that does the reading of the file and setting of the values on the ConfigManager.
Then in the constructor, where you try to call the constructor again, just call the method.
i.e. dont call the constructor again.
update -- I would organize the code like this:
this is obviously not working code, and I dont know specifically what you are doing so its as far as I can go. But its more readable than what you have now, and a bit more organized. Also, do you really want to create a new default config file if the specified one does not exist? Why not pop up a warning saying the config did not exist so you are using defaults, but not write the default file? You might have a reason to write the default, and if thats true then ok, but if you don't have to, don't add more work...
解决方案是将构造函数分为两部分。第一部分尝试从现有文件创建
FileInputStream
。如果它抛出FileNotFoundException
,则您可以按上述方式创建并填充该文件,然后再次打开FileInputStream
。第二部分获取由第一部分打开的文件FileInputStream
(无论它是如何打开的)并继续初始化。另一种选择是将此加载推迟到
init()
方法,以便类的使用者必须创建并初始化其对象。The solution is to partition your constructor into two parts. The first part tries to create the
FileInputStream
from the existing file. If it throws theFileNotFoundException
, then you create and populate the file as above, and then open theFileInputStream
again. The second part takes the fileFileInputStream
opened by the first part (regardless of how it was opened) and proceeds with initialization.Another option is to defer this loading to an
init()
method, so that consumers of your class must both create and initialize their objects.您需要能够再次调用构造函数,但无需创建新对象 - 只需在同一个对象上调用它。由于 Java 不允许您这样做,因此您必须创建一个辅助方法,将代码从构造函数移至其中,然后从构造函数调用新方法。
对于任何需要实现递归但又不能直接递归的情况来说,这是一项基本技术。
You need to be able to call the constructor again, but without creating a new object - just calling it on the same object. Since Java doesn't allow you to do that, you have to create an auxillary method, move the code from the constructor into that, and then call the new method from the constructor.
This is a basic technique for any situation where you need to implement recursion, but you can't directly recurse.
实现此目的的最简洁方法是不执行任何可能导致构造函数中出现异常的操作。如果您绝对需要在使用对象之前执行它们,请在单独的方法 init() 中执行它们。
The cleanest way of accomplishing this is not to perform any operations that can result in exceptions in the constructor. If you absolutely need to perform them before your object can be used, do them in a separate method init().
尝试将配置文件的解析委托给另一种方法。这样,您可以先检查文件是否存在,然后创建一个默认文件,或者将现有文件传递给这个新方法。
Try delegating the parsing of the configuration file to another method. That way, you can check if the file exists first and then either create a default one, or pass the existing one to this new method.
嗯,实际上,在构造函数执行成功且没有错误后,您已经有了一个新的 ConfigManager 实例。因此,您所要做的就是删除有问题的行。
或者考虑使用静态初始值设定项。当您的应用程序部署/启动时,这只会检查该文件一次。
Well, actually you have a new instance of ConfigManager after the constructor was executed without an error. So all you have to to is to just remove the line in question.
Or consider using a static initializer. This will check for the file only once, when your application is deployed/started.
我建议你先解决懒惰问题。事实上,你只是在为自己创造更多的工作。
I suggest you fix the laziness first. In reality you are just creating more work for yourself further down the line.