Java 当我们关闭一个资源时,对象是否被实例化并销毁?

Java 当我们关闭一个资源时,对象是否被实例化并销毁?,java,resources,Java,Resources,我的疑问主要是在阅读以下代码中的套接字时产生的: String hostName = args[0]; int portNumber = Integer.parseInt(args[1]); try ( Socket echoSocket = new Socket(hostName, portNumber); PrintWriter out = new PrintWriter(echoSocket.getOutputSt

我的疑问主要是在阅读以下代码中的套接字时产生的:

 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());
        }
链接:

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

看看您对资源的尝试,让我们只考虑零件包装系统

stdIn是一个包装InputStreamReader对象的对象,该对象包装InputStream对象。该InputStream对象是Java进程的标准输入,除非您将其更改为Java进程的标准输入

退出try块时,它将调用stdIn.close,这将在InputStreamReader上级联并调用close,InputStreamReader将级联并调用close,这将在System.in引用的对象上级联并调用close


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

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

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


  }
当try结束时,try with资源将对任何声明的资源调用close。这并不一定会像C中的析构函数那样破坏对象,但通常是这样使用的。该变量也将超出try的作用域,因此可以对其进行垃圾收集

在您的示例中,stdIn包装System.IN so System.IN将被关闭。但是,由于在尝试后它仍在作用域中,因此不会对其进行垃圾收集。但是你不能再给它写信了

Try with resource只是syntactic sugar,它将被编译成如下内容:

    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块中抛出异常,那么suppress异常将添加到原始异常对象中,该对象可以通过新的Throwable.getsuppress方法检索。因此stacktrace正确地显示了try中抛出的原始异常

有关“试用资源”的详细信息,请参阅Oracle教程:

如果关闭资源意味着销毁对象

没有。Java中没有“销毁”这样的东西

那就意味着stdIn和in被摧毁了

不,没有

它是块外的一个单独实例。是这样吗


不。

是这样的。System.in将被关闭。@SotiriosDelimanolis我认为System.in不会被try with resource关闭,因为它没有在try块的with resource部分声明。@dkatzel stdIn在try with resources中声明。当它的结束被调用时,它将级联到它所包装的读者,依此类推。@SotiriosDelimanolis哦,你的权利。我以为你指的是System.in.@dkatzel是的,我指的是System.in引用的对象。当stdIn关闭时,它就会关闭。好的,这就清楚了。非常感谢。顺便说一句,这个链接已经在我的一个标签页上打开了,我刚通过输入/输出开始联网,只是有点晕过去了。
    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
     }
  }
}