Почему делает PrintStream.close (), заканчивают тем, что были названы дважды?

Попробуйте это:

.checked {
    color:green
 }


 <select>
   <option style="color:grey">Initial Option</option>
   <option class="checked">One</option>
   <option class="checked">Two</option>
 </select>
7
задан Simon Nickerson 12 May 2009 в 13:36
поделиться

2 ответа

Взгляните на исходный код PrintStream.

Он содержит две ссылки на базовый Writer textOut и charOut , одну базу символов и один текстовый (что бы это ни значило). Кроме того, он наследует третью ссылку на байтовый поток OutputStream, называемый out .

/**
 * Track both the text- and character-output streams, so that their buffers
 * can be flushed without flushing the entire stream.
 */
private BufferedWriter textOut;
private OutputStreamWriter charOut;

В методе close () он закрывает их все ( textOut ] в основном то же самое, что и charOut ).

 private boolean closing = false; /* To avoid recursive closing */

/**
 * Close the stream.  This is done by flushing the stream and then closing
 * the underlying output stream.
 *
 * @see        java.io.OutputStream#close()
 */
public void close() {
synchronized (this) {
    if (! closing) {
    closing = true;
    try {
        textOut.close();
        out.close();
    }
    catch (IOException x) {
        trouble = true;
    }
    textOut = null;
    charOut = null;
    out = null;
    }
}
}

Теперь интересно то, что charOut содержит (в оболочке) ссылку на сам PrintStream (обратите внимание на init (new OutputStreamWriter (this)) в конструкторе)

private void init(OutputStreamWriter osw) {
   this.charOut = osw;
   this.textOut = new BufferedWriter(osw);
}

/**
 * Create a new print stream.
 *
 * @param  out        The output stream to which values and objects will be
 *                    printed
 * @param  autoFlush  A boolean; if true, the output buffer will be flushed
 *                    whenever a byte array is written, one of the
 *                    <code>println</code> methods is invoked, or a newline
 *                    character or byte (<code>'\n'</code>) is written
 *
 * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
 */
public PrintStream(OutputStream out, boolean autoFlush) {
this(autoFlush, out);
init(new OutputStreamWriter(this));
}

Итак, вызов close () вызовет charOut.close () , который, в свою очередь, вызывает исходный close () снова,

1
ответ дан 6 December 2019 в 21:19
поделиться

Если вы посмотрите свой код в отладчике и установите точку останова в методе close () , он покажет следы стека who вызывает ваш метод close () :

  1. ваш основной метод
  2. sun.nio.cs.StreamEncoder $ CharsetSE.implClose () строка 431

полная трассировка стека для последнего выглядит так:

PrintTest$MyPrintStream.close() line: 20    
sun.nio.cs.StreamEncoder$CharsetSE.implClose() line: 431 [local variables unavailable]  
sun.nio.cs.StreamEncoder$CharsetSE(sun.nio.cs.StreamEncoder).close() line: 160 [local variables unavailable]    
java.io.OutputStreamWriter.close() line: 222 [local variables unavailable]  
java.io.BufferedWriter.close() line: 250 [local variables unavailable]  
PrintTest$MyPrintStream(java.io.PrintStream).close() line: 307  
PrintTest$MyPrintStream.close() line: 20    
PrintTest.main(java.lang.String[]) line: 27 

К сожалению, я не могу сказать , почему StreamEncoder будет вызывать обратно в ваш PrintStream, поскольку моя IDE не имеет вложенного источника для sun.nio.cs.StreamEncoder :( Это JDK 6 кстати, если это имеет значение.

Кстати, , если вы задаете этот вопрос, потому что заметили, что пользовательский код в вашем методе close () выполняется дважды, вам действительно стоит проверить, не this.closing . PrintStream.close () устанавливает значение true (а в комментариях класса указано / * Чтобы избежать рекурсивного закрытия * / ).

11
ответ дан 6 December 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: