8

在这个java代码中,

import java.io.IOException;

public class Copy
{
   public static void main(String[] args)
   {
      if (args.length != 2)
      {
         System.err.println("usage: java Copy srcFile dstFile");
         return;
      }

      int fileHandleSrc = 0;
      int fileHandleDst = 1;
      try
      {
         fileHandleSrc = open(args[0]);
         fileHandleDst = create(args[1]);
         copy(fileHandleSrc, fileHandleDst);
      }
      catch (IOException ioe)
      {
         System.err.println("I/O error: " + ioe.getMessage());
         return;
      }
      finally
      {
         close(fileHandleSrc);
         close(fileHandleDst);
      }
   }

   static int open(String filename)
   {
      return 1; // Assume that filename is mapped to integer.
   }

   static int create(String filename)
   {
      return 2; // Assume that filename is mapped to integer.
   }

   static void close(int fileHandle)
   {
      System.out.println("closing file: " + fileHandle);
   }

   static void copy(int fileHandleSrc, int fileHandleDst) throws IOException
   {
      System.out.println("copying file " + fileHandleSrc + " to file " +
                         fileHandleDst);
      if (Math.random() < 0.5)
         throw new IOException("unable to copy file");

      System.out.println("After exception");
   }
}

我期望的输出是

copying file 1 to file 2
I/O error: unable to copy file
closing file: 1
closing file: 2

然而,有时我得到这个预期的输出,而在其他时候我得到以下输出:

copying file 1 to file 2
closing file: 1
closing file: 2
I/O error: unable to copy file  

有时甚至是这个输出:

I/O error: unable to copy file
copying file 1 to file 2
closing file: 1
closing file: 2

在每次执行期间,我是否得到第一个、第二个或第三个输出似乎都是随机发生的。我发现这个帖子显然谈到了同样的问题,但我仍然不明白为什么我有时会得到输出 1、2 或 3。如果我正确理解了这段代码,那么输出 1 应该是我每次得到的(发生异常)。如何确保始终获得输出 1,或者能够判断何时获得输出 1 或何时获得输出 2 或 3?

4

5 回答 5

19

问题是您正在将一些输出写入System.outSystem.err. 这些是独立的流,具有独立的缓冲。据我所知,它们被刷新的时间没有具体说明。

简而言之,当写入不同的流时,您不能使用输出显示的顺序来确定调用println()发生的顺序。请注意,输出System.out总是以预期的顺序出现。

就执行顺序而言,首先执行的主体try。如果它抛出异常,catch则执行相应子句的主体。该finally块总是最后执行。

于 2013-07-26T06:17:26.063 回答
4

先执行Try块,如果成功,最后执行,如果try块失败,则catch执行并finally执行。发生的事情 finally 块将执行。

如果您调用System.exit(0)finally 块未执行

于 2013-07-26T06:20:37.643 回答
2

使用 try catch 块处理异常的事情是,如果有任何异常进入 catch 块,控件将进入 try。但是每次执行时控件都会进入最终块。

于 2013-07-26T06:17:27.820 回答
1

您正在将错误消息写入标准输出和标准错误。它们具有不同的缓冲区,因此无法保证您看到的输出在两个输出流之间的顺序与您创建它的顺序相同。

由于我在您的代码中看不到任何错误(尽管return;您的catch片段中的多余部分有点卡在我的抓取中),所以我建议您将所有消息写入 stderr,并查看消息顺序是否更符合要求和你所期待的一样。

于 2013-07-26T06:18:08.733 回答
1

您的示例中有一个故障,我将删除该故障。您正在写入 System.out 和 System.err 并期望您的控制台正确同步两个流。为了消除副作用,我只会在这里使用一个流。

于 2013-07-26T06:19:05.913 回答