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

そして、最初、2番目、または3番目の出力を取得するかどうかは、実行ごとにランダムに発生するようです。明らかに同じ問題について話しているTHIS POSTを見つけましたが、出力 1、2、または 3 を取得する理由がまだわかりません。このコードを正しく理解していれば、出力 1 が毎回取得されるはずです (例外が発生します)。 )。出力 1 を一貫して取得する方法、または出力 1 を取得する時期または出力 2 または 3 を取得する時期を判断できるようにするにはどうすればよいですか?

4

5 に答える 5

19

System.out問題は、いくつかの出力をとに書き込んでいることですSystem.err。これらは、独立したバッファリングを備えた独立したストリームです。それらがフラッシュされるタイミングは、私の知る限り、指定されていません。

println()要するに、異なるストリームに書き込む場合、出力が表示される順序を使用して呼び出しが発生した順序を決定することはできません。System.outへの出力は、常に予想される順序で表示されることに注意してください。

実行順序に関しては、本体がtry最初に実行されます。例外がスローされると、適切なcatch句の本体が実行されます。finallyブロックは常に最後に実行されます。

于 2013-07-26T06:17:26.063 に答える
4

最初に実行Tryブロックが成功した場合は最終的に実行され、tryブロックが失敗した場合catchは実行されfinally実行されます。最終ブロックが実行されます。

しかし

System.exit(0)finally ブロックを呼び出すと実行されない

于 2013-07-26T06:20:37.643 に答える
2

try catch ブロックを使用した例外処理では、catch ブロック内で例外が発生した場合、コントロールが try 内に移動します。ただし、コントロールは実行されるたびに最終ブロックに移動します。

于 2013-07-26T06:17:27.820 に答える
1

あなたの例には、私が削除するグリッチが1つあります。System.out と System.err の両方に書き込みを行っており、コンソールが両方のストリームを正しく同期することを期待しています。副作用を取り除くために、ここではストリームを 1 つだけ使用します。

于 2013-07-26T06:19:05.913 に答える
1

エラーメッセージを stdout と stderr の両方に書き込んでいます。これらには異なるバッファーがあるため、表示される出力が、2 つの出力ストリーム間で、作成した順序と同じになるという保証はありません。

あなたのコードにはエラーが見られないので (return;あなたのcatchセグメントの余分な部分が私のクローに少し引っかかっていますが)、すべてのメッセージを stderr に書き込んで、メッセージの順序がもう少し合っているかどうかを確認することをお勧めします。あなたが期待していたもので。

于 2013-07-26T06:18:08.733 に答える