In this program, the third string never gets printed. Why?
(This Java program was run on Eclipse Indigo on Ubuntu 10.10.)
import java.io.PrintWriter;
public class Tester
{
static void nested()
{
PrintWriter object2 = new PrintWriter(System.out, true);
object2.println("second");
object2.close(); // delete this line to make all开发者_JS百科 strings print
}
public static void main(String[] args)
{
PrintWriter object1 = new PrintWriter(System.out, true);
object1.println("first");
Tester.nested();
object1.println("third");
object1.close();
}
}
By closing the nested PrintWriter
, you also close the embedded System.out
stream, which seemingly prevents further writes to it (although I would expect an exception really instead of swallowing output).
So the entire problem can be reduced to:
public class Tester {
public static void main(String[] args) {
System.out.println("first");
System.out.close();
System.out.println("second");
}
}
This too doesn't print anymore after "first", but also doesn't throw an exception. A very quick debugging session shows there's a call to a Sun native function, which is a little harder to debug into.
Update*
This is the culprit: System.out
is of type java.io.PrintStream
and it contains the following lovely method:
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
The ensureOpen()
method indeed throws an exception, but it's swallowed here and the trouble
flag is set (a well known anti-pattern). This thus silently ignores further writes to the closed stream.
From the documentation of close() it says
Closes the stream and releases any system resources associated with it. Closing a previously closed stream has no effect
So my guess is that it is releasing the System.out and hence can't be used again. Also, I added a System.out.println("Finished");
line at the end and it doesn't output anything if a close has been called on System.out
in the code. Try it out.
精彩评论