2

老实说,我对异常处理不是很有经验,因为经常因为我的懒惰,我倾向于不处理异常。所以这是一个非常基本的问题。

我想知道用异常处理方法完成这种情况的最干净的方法是什么:

我有一个类(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 对象?这是处理此类异常的正确方法吗?

提前致谢

4

8 回答 8

4

您可以做的是在尝试解析文件之前确保文件存在。

FileInputStream fis = null;
try {
    fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
    BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
    writer.write(defaultConfig);
    writer.close();
    fis = new FileInputStream(file);
}

try{
     builder = builderFactory.newDocumentBuilder();
     document = builder.parse (fis);
于 2011-05-16T15:00:30.290 回答
2

不要在构造函数中读取文件,创建一个方法(可能是私有的)来读取文件并设置 ConfigManager 上的值。

然后在构造函数中,您尝试再次调用构造函数,只需调用该方法即可。

即不要再次调用构造函数。

更新——我会像这样组织代码:

ConfigManager(String fileName) {
   File file = new File(fileName);
   if (!file.exists()){
       // create this method -- Im assuming its ok to put the default 
       // config on the path where the file did not exist.
       createDefaultConfigFile(fileName); 
   }

   parseConfigFile(fileName, ...); // create this method too
}

这显然不是工作代码,我不知道具体你在做什么,所以尽我所能。但它比您现在拥有的更具可读性,并且更有条理。另外,如果指定的配置文件不存在,您真的要创建一个新的默认配置文件吗?为什么不弹出警告说配置不存在,所以您使用默认值,但不写入默认文件?您可能有理由编写默认值,如果这是真的,那么可以,但如果您不需要,请不要添加更多工作......

于 2011-05-16T14:56:10.130 回答
1

解决方案是将构造函数分成两部分。第一部分尝试FileInputStream从现有文件创建。如果它抛出FileNotFoundException,那么您如上所述创建并填充文件,然后FileInputStream再次打开。第二部分获取FileInputStream第一部分打开的文件(不管它是如何打开的)并继续初始化。

另一种选择是将这种加载推迟到一个init()方法中,这样你的类的消费者必须同时创建和初始化他们的对象。

于 2011-05-16T14:56:01.340 回答
1

您需要能够再次调用构造函数,但无需创建新对象 - 只需在同一个对象上调用它。由于 Java 不允许您这样做,因此您必须创建一个辅助方法,将代码从构造函数移到该方法中,然后从构造函数调用新方法。

对于需要实现递归但不能直接递归的任何情况,这是一项基本技术。

于 2011-05-16T14:56:25.937 回答
1

实现这一点的最干净的方法是不执行任何可能导致构造函数异常的操作。如果在使用对象之前绝对需要执行它们,请在单独的方法 init() 中执行它们。

于 2011-05-16T14:56:45.220 回答
1

尝试将配置文件的解析委托给另一种方法。这样,您可以先检查文件是否存在,然后创建一个默认文件,或者将现有文件传递给这个新方法。

于 2011-05-16T14:56:54.257 回答
1

好吧,实际上在构造函数执行后没有错误的情况下,您有一个新的 ConfigManager 实例。所以你所要做的就是删除有问题的行。

或者考虑使用静态初始化程序。当您的应用程序部署/启动时,这将只检查一次文件。

于 2011-05-16T14:58:05.853 回答
1

通常因为我的懒惰,我倾向于不处理异常

我建议你先解决懒惰。实际上,您只是在为自己创造更多的工作。

于 2011-05-17T01:49:22.860 回答