public final class System {
private static native void registerNatives();
static {
registerNatives();
}
private System() {
}
public static final InputStream in = null;
public static final PrintStream out = null;
...
}
public class PrintStream extends FilterOutputStream{
...
public void println() {
newLine();
}
/**
* Prints a boolean and then terminates the line. This method behaves as
* though it invokes {@link #print(boolean)} and then
* {@link #println()}.
*
* @param x The {@code boolean} to be printed
*/
public void println(boolean x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
/**
* Prints a character and then terminates the line. This method behaves as
* though it invokes {@link #print(char)} and then
* {@link #println()}.
*
* @param x The {@code char} to be printed.
*/
public void println(char x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
/**
* Prints an integer and then terminates the line. This method behaves as
* though it invokes {@link #print(int)} and then
* {@link #println()}.
*
* @param x The {@code int} to be printed.
*/
public void println(int x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
/**
* Prints a long and then terminates the line. This method behaves as
* though it invokes {@link #print(long)} and then
* {@link #println()}.
*
* @param x a The {@code long} to be printed.
*/
public void println(long x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
/**
* Prints a float and then terminates the line. This method behaves as
* though it invokes {@link #print(float)} and then
* {@link #println()}.
*
* @param x The {@code float} to be printed.
*/
public void println(float x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
...
public void println(String x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
/**
* Prints an Object and then terminates the line. This method calls
* at first String.valueOf(x) to get the printed object's string value,
* then behaves as
* though it invokes {@link #print(String)} and then
* {@link #println()}.
*
* @param x The {@code Object} to be printed.
*/
public void println(Object x) {
String s = String.valueOf(x);
if (getClass() == PrintStream.class) {
// need to apply String.valueOf again since first invocation
// might return null
writeln(String.valueOf(s));
} else {
synchronized (this) {
print(s);
newLine();
}
}
}
...
}
public void println(int x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
근데 얘가 좀 이상한게 자바 파일 안에 있는 getClass메소드 설명과 API 문서에 있는 설명이 다르다.
자바 파일에는 이렇게 적혀있다.
다음은 API 문서에 있는 설명이다.
그럼 우선 hash code에 대해 알아보자
그러면 다음으로 런타임 클래스를 알아보자
헷갈려서 간단하게 getClass를 사용해보았다.
String s = "kimminje";
System.out.println(s.getClass());
-> class java.lang.String
아니다 getClass는 현재 객체의 클래스를 반환한다고 했다.
println은 System.out을 사용하니 위에서의 getClass는 System.out 객체의 클래스를 반환하지 않을까? 시도해보자
System.out.println(System.out.getClass());
->class java.io.PrintStream
이렇게 PrintStream으로 출력되는 것을 알 수 있다.
그러면 println의 메소드로 들어가면 if 문이 참이 되어 실행될 것이다.
이것도 확인해보자
if (System.out.getClass()== PrintStream.class){
System.out.println("true");
}
->true
true가 출력된 것으로 보아 println의 메소드도 참이 되어 writeln(String.valueOf(x));가 실행되는 것을 알 수 있다.
그렇다면 getClass()가 PrintStream 클래스와 같으니 writeln에 x값을 String으로 변환하여 넣어준다.
x값을 특별한 방식으로 출력하기 위해 사용하는 메소드인 것 같은데 구글에 writeln에 대한 정보가 없다….
public void print(int i) {
write(String.valueOf(i));
}
하지만 print 메소드가 이렇게 구성되어 화면에 출력을 해주는 메소드이니 writeln은 출력을 하고 줄바꿈을 해주는 메소드라는 것을 알 수 있다.