2013-10-25 3 views
2

이클립스에서 디버깅하는 동안 system.console을 시뮬레이트하기 위해이 사용자 정의 클래스를 사용하고 있습니다. 혼란스러운 점은 readLine의 두 번째 호출 후에 reader = new BufferedReader(new InputStreamReader( System.in));이 null을 반환한다는 것입니다. BufferedReader가 null을 돌려 준다

은 내가 System.in을 닫았지만, oracle

의 InputStream의 close 메소드는 아무것도하지 않습니다에 따라했기 때문에 그것은 생각했다.

그래서 이제 나는 혼란 스럽습니다. 여기에 코드입니다 :

public class CustomConsole { 
    public String readLine(String format, Object... args) { 
     if (System.console() != null) { 
      return System.console().readLine(format, args); 
     } 
     BufferedReader reader = null; 
     String line = null; 
     try { 
      System.out.print(String.format(format, args)); 
      reader = new BufferedReader(new InputStreamReader(
        System.in)); 
      line = reader.readLine(); 
     } catch (IOException e) { 
      Logger.fatal(e.getMessage()); 
      System.exit(-1); 
     } finally { 
      if (reader != null) { 
       try { 
        reader.close(); 
       } catch (IOException e) { 
        Logger.error("CustomConsole.readLine(): BufferedReader could not be closed"); 
        e.printStackTrace(); 
       } 
      } else { 
       Logger.error("CustomConsole.readLine(): BufferedReader is null"); 
      } 
     } 
     return line; 
    } 

    public String readLine() { 
     return readLine("", ""); 
    } 

    public char[] readPassword(String format, Object... args) { 
     if (System.console() != null) return System.console().readPassword(format, args); 
     return this.readLine(format, args).toCharArray(); 
    } 
} 

답변

2

InputStreamclose 방법은 않습니다 아무것도하지만, InputStream는 서브 클래스화할 수이 서브 클래스는 아무것도 할 close을 구현할 수 있습니다. 예를 들어 BufferedInputStream의 경우입니다. 제 컴퓨터에서이 유형은 System.in입니다.

리더를 닫을 때 모든 기본 리소스가 닫히기 때문에 System.in을 종료해야합니다. 이후에는 아무 것도 읽을 수 없습니다.

이 문제를 해결하려면 판독기를 완전히 닫은 코드 만 제거하면됩니다. BufferedReader를 매번 다시 작성한 다음 나중에 CustomConsole의 필드로 저장하고 다음 번에 다시 사용하는 것이 이상하게 보일 수 있습니다. 어쨌든 시스템에 의해 처리되는 System.in을 감싸는 래퍼 일 뿐이므로 이제까지 닫을 필요가 없습니다.

같은 것을 생산하는 것 그 정신에 클래스를 다시 쓰기 :

public class CustomConsole { 

    private BufferedReader reader; 

    public String readLine(String format, Object... args) { 
     if (System.console() != null) { 
      return System.console().readLine(format, args); 
     } 

     if (reader == null) { 
      reader = new BufferedReader(new InputStreamReader(System.in)); 
     } 

     try { 
      return reader.readLine(); 
     } catch (IOException e) { 
      Logger.fatal(e.getMessage()); 
      System.exit(-1); 
      return null; 
     } 
    } 

// .... 
+0

"BufferedReader"가 닫히지 않으면 내 프로그램이 끝날 때 누수가 발생하지 않습니까? – Wusiji

+0

두 가지 사항을 이해해야합니다. 1) 다른 독자의 래퍼 인 표준 Readers/InputStream의 모든 close() 메서드는 기본 판독기/스트림을 닫습니다. 따라서 시스템을 사용하는 마지막 스트림 만 실제로 닫을 가치가 있습니다. 그리고 귀하의 경우 그것은 System.in이기 때문에 이것은 JVM에 의해 이미 처리되었습니다. –

+0

저에게 해명 해 주셔서 감사합니다 – Wusiji

0

의 InputStream이 추상 클래스입니다. System.in은 close 메소드가 다르게 구현 된 InputStream의 서브 클래스 객체를 제공합니다.

작성한 BufferedReader를 보유 할 필드를 갖도록 클래스를 수정하는 방법은 어떻습니까? 이런 식으로 :

public class CustomConsole { 
    private BufferedReader reader; 

    public String readLine(String format, Object... args) { 
     if (System.console() != null) { 
      return System.console().readLine(format, args); 
     } else if (reader == null) { 
      reader = new BufferedReader(new InputStreamReader(
       System.in)); 
     } 

     return reader.readLine(); 
     ... 

원하는대로 예외 처리 코드를 추가하십시오. 독자를 닫을 필요는 없습니다.

관련 문제