当我们关闭资源时,对象是否被实例化了?

时间:2013-10-21 19:39:38

标签: java resources

我的疑问主要出现在读取套接字时,在以下代码中:

 String hostName = args[0];
    int portNumber = Integer.parseInt(args[1]);

    try (
        Socket echoSocket = new Socket(hostName, portNumber);
        PrintWriter out =
            new PrintWriter(echoSocket.getOutputStream(), true);
        BufferedReader in =
            new BufferedReader(
                new InputStreamReader(echoSocket.getInputStream()));
        BufferedReader stdIn =
            new BufferedReader(
                new InputStreamReader(System.in))
    ) {
        String userInput;
        while ((userInput = stdIn.readLine()) != null) {
            out.println(userInput);
            System.out.println("echo: " + in.readLine());
        }

链接:http://docs.oracle.com/javase/tutorial/networking/sockets/examples/EchoClient.java

在上面的代码中,据我所知,PrintWriter和BufferedReader是资源,但我也在trywithreasources块中读取,一旦它结束,其中的所有资源都被关闭。但是如果关闭资源意味着破坏对象,那就意味着stdIn和in被销毁,并且它是块之外的单独实例。是这样吗?

3 个答案:

答案 0 :(得分:0)

查看您的try-with-resources,我们只选择包裹System.in的部分。

try (
    ...
    BufferedReader stdIn =
        new BufferedReader(
            new InputStreamReader(System.in))
)

stdIn是一个包装InputStreamReader对象的对象,它包装了InputStream个对象。那个InputStream对象是(除非你已经改变它)Java进程的标准输入。

当您退出try屏蔽时,它会调用stdIn.close(),它会级联并致电close() InputStreamReaderclose()会级联并呼叫System.in在{{1}}引用的对象上。

Java中没有破坏。如果上述变量引用的对象在程序中无法访问,则它们将被垃圾回收。

答案 1 :(得分:0)

try-with-resource语句只会关闭try内部括号中声明的资源。

 try ( /*anything declared here will be closed*/) {


  }

当try尝试结束时,try with resource将在声明的任何资源上调用close()。这不一定像C中的析构函数一样“破坏”对象,但它通常以这种方式使用。该变量也将超出try之外的范围,因此可以进行垃圾回收。

在您的示例中stdIn换行System.in,以便System.in将被关闭。但是,由于它在尝试后仍然在范围内,因此不会进行垃圾回收。 (但你不能再写了)

Try-with-resource只是“合成糖”,将被编译成这样的东西:

    Socket echoSocket =null
    PrintWriter out =null
    BufferedReader in =null
    BufferedReader stdIn =null
  try{


   echoSocket = new Socket(hostName, portNumber);
    out =
        new PrintWriter(echoSocket.getOutputStream(), true);
    in =
        new BufferedReader(
            new InputStreamReader(echoSocket.getInputStream()));
    stdIn =
        new BufferedReader(
            new InputStreamReader(System.in));

    String userInput;
    while ((userInput = stdIn.readLine()) != null) {
        out.println(userInput);
        System.out.println("echo: " + in.readLine());
    }
  }finally{
   if(stdIn !=null){
      try{
        stdIn.close()
      }catch(Exception e){
      //surpress exception if needed
     }
   }
  if(in !=null){
     try{
        in.close()
      }catch(Exception e){
      //surpress exception
     }
   }
   if(out !=null){
     try{
        out.close()
      }catch(Exception e){
       //surpress exception
     }
   }
   if(echoSocket !=null){
     try{
        echoSocket.close()
      }catch(Exception e){
        //surpress exception
     }
  }
}

请注意,资源以相反的顺序关闭以解决嵌套问题。如果某个东西在try块中引发异常并且其他东西在finally块中引发了异常,那么“surpress exception”会被添加到原始的Exception对象中,该对象可以通过新的Throwable.getSuppressed()方法进行检索。这样堆栈跟踪正确显示了try中抛出的原始异常。

有关try-with-resource的更多信息,请参阅Oracle教程:http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

答案 2 :(得分:0)

  

如果关闭资源意味着破坏对象

没有。 Java中没有“破坏”这样的东西。

  

这意味着stdIn和in被销毁

不,不。

  

并且它是块外的单独实例。是这样吗?

没有