Error handling 在Java8流foreach中引发异常

Error handling 在Java8流foreach中引发异常,error-handling,java-8,java-stream,Error Handling,Java 8,Java Stream,我使用的是Java8流,我不能在流的foreach中抛出异常 stream.forEach(m -> { try { if (isInitial) { isInitial = false; String outputName = new SimpleDateFormat(Constants.HMDBConstants.HMDB_SDF_FILE_NAME).format(new Da

我使用的是Java8流,我不能在流的foreach中抛出异常

 stream.forEach(m -> {
        try {

            if (isInitial) {
                isInitial = false;
                String outputName = new SimpleDateFormat(Constants.HMDBConstants.HMDB_SDF_FILE_NAME).format(new Date());
                if (location.endsWith(Constants.LOCATION_SEPARATOR)) {
                    savedPath = location + outputName;
                } else {
                    savedPath = location + Constants.LOCATION_SEPARATOR + outputName;
                }
                File output = new File(savedPath);
                FileWriter fileWriter = null;
                fileWriter = new FileWriter(output);
                writer = new SDFWriter(fileWriter);
            }

            writer.write(m);

        } catch (IOException e) {
            throw new ChemIDException(e.getMessage(),e);
        }

    });
这是我的特例课

public class ChemIDException extends Exception {
public ChemIDException(String message, Exception e) {
    super(message, e);
}
}

我正在使用记录器记录上层的错误。所以我想把这个异常放到最上面。谢谢


尝试扩展
运行时异常。为馈送到
foreach
而创建的方法没有throwable类型,因此您需要运行时throwable类型的方法

警告:这可能不是一个好主意


但是它可能会起作用。

为什么要使用
forEach
,一种设计用于处理每个元素的方法,而您只想处理第一个元素?您没有意识到
forEach
是作业的错误方法(或者流API中的方法比
forEach
多),而是使用
isInitial
标志来混淆这一点

试想一下:

Optional<String> o = stream.findFirst();
if(o.isPresent()) try {
    String outputName = new SimpleDateFormat(Constants.HMDBConstants.HMDB_SDF_FILE_NAME)
                       .format(new Date());
    if (location.endsWith(Constants.LOCATION_SEPARATOR)) {
        savedPath = location + outputName;
    } else {
        savedPath = location + Constants.LOCATION_SEPARATOR + outputName;
    }
    File output = new File(savedPath);
    FileWriter fileWriter = null;
    fileWriter = new FileWriter(output);
    writer = new SDFWriter(fileWriter);
    writer.write(o.get());
} catch (IOException e) {
    throw new ChemIDException(e.getMessage(),e);
}
可选o=stream.findFirst();
如果(o.isPresent())尝试{
String outputName=新的SimpleDataFormat(Constants.HMDBConstants.HMDB\u SDF\u文件名)
.格式(新日期());
if(location.endsWith(Constants.location_分隔符)){
savedPath=location+outputName;
}否则{
savedPath=location+Constants.location\u SEPARATOR+outputName;
}
文件输出=新文件(savedPath);
FileWriter FileWriter=null;
fileWriter=新的fileWriter(输出);
writer=新的SDFWriter(fileWriter);
writer.write(o.get());
}捕获(IOE异常){
抛出新的ChemIDException(e.getMessage(),e);
}
它在异常处理方面没有问题。本例假设流的元素类型为
String
。否则,您必须调整
可选
类型



但是,如果您的
i初始
标志在流处理过程中更改了不止一次,那么您的作业肯定使用了错误的工具。在使用Streams之前,您应该已经阅读并理解了StreamAPI文档的内容以及。仅将循环转换为流上的
forEach
调用并不能改进代码。

从我看到的代码来看,您应该使用
for
循环而不是流。您试图将命令式代码放在功能环境中。我想读取大文件并将一些元素写入另一个文件。这里我正在做的是用过滤器读取文件。所以我认为最好的方法是使用stream,你可能应该解释为什么这是一个坏主意,而不是帮助他们在没有其他选择的情况下继续射击自己的脚。谢谢你的回答。但是抛出泛型异常而不是抛出专用异常好吗?没有理由不能抛出
RuntimeException
的扩展,这是我推荐的。此外,如果您确保捕捉到
foreach
附近的异常,您将防止意外错误冒泡到执行顶部。在这里,我所做的是在isInitial if块内的给定位置创建文件,然后我将流的每个元素都写入创建的文件。创建文件后,isInitial将为false,然后它将执行其余的行。我不想写入流的第一个元素。我想写所有的。我想你误解了我的问题。问题是在流的foreach内部处理异常。您的
if(isInitial){isInitial=false;/*code*/}
清楚地表明代码将只执行一次,仅针对第一个元素。除非
isInitial
在开始时已
false
。在这种情况下,代码不会做任何事情。答案的最后一部分仍然有效。您正在以一种令人沮丧的方式使用流API,并且没有任何好处。无法处理已检查的异常只是其中的一个缺点。保持循环。