Java 可以在变量中存储异常以稍后抛出吗?

Java 可以在变量中存储异常以稍后抛出吗?,java,exception,throw,Java,Exception,Throw,我有一个方法被另一个类调用,该类对对象集合执行许多步骤。具体来说,我正在将文件列表从其原始位置复制到一个新文件夹。复制文件后,我用与文件组相关的其他数据更新数据库。它看起来像这样: public void copyFilesAndStore(File[] files, DataObject additionalData){ for (File f in files){ copyFileToDestination(f); } updateDatabase(a

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

public void copyFilesAndStore(File[] files, DataObject additionalData){
    for (File f in files){
        copyFileToDestination(f);
    }
    updateDatabase(additionalData);
}
public void copyFilesAndStore(File[] files, DataObject additionalData){
    for (File f in files){
        try {
            copyFileToDestination(f);
        } catch (IOException ex) {
            log(ex);
        }
    }
    updateDatabase(additionalData);
}
问题是,如果其中一个文件出现问题,copyFileToDestination(File f)方法可能引发各种IOException,但即使其中一个文件出现异常,我仍希望继续复制其余文件,并调用更新数据库。所以我可以这样做:

public void copyFilesAndStore(File[] files, DataObject additionalData){
    for (File f in files){
        copyFileToDestination(f);
    }
    updateDatabase(additionalData);
}
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);
}

当然,以后不要再扔了,反正只有第一个会扔。我个人只是将有问题的文件名(可能还有一个友好的、特定的错误字符串)存储到一个列表中,稍后再显示它们。例如,“File abc.txt failed:Not found”

我认为更适合抛出您自己的异常,将
遇到异常列为原因:

throw new CopyAndStoreFailedException(encounteredException);

让您的异常类型能够跟踪多个
原因异常甚至可能是有意义的:消费代码可能希望知道哪些特定文件未能复制,以便它可以向用户指示问题,或者尝试以某种方式从问题中恢复。因此,您可以向自定义异常传递一个完整的
遇到异常的列表,该列表可以通过getter方法检索。

这很好,但您只是抛出最后捕获的异常。您可能希望存储所有出错的文件,然后返回列表

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

存储异常是完全安全的(不包括某些特殊情况,如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)); 
    }
} 
public void copyFilesAndStore(文件[]文件,数据对象附加数据){
列表遇到异常=新建LinkedList();
对于(文件中的文件f){
试试{
copyFileToDestination(f);
}捕获(IOEX){
对数(ex);
遇到异常。添加(ex);
} 
} 
更新数据库(附加数据);
如果(!encounteredExceptions.empty()){
抛出(新延迟异常(遇到异常));
}
} 

其中,
DelayedException
是您自己的自定义异常,可以存储其他异常的列表(有点像常规异常中由链引起的异常)

我认为如果您要保存异常对象,您应该存储所有异常的集合,而不仅仅是最后一个。是的,我意识到只有最后一个异常会被抛出;我必须了解调用类(由另一个人开发)的需求是什么,他们是否关心实际发生了哪些特定异常,或者只关心至少发生了一个异常。谢谢