我想在finally块中关闭我的流,但它会抛出一个IOException
所以我似乎必须在我的try
块中嵌套另一个finally
块才能关闭流。这是正确的方法吗?看起来有点笨拙。
以下是代码:
public void read() {
try {
r = new BufferedReader(new InputStreamReader(address.openStream()));
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch (IOException readException) {
readException.printStackTrace();
} finally {
try {
if (r!=null) r.close();
} catch (Exception e){
e.printStackTrace();
}
}
}
答案 0 :(得分:35)
此外,如果您使用的是Java 7,则可以使用try-with-resources statement:
try(BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()))) {
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch(IOException readException) {
readException.printStackTrace();
}
答案 1 :(得分:24)
看起来有点笨拙。
是的。至少java7试用资源修复了这个。
在java7之前,您可以创建一个吞下它的closeStream
函数:
public void closeStream(Closeable s){
try{
if(s!=null)s.close();
}catch(IOException e){
//Log or rethrow as unchecked (like RuntimException) ;)
}
}
或者将try ...最终放在try catch中:
try{
BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()));
try{
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
}finally{
r.close();
}
}catch(IOException e){
e.printStackTrace();
}
它更冗长,并且finally中的异常将在try中隐藏一个但它在语义上更接近Java 7中引入的try-with-resources。
答案 2 :(得分:23)
在Java 7中,你可以这样做......
try (BufferedReader r = new BufferedReader(...)){
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch(IOException e) {
//handle exception
}
AutoCloseable
。close()
。答案 3 :(得分:8)
是的,它是笨重,丑陋和令人困惑的。一种可能的解决方案是使用提供Commons IO方法的closeQuietly。
本页右侧的“相关”栏中有许多问题实际上是重复的,我建议仔细研究这些问题以解决这个问题。
答案 4 :(得分:5)
就像提到Commons IO库的答案一样,Google Guava Libraries对于java.io.Closeable这样的东西有一个类似的帮助方法。该课程为com.google.common.io.Closeables。您正在寻找的功能同样命名为Commons IO:closeQuietly()。
或者你可以自己动手来关闭这样的一堆:Closeables.close(closeable1,closeable2,closeable3,...):
import java.io.Closeable;
import java.util.HashMap;
import java.util.Map;
public class Closeables {
public Map<Closeable, Exception> close(Closeable... closeables) {
HashMap<Closeable, Exception> exceptions = null;
for (Closeable closeable : closeables) {
try {
if(closeable != null) closeable.close();
} catch (Exception e) {
if (exceptions == null) {
exceptions = new HashMap<Closeable, Exception>();
}
exceptions.put(closeable, e);
}
}
return exceptions;
}
}
甚至返回抛出的任何异常的映射,如果没有则返回null。
答案 5 :(得分:2)
你最终的方法是正确的。如果您在finally块中调用的代码可能会抛出异常,请确保您要么处理它,要么记录它。永远不要让它冒出最后一块。
在catch区块中,您正在吞咽异常 - 这是不正确的。
...谢谢
答案 6 :(得分:0)
public void enumerateBar() throws SQLException {
Statement statement = null;
ResultSet resultSet = null;
Connection connection = getConnection();
try {
statement = connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM Bar");
// Use resultSet
}
finally {
try {
if (resultSet != null)
resultSet.close();
}
finally {
try {
if (statement != null)
statement.close();
}
finally {
connection.close();
}
}
}
}
private Connection getConnection() {
return null;
}
source。 这个样本对我很有用。
答案 7 :(得分:0)
我在您的代码中注意到的第一件事是代码中的大括号{}(如果您查看的话)。另外,您需要将r
的值初始化为null
,因此首先需要将空值传递给对象,以便如果您编写的条件可以执行not null
条件检查并关闭流。