Java序列化:在try或finally块中关闭流?

时间:2016-09-19 11:50:45

标签: java serialization inputstream

我正在查看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

8 个答案:

答案 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或更高版本...

不要在finally块中关闭

close方法可以引发<properties> ......... <sonar.exclusions>./app/models,./app/controllers</sonar.exclusions> ......... </properties> ,而IOException / FileInputStream可以为null。在ObjectInputStream中使用.close时,必须检查null并再次尝试/捕获。

改为使用“ try-with-resources语句”

使用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)

你应该 在finally块中关闭

在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
  }
 }
}