1

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

 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 被销毁,并且它是块外的单独实例。是这样吗?

4

3 回答 3

0

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

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

这意味着 stdIn 和 in 被破坏

不,它没有。

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

不。

于 2013-10-22T00:30:03.897 回答
0

The try-with-resource statement will only close resources declared in the parentheses between the inside the try.

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


  }

The when the try ends, the try with resource will call close() on any resource declared. This doesn't necessarily "destroy" an object like a destructor in C, but it is often used that way. The variable will also fall out of scope outside the try so it can be garbage collected.

IN your example stdIn wraps System.in so System.in WILL BE CLOSED. However since it is still in scope after the try, it will not be garbage collected. (but you can't write to it anymore)

Try-with-resource is just "syntatic sugar" and will be compiled into something like this:

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

Notice that the resources are closed in reverse order to solve the nesting issue. If something threw an exception in the try block AND something else threw an exception in the finally block, then the "surpress exception" gets added to the original Exception object which can be retrieve via the new Throwable.getSuppressed() method. This is so the stacktrace correctly shows the original exception that was thrown inside the try.

for more information about try-with-resource see Oracle's tutorial: http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

于 2013-10-21T19:57:16.163 回答
0

看着你的try-with-resources,让我们只考虑包装的部分System.in

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

stdIn是包装InputStreamReader对象的InputStream对象。该InputStream对象是(除非您已更改)Java 进程的标准输入。

当您退出该try块时,它会调用stdIn.close(),这将级联并调用close()InputStreamReader级联并调用close()引用的对象System.in

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

于 2013-10-21T19:56:29.010 回答