开发者

java exception handling in constructor

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 constru开发者_开发知识库cted 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


What you can do is ensure the file exists before attempting to parse it.

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);


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:

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
}

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...


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 the FileNotFoundException, then you create and populate the file as above, and then open the FileInputStream again. The second part takes the file FileInputStream 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.


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.


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.


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.


often for my laziness I tend to not handle exceptions

I suggest you fix the laziness first. In reality you are just creating more work for yourself further down the line.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜