Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.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序列化:在try或finally块中关闭流?_Java_Serialization_Inputstream - Fatal编程技术网

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

Java序列化:在try或finally块中关闭流?,java,serialization,inputstream,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 FileInputStrea

我在阅读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);
   }
}

来源:

您应该最终关闭连接。无论是尝试还是捕获,最终都将执行

我们还需要在每个连接创建后关闭它

try{
  // statements 
}catch (){
 // statements 
}
finally {
    in.close();
    fileIn.close();
}
从文件:

try
块退出时,
finally
块始终执行。这确保即使发生意外异常,也会执行finally块

运行时系统始终执行
finally
块中的语句,而不管
try
块中发生了什么。所以这是进行清理的最佳场所

所以,这意味着,如果您打开了一些连接、流或其他资源,那么您必须确保在执行代码块后它们将被关闭

要避免这种丑陋的块,可以使用实用程序方法:

public void close(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException ex) {
            // handle block
        }
    }
}
由于Java 8(但不是必需的),您可以为自己的异常处理程序提供关闭资源:

public void close(Closeable closeable, Consumer<? extends Throwable> handler) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException ex) {
            handler.accept(ex);
        }
    }
}
public void close(Closeable Closeable,Consumer您应该最终关闭block

在试区关门是个坏习惯

  try { 
     e = (Employee) in.readObject();   //Possibility of exception 
  } catch(IOException i) { 

  } catch(ClassNotFoundException c) { 

  } finally {
     in.close();
     fileIn.close();
  }

当某人在编写代码时知道它将抛出异常,他/她必须关闭打开的资源

try with resources语句

try with resources语句是一个try语句,用于声明一个或多个资源。资源是一个必须在程序完成后关闭的对象。try with resources语句确保在语句末尾关闭每个资源。实现java.lang.AutoCloseable的任何对象,包括所有对象实现java.io.Closeable的cts可以用作资源

下面的示例从文件中读取第一行。它使用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语句中声明的-无论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();
    }
}
来源=>

我在阅读Java序列化文章时,多次无意中发现流在try块而不是finally块中关闭的示例

这样做的示例是糟糕的示例。关闭
try
块中的流将适用于简单的一次性示例,但在可能多次执行代码的情况下这样做可能会导致资源泄漏

这个问题的其他答案很好地解释了关闭流的正确方法

有人能解释一下为什么会这样吗


这可以归结为教程网站的质量控制不佳,即代码审查不足。

您应该始终在
最后
块中
关闭
。
但是,您可以使用
try with resources

以下是链接:


公认的答案肯定有缺陷

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

如果您是Java 7或更高版本

不要在最后一个街区靠近 close方法可以抛出一个
IOException
,并且
FileInputStream
/
ObjectInputStream
可以为null。当您在
finally
中使用
.close
时,您必须检查null并重试/catch

改用“try with resources语句” 使用代码如下所示:

try(
    FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn)
) {
    e = (Employee) in.readObject();
    // in.close();
    // fileIn.close();
} 

try with resources语法保证资源实现接口将自动关闭。因此,您不需要对代码调用
close
方法。

这显然是一个错误的代码。如果引发IOException,流仍将打开。因为代码已损坏?对于我来说,当前正确的方法是使用
try with-Resources
。是的,我注意到同一个教程网站上有很多错误。我建议您也/改为查看StackOverflow文档网站(请参阅本页顶部的“文档(beta)”按钮)。我们还有一些“质量控制问题”目前…但我们正在努力。哇,谢谢你的建议!我从来不知道有这样一件事:数据此代码肯定有错误。close方法也会引发IOException。如果在调用in.close时发生这种情况,则异常会阻止调用fileIn.close,fileIn流保持打开状态。
try(
    FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn)
) {
    e = (Employee) in.readObject();
    // in.close();
    // fileIn.close();
}