Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么未处理的IOException会在stream.forEach()中触发,而不是在普通for循环中触发_Java_For Loop_Foreach_Java 8_Ioexception - Fatal编程技术网

Java 为什么未处理的IOException会在stream.forEach()中触发,而不是在普通for循环中触发

Java 为什么未处理的IOException会在stream.forEach()中触发,而不是在普通for循环中触发,java,for-loop,foreach,java-8,ioexception,Java,For Loop,Foreach,Java 8,Ioexception,未处理的IOException在以下代码中触发: ZipOutputStream zos = new ZipOutputStream(outputStream); testIds.stream().forEach(testId->{ zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));

未处理的
IOException
在以下代码中触发:

ZipOutputStream zos = new ZipOutputStream(outputStream);
testIds.stream().forEach(testId->{
            zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
            zos.write(files.get(testId));
            zos.closeEntry();
        });
ZipOutputStream zos = new ZipOutputStream(new ByteArrayOutputStream());    
for (Integer testId : testIds) {
    zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
    zos.write(files.get(testId));
    zos.closeEntry();
}
但以下代码中的情况并非如此:

ZipOutputStream zos = new ZipOutputStream(outputStream);
testIds.stream().forEach(testId->{
            zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
            zos.write(files.get(testId));
            zos.closeEntry();
        });
ZipOutputStream zos = new ZipOutputStream(new ByteArrayOutputStream());    
for (Integer testId : testIds) {
    zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
    zos.write(files.get(testId));
    zos.closeEntry();
}

看起来您正在关闭循环中的流。第二次,流被关闭。

看起来您正在关闭循环中的流。第二次,流关闭。

它不是特定于
forEach

检查lambda主体中抛出的异常,而不检查lambda主体中抛出的异常。

15.27.3。Lambda表达式的类型

可在lambda主体中引发的已检查异常 表达式可能导致编译时错误,如§11.2.3所述

此时,您可以阅读:

11.2.3。异常检查

如果lambda主体可以引发一些异常,则这是一个编译时错误 类E,当E是一个已检查的异常类且E不是 目标函数类型的throws子句中声明的某个类 通过lambda表达式

foreach()
接受一个
Consumer
,您可以看到中定义的
accept()
没有声明任何异常:

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);    
    ...
}
因此,编译很好,因为选中的异常已“处理”:您将抛出它。
出于解释原因,同样的事情不适用于lambda。

作为解决方法,您有两种方法:

  • 不使用流。你应该考虑这一点,因为它在你的用例

  • 中没有很多附加值。
  • 捕捉异常

  • ZipOutputStream zos = new ZipOutputStream(outputStream);
    testIds.stream().forEach(testId->{
        try{
            zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
            zos.write(files.get(testId));
            zos.closeEntry();
        } catch(IOException e) {
            throw new RuntimeException(e)
        }
    }
    
关于第二点,由于不能从lambda主体抛出
IOException
,因此必须使用
catch
语句来处理它。
如果异常应该传播到客户端,则可以重新抛出一个
RuntimeException
,该异常将实际异常包装为运行时异常,因为运行时异常与lambda正文中的已检查异常没有相同的限制:

ZipOutputStream zos = new ZipOutputStream(outputStream);
testIds.stream().forEach(testId->{
           try{
                zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
                zos.write(files.get(testId));
                zos.closeEntry();
            }
            catch(IOException e){
                // log the exception 
                throw new RuntimeException(e);
                // or throw a custom RuntimeException class if it makes more sense
            } 
        });

它不特定于
forEach

检查lambda主体中抛出的异常,而不检查lambda主体中抛出的异常。

15.27.3。Lambda表达式的类型

可在lambda主体中引发的已检查异常 表达式可能导致编译时错误,如§11.2.3所述

此时,您可以阅读:

11.2.3。异常检查

如果lambda主体可以引发一些异常,则这是一个编译时错误 类E,当E是一个已检查的异常类且E不是 目标函数类型的throws子句中声明的某个类 通过lambda表达式

foreach()
接受一个
Consumer
,您可以看到中定义的
accept()
没有声明任何异常:

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);    
    ...
}
因此,编译很好,因为选中的异常已“处理”:您将抛出它。
出于解释原因,同样的事情不适用于lambda。

作为解决方法,您有两种方法:

  • 不使用流。你应该考虑这一点,因为它在你的用例

  • 中没有很多附加值。
  • 捕捉异常

  • ZipOutputStream zos = new ZipOutputStream(outputStream);
    testIds.stream().forEach(testId->{
        try{
            zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
            zos.write(files.get(testId));
            zos.closeEntry();
        } catch(IOException e) {
            throw new RuntimeException(e)
        }
    }
    
关于第二点,由于不能从lambda主体抛出
IOException
,因此必须使用
catch
语句来处理它。
如果异常应该传播到客户端,则可以重新抛出一个
RuntimeException
,该异常将实际异常包装为运行时异常,因为运行时异常与lambda正文中的已检查异常没有相同的限制:

ZipOutputStream zos = new ZipOutputStream(outputStream);
testIds.stream().forEach(testId->{
           try{
                zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
                zos.write(files.get(testId));
                zos.closeEntry();
            }
            catch(IOException e){
                // log the exception 
                throw new RuntimeException(e);
                // or throw a custom RuntimeException class if it makes more sense
            } 
        });

这是因为
.forEach()
消费者
)中使用的接口中的方法签名没有声明引发异常

ZipOutputStream zos = new ZipOutputStream(outputStream);
testIds.stream().forEach(testId->{
    try{
        zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
        zos.write(files.get(testId));
        zos.closeEntry();
    } catch(IOException e) {
        throw new RuntimeException(e)
    }
}
签名如下所示:

public interface Consumer<T> {
     void accept(T t); // <-- no throws declaration
}
 public void method() throws IOException{ // <-- throws declaration here
     ZipOutputStream zos = new ZipOutputStream(new ByteArrayOutputStream());    
     for (Integer testId : testIds) {
         zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
         zos.write(files.get(testId));
         zos.closeEntry();
     }
}    
公共接口使用者{

void accept(T);//这是因为
.forEach()
消费者
)中使用的接口的方法签名没有声明引发异常

ZipOutputStream zos = new ZipOutputStream(outputStream);
testIds.stream().forEach(testId->{
    try{
        zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
        zos.write(files.get(testId));
        zos.closeEntry();
    } catch(IOException e) {
        throw new RuntimeException(e)
    }
}
签名如下所示:

public interface Consumer<T> {
     void accept(T t); // <-- no throws declaration
}
 public void method() throws IOException{ // <-- throws declaration here
     ZipOutputStream zos = new ZipOutputStream(new ByteArrayOutputStream());    
     for (Integer testId : testIds) {
         zos.putNextEntry(new ZipEntry(testId + "_" + (Calendar.getInstance().getTimeInMillis() / 1000) + ".pdf"));
         zos.write(files.get(testId));
         zos.closeEntry();
     }
}    
公共接口使用者{

void accept(T);//异常将从lambda内抛出,这意味着lambda的调用方需要捕获/检查异常。我假设您的代码段外有一个
try catch
throws
子句

由于
forEach
没有为您检查异常,因此
IOException
未处理。您必须处理它。最简单的方法是捕获异常并将其包装(例如在运行时异常中)


异常将从lambda内抛出,这意味着lambda的调用方需要捕获/检查异常。我假设您的代码段外有
try-catch
throws
子句

由于
forEach
没有为您检查异常,因此
IOException
未处理。您必须处理它。最简单的方法是捕获异常并将其包装(例如在运行时异常中)


两个代码段在未处理的异常方面都有相同的问题。@Tom为您附上屏幕截图。即使屏幕截图也不包含明显重要的方法头。在屏幕截图中,您可以清楚地看到stream.forEach代码段出现编译时错误,但其他代码段的情况不同。是的,正如我所说的方法头抛出s例外。不,你没有说过。无论是在问题中,在问题的编辑中,还是在这个问题下的评论中。这两个代码段对于未处理的例外都有相同的问题。@Tom为你附上屏幕截图。甚至屏幕截图也没有包含明显重要的方法标题。在屏幕截图中,你可以清楚地看到这一点stream.forEach代码段给出了编译时错误,但与其他代码段的情况不同。是的,正如我所说的,方法头抛出异常。不,您没有说过。在问题中,在