好的,可以在变量中存储异常以便稍后抛出?

时间:2012-04-12 01:10:58

标签: java exception throw

我有一个方法被另一个类调用,该方法对一组对象执行许多步骤。具体来说,我正在将文件列表从原始位置复制到新文件夹。复制文件后,我使用与该组文件相关的其他数据更新数据库。它看起来像这样:

public void copyFilesAndStore(File[] files, DataObject additionalData){
    for (File f in files){
        copyFileToDestination(f);
    }
    updateDatabase(additionalData);
}

问题是,如果其中一个文件出现问题,copyFileToDestination(File f)方法可以抛出各种IOExceptions,但即使其中一个文件存在异常,我也要继续复制其余的文件,并进行调用以更新数据库。所以我可以这样做:

public void copyFilesAndStore(File[] files, DataObject additionalData){
    for (File f in files){
        try {
            copyFileToDestination(f);
        } catch (IOException ex) {
            log(ex);
        }
    }
    updateDatabase(additionalData);
}

但是,调用copyFilesAndStore()的类需要知道副本是否成功,但如果我捕获此方法中的所有异常,它将不会知道它们。做下面的事情是否有意义,或者我错过了更好的解决方案?

public void copyFilesAndStore(File[] files, DataObject additionalData){

    IOException encounteredException = null;

    for (File f in files){
        try {
            copyFileToDestination(f);
        } catch (IOException ex) {
            log(ex);
            encounteredException = ex;
        }
    }

    updateDatabase(additionalData);

    if (encounteredException != null)
        throw(encounteredException);
}

4 个答案:

答案 0 :(得分:3)

存储异常是非常安全的(不包括一些极端情况,比如OutOfMemoryException等),但是如果你想在循环中存储可能的异常,通常最好将它们全部存储起来:

public void copyFilesAndStore(File[] files, DataObject additionalData){ 

    List<IOException> encounteredExceptions = new LinkedList<IOException>(); 

    for (File f in files){ 
        try { 
            copyFileToDestination(f); 
        } catch (IOException ex) { 
            log(ex); 
            encounteredExceptions.add(ex); 
        } 
    } 

    updateDatabase(additionalData); 

    if (!encounteredExceptions.empty()) {
        throw(new DelayedException(encounteredExceptions)); 
    }
} 

其中DelayedException是您自己的自定义异常,可以存储其他异常的列表(类似于常规异常中的引起链)

答案 1 :(得分:1)

我认为抛出自己的例外更为合适,列出encounteredException作为原因:

throw new CopyAndStoreFailedException(encounteredException);

让您的异常类型能够跟踪多个cause异常甚至是有意义的:消费代码可能想要知道哪些特定文件无法复制,以便它可以指示对用户的问题或尝试以某种方式从问题中恢复。因此,您将自定义异常传递给encounteredExceptions的整个列表,可以通过getter方法检索。

答案 2 :(得分:0)

不要以后重新扔掉它们 - 当然,只有第一个才能进去。我个人只是将有问题的文件名(可能是一个友好的,特定的错误字符串)存储到列表中,然后再显示它们。例如。 “文件abc.txt失败:找不到”

答案 3 :(得分:-1)

没关系,但是你只是抓住最后一个例外。您可能希望存储所有有错误的文件,然后返回列表。

public void copyFilesAndStore(File[] files, DataObject additionalData){

    YourExceptionClass encounteredException = new YourExceptionClass();

    for (File f in files){
        try {
            copyFileToDestination(f);
        } catch (IOException ex) {
            log(ex);
            encounteredException.addFile(f);
        }
    }

    updateDatabase(additionalData);

    if (encounteredException.hasFiles)
        throw(encounteredException);
}