System.out.println 질문있습니다.
조회수 1712회
System.out.println()를 뜯어보고 있습니다. System 이라는 객체안에 PrintStream으로 선언된 객체 out에 접근하여 PrintStream의 메소드인 println을 접근 하는 것 까지는 알겠습니다.
근데, System에서 out을 선언할 때, public static final PrintStream out = null; 로 선언하고 끝입니다.
그럼 out은 객체가 생성되지 않은 상태인데 println을 접근 할 수 있는걸 보면(println이 static메소드도 아니고) 어느 부분에서 객체가 생성이 된다는 의미같은데 어느곳인지 알 수 있을까요?
아니면 제가 혹시 잘못 알고 있는걸까요?
1 답변
-
안녕하세요 찾아보니깐 Out은 PrintStream의 인스터스라네요
java.io.PrintStream 을 보면 생성자에서 this() 나 super()를 통해 out을 건드립니다. 근데 그 out의 구조는 OutputStream 에서 부터 오네요.
java.lang.Object ㄴ java.io.OutputStream ㄴ java.io.FilterOutputStream ㄴ java.io.PrintStream
FilterOutputStream 을 까보니
public class FilterOutputStream extends OutputStream { protected OutputStream out; //여기 private volatile boolean closed; private final Object closeLock = new Object(); public FilterOutputStream(OutputStream out) { this.out = out; //여기 }
PrintStream을 까보니
public class PrintStream extends FilterOutputStream implements Appendable, Closeable { 67 private final boolean autoFlush; 68 private boolean trouble = false; 69 private Formatter formatter; 75 private BufferedWriter textOut; 76 private OutputStreamWriter charOut; 107 private PrintStream(boolean autoFlush, OutputStream out) { 108 super(out); //여기 109 this.autoFlush = autoFlush; 110 this.charOut = new OutputStreamWriter(this); 111 this.textOut = new BufferedWriter(charOut); 112 } 113 119 private PrintStream(boolean autoFlush, Charset charset, OutputStream out) { 120 this(out, autoFlush, charset); //여기 121 }
참고: https://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html
수정
- 윗 내용은 타입이고 System.java 에서 out은 그대로 null
- System.java에서 setOut() 가 아닌 SetOut0() 으로 newPrintStream 을 이용해 PrintStream 객체를 만들어주고 넘김
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
- 근데 정의 부분은 없고 이것 만 있음..
private static native void setOut0(PrintStream out);
- Native 키워드는 자바 네이티브 인터페이스라고 (JNI) 다른 언어로 정의 ㄷㄷ;
- 오픈JDK로 확인해보니 http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/9b8c96f96a0f/src/share/native/java/lang/System.c 여기에 372줄에 정의되어 있음
- 댓글 감사드립니다 :) System에서 out을 선언하지만, filterOutputStream 에서도 OutputStream out을 따로 생성해주고 있습니다. PrintStream 생성자에서 건드리는 out은 , filterOutputStream 에서 생성된 out이구요. System 에서 만들어준 out을 건드리는건 아닌것 같네요. 같이 고민해 주셔서 감사합니다 :) 심승현 2018.8.23 19:38
- 저도 setOut에서 System.out을 정의한다고 보는데, 말씀하신 setOut0(~~) 이 부분에서 fdOut 에 관련하여 위에 FileOutputStream이라는 부분을 보아하니 표준출력인 콘솔을 File로 바꾸기 위해서 사용하는 부분같아보여요... 어렵네요 ㅠㅠ 심승현 2018.8.23 20:47
- 안녕하세요 제 생각 정리해보겠습니다. setOut() 가 아닌 setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding"))); 이부분인것 같습니다(뒤에 숫자0이 있습니다;) 정의부분은 private static native void setOut0(PrintStream out); 로 되어있는데 native 키워드 인거 보니 다른 언어로 정의되어있는 것 같아요 ㅠㅠ 최진우 2018.8.23 21:11
- 이거 보고 native키워드가 다른언어라고 생각했어요. https://hashcode.co.kr/questions/613/자바에서-native키워드가-뭔가요 그리고 계속 찾아보니 http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/9b8c96f96a0f/src/share/native/java/lang/System.c 여기에 372줄에 정의되어있네요 휴~ 최진우 2018.8.23 21:14
- private static native void setOut0(PrintStream out); 여기서 native에 의해서 다른 언어로 out이 초기화 된다고 봐야 겠네요. 같이 고민해주셔서 감사합니다 :) 심승현 2018.8.23 21:38
- !!!!!!!!!!!!!!!!! 정말 감사합니다! 이렇게 까지 뜯어봐주실 줄이야 너무나 감사합니다. 오늘도 많이 알고 가네요! 이런 내용은 어떻게 찾는건가요...? 조심스럽게 물어봅니다 알려주세요! 심승현 2018.8.23 21:58
- setOut0 정의부분이 어디지? -> 없네..native? 머지? -> 해쉬코드검색 -> JNI 알게됨 -> 구글링(How to find jni code in java) -> 스택오버플로우에서 오픈jdk링크 찾음 -> url 수정해봤더니 됨 -> system.c 이렇게 찾았어요! 최진우 2018.8.23 22:12
- 구웃..! 심승현 2018.8.23 23:35
댓글 입력