我正在查看Java序列化文章,并且在try块中而不是finally块中关闭流的示例中偶然发现了很多次。有人可以向我解释为什么会这样吗?
示例:
import java.io.*;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch(IOException i) {
i.printStackTrace();
return;
} catch(ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
来源:http://www.tutorialspoint.com/java/java_serialization.htm
答案 0 :(得分:5)
try-with-resources Statement
try-with-resources语句是一个声明一个或多个资源的try语句。资源是在程序完成后必须关闭的对象。 try-with-resources语句确保在语句结束时关闭每个资源。实现java.lang.AutoCloseable的任何对象(包括实现java.io.Closeable的所有对象)都可以用作资源。
以下示例从文件中读取第一行。它使用BufferedReader实例从文件中读取数据。 BufferedReader是一个在程序完成后必须关闭的资源:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
在此示例中,try-with-resources语句中声明的资源是BufferedReader。声明语句出现在try关键字后面的括号内。 Java SE 7及更高版本中的BufferedReader类实现了java.lang.AutoCloseable接口。因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常还是突然完成(由于BufferedReader.readLine方法抛出IOException),它都将被关闭。
在Java SE 7之前,您可以使用finally块来确保关闭资源,无论try语句是正常还是突然完成。以下示例使用finally块而不是try-with-resources语句:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
来源=> http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
答案 1 :(得分:2)
来自文档:
当
finally
块退出时,try
块始终执行。这确保即使发生意外异常也会执行finally块。运行时系统始终执行
finally
块中的语句,而不管try
块中发生了什么。因此,它是进行清理的理想场所。
所以这意味着如果你有一些连接,流或其他资源打开,你必须确保在你的代码块被执行后它们将被关闭。
为了避免这种丑陋的块,您可以使用实用程序方法:
public void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
// handle block
}
}
}
从Java 8开始(但不是必需的),您可以提供自己的Exception处理程序和关闭资源:
public void close(Closeable closeable, Consumer<? extends Throwable> handler) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
handler.accept(ex);
}
}
}
另外,仅仅为了知识,在没有调用finally块的情况下有two个案例。这意味着在大多数情况下它将被调用。
答案 2 :(得分:1)
你最后应该关闭连接。最后总是要执行是否进入尝试或捕获。
我们还需要在创建后关闭每个连接。
try{
// statements
}catch (){
// statements
}
finally {
in.close();
fileIn.close();
}
答案 3 :(得分:1)
我正在查看Java序列化文章,并且在try块中而不是finally块中关闭流的示例中偶然发现了很多次。
这样做的例子很糟糕。关闭try
块内的流将适用于简单的一次性示例,在代码可能被多次执行的情况下执行此操作可能会导致资源泄漏。
本课题的其他答案很好地解释了关闭流的正确方法。
有人可以向我解释为什么会这样吗?
归结为教程网站的质量控制不佳;即代码审查不充分。
答案 4 :(得分:1)
如果您是Java 7或更高版本...
close方法可以引发<properties>
.........
<sonar.exclusions>./app/models,./app/controllers</sonar.exclusions>
.........
</properties>
,而IOException
/ FileInputStream
可以为null。在ObjectInputStream
中使用.close
时,必须检查null并再次尝试/捕获。
使用try-with-resources,您的代码如下所示:
finally
尝试使用资源语法可确保实现AutoCloseable
接口的资源将自动关闭。因此,您无需在代码上调用try(
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)
) {
e = (Employee) in.readObject();
// in.close();
// fileIn.close();
}
方法。
答案 5 :(得分:0)
你应该
在try block中关闭是一个坏习惯。
try {
e = (Employee) in.readObject(); //Possibility of exception
} catch(IOException i) {
} catch(ClassNotFoundException c) {
} finally {
in.close();
fileIn.close();
}
如果有人在编写代码时知道它会引发异常,那么他/她必须 close the opened resources
答案 6 :(得分:0)
您应该始终在close
块中finally
。
但是,您可以使用try with resources
。
这里是链接:https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
答案 7 :(得分:0)
接受的答案肯定有错误。
close方法也可能引发IOException。如果发生这种情况 调用in.close时,该异常阻止了fileIn.close的获取 调用,并且fileIn流保持打开状态。
当涉及多个流时,可以如下实现:
} finally {
if ( in != null) {
try { in .close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
if (fileIn != null) {
try {
fileIn.close();
} catch (IOException ex) {
// Again, there is nothing we can do if close fails
}
}
}
或者,利用可关闭的界面
} finally {
closeResource(in);
closeResource(fileIn);
}
方法:
private static void closeResource(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
}