Java 如何廉洁地处理;未报告的异常IOException“;在流/forEach?
我正在尝试使用Java流写入文件。据我所知,只要你将异常抛出,就不必捕捉异常。 但是,编译器抛出一个错误(在stream.foreach()的行上),并说 错误:未报告的异常IOException;必须被抓住或宣布被抛出 有人能解释一下为什么会这样吗? (我只对使用流的解决方案感兴趣)Java 如何廉洁地处理;未报告的异常IOException“;在流/forEach?,java,compiler-errors,java-8,java-stream,Java,Compiler Errors,Java 8,Java Stream,我正在尝试使用Java流写入文件。据我所知,只要你将异常抛出,就不必捕捉异常。 但是,编译器抛出一个错误(在stream.foreach()的行上),并说 错误:未报告的异常IOException;必须被抓住或宣布被抛出 有人能解释一下为什么会这样吗? (我只对使用流的解决方案感兴趣) public void save(字符串文件、ArrayList文本)引发IOException{ FileWriter fw=新的FileWriter(文件); text.stream().forEach(x-
public void save(字符串文件、ArrayList文本)引发IOException{
FileWriter fw=新的FileWriter(文件);
text.stream().forEach(x->fw.write(x+“\n”);
fw.close();
}
Netbeans提出了这一点,但有没有更简单的方法
public void save(String file, ArrayList<String> text) throws IOException {
FileWriter fw = new FileWriter(file);
text.stream().forEach(x->{
try {
fw.write(x +"\n");
} catch (IOException ex) {
...
}
});
fw.close();
}
public void save(字符串文件、ArrayList文本)引发IOException{
FileWriter fw=新的FileWriter(文件);
text.stream().forEach(x->{
试一试{
fw.写入(x+“\n”);
}捕获(IOEX异常){
...
}
});
fw.close();
}
不幸的是,没有简单的解决方案。需要捕获抛出选中异常的Lambda表达式。最简单的方法可能是在单独的方法中将选中的异常转换为未选中的异常
try {
text.forEach(this::write);
catch (UncheckedIOException ex) {
...
}
private void write(String line) throws UncheckedIOException {
try {
fw.write(line +"\n");
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
});
不过,老实说,除了让save
方法更干净之外,这并没有比NetBean的建议更整洁
如果您不清楚选中/未选中异常的区别,请阅读接受的答案
请注意,
List
有一个forEach
方法(实际上是Iterable
扩展的List
方法),因此stream()
是多余的。forEach
操作需要一个消费者,其accept
方法不允许抛出选中的异常。在您的情况下,解决方案很简单:
public void save(String file, ArrayList<String> text) throws IOException {
Files.write(Paths.get(file), text, Charset.defaultCharset());
}
你可以像这样使用它
public void save(String file, ArrayList<String> text) throws IOException {
try( FileWriter fw = new FileWriter(file) ) {
IOConsumer.doForEach(text.stream(), x -> fw.write(x +"\n"));
}
}
public void save(字符串文件、ArrayList文本)引发IOException{
try(FileWriter fw=newfilewriter(文件)){
IOConsumer.doForEach(text.stream(),x->fw.write(x+“\n”);
}
}
此构造确保您在启动器级别正确处理潜在的IOException
s。注意,我用正确的try with resource构造替换了不安全的显式close()
调用
有了它,您仍然可以使用任意的中间流操作,即doForEach(text.stream().intermediateOp1().iOp2(),x->fw.write(x+“\n”)
或集合以外的流源。这是一个非常恼人的问题,我认为没有较短的解决方案。我的答案基本上包含了友好狗的答案。除了runtimeexecptions
@Thorvason之外,你不能忽略任何东西,这是不正确的。您还可以忽略Error
的子类。参见UncheckedIOException
应包括原始原因:抛出新的UncheckedIOException(ex)代码>。或者,您可以抛出ex
将异常简单地传播到调用堆栈中。在这种情况下,后面的选择似乎是合理的,因为save()
已经用抛出IOException
@code学徒谢谢-很好的捕获。你的意思是在写中抛出ex
?这是行不通的,因为它抛出了一个未选中的ex,并且ex被选中了。在最初发布该评论后,我对其进行了多次编辑。不确定您是否看到了最新版本。我认为,抛出ex在这种情况下,code>更可取,因为save()
已经有了一个合适的throws
子句。按照我阅读OP的方式,最初的问题源于lambda表达式,而不是一般的throws
子句。
public void save(String file, ArrayList<String> text) throws IOException {
Files.write(Paths.get(file),
(Iterable<String>)()->text.stream().iterator(), Charset.defaultCharset());
}
interface IOConsumer<T> extends Consumer<T> {
public default void accept(T t) {
try { doIO(t); } catch(IOException ex) { throw new UncheckedIOException(ex); }
}
void doIO(T t) throws IOException;
public static <E> void doForEach(Stream<? extends E> s, IOConsumer<? super E> c)
throws IOException {
try{ s.forEachOrdered(c); } catch(UncheckedIOException ex){ throw ex.getCause(); }
}
}
public void save(String file, ArrayList<String> text) throws IOException {
try( FileWriter fw = new FileWriter(file) ) {
IOConsumer.doForEach(text.stream(), x -> fw.write(x +"\n"));
}
}