System.out.println("Hello");
System은 클래스이다. 왜인고 하니 일단 첫 문자가 대문자로 작성되었기 때문이다. 첫 문자에 저렇게 대문자를 콰광 박을 수 있을 수 있는 건 클래스 뿐이다. 그리고 맨 뒤를 보니 println();이 있다. 이 형태는 익숙하다. 매개변수를 받아 특정한 행동을 명령 하는 메소드가 분명하다. 그런데 우리가 객체 지향을 배울 때 객체를 생성해서 객체.메소드(); 형태로 사용하지 않았나? 그런데 갑자기 클래스 명이 튀어 나와서 맨 앞을 차지하고 있다. 또 아직 문제가 남았다. 나는 이런 메소드를 정의한 적이 없다는 것이다. 저 클래스는 또 어디서 왔는가. 가온데 있는 out은 또 뭔가. 알아보도록 하자.
우선 이런 경우를 되돌려 떠올려 보자. 내가 원곡_초등학교 라는 클래스를 생성했고 이 클래스에 static으로 선언된 교내안내방송하기()라는 메소드가 있는 상황이다.
public class 원곡_초등학교{
static 교내안내방송하기 (String 할말){
System.out.println("띵똥 땡똥 교내 안내 방송입니다."+할말);
}
}
원래는
원곡_초등학교 강감찬_선생 = new 원곡_초등학교();
강감찬_선생.교내안내방송하기("지금 교문 밖으로 나가고 있는 학생들 교무실로 오도록.");
이런 식으로 교내 방송 메소드를 사용해야 한다. 그런데! static으로 선언되어 있으면 인스턴스 없이도 사용이 가능하다. (= 이 말을 다른 말로 하면 static으로 선언된 변수나 메소드는 모든 클래스의 인스턴스가 공유하는 내용이라서 구태여 인스턴스화 시켜 개별화 시킬 필요가 없다는 뜻이다.) 따라서 원곡_초등학교.교내안내방송하기(); 이런식으로 바로 바로 방송을 쏠 수 있는 것이다. 자 이제 실마리를 하나 잡았다. System이 클래스인데 그 뒤에 붙은 것이 out 이다. 이 말은 out에 static이 붙어있어 객체 생성 없이도 상용가능하다는 뜻이된다. 그런데 매개 변수를 넘겨줄 ()이 안보인다. 적어도 메소드는 아닌 것 같다. api에서 정체를 까보자.
어디 있나 봤더니 변수 등을 모아 놓은 필드써머리에 있었다. out이라는 변수가 있는 것이다. 그래 여기까지 해서 System.out 의 관계는 알았다. 그런데 그 뒤에 println은 또 뭔가. 그 질문을 하려고 봤더니 out이라는 변수의 타입이 이상하다. int형도 아니고 char도 아니다. 뭔고 하니 읽어보니 PrintStream 이다. 기본 자료형이 아니라 바로 참조 자료형! 다시 말해 클래스이다. 그러니까 out은 우리가 int나 char을 사용할 때 사용하던 기본 자료형의 일반적인 변수가 아니라 객체인 것이다. 객체! 그것은 클래스의 메소드를 활용 할 수 있다. 그렇다면 뭔가 각이 나온다 PrintStream 의 메소드 중에 println이 있는 것인가! 확인해 보도록 하자.
위에 보이는 것은 파란색 링크로 걸려있는 PrintStream 을 클릭해서 본 메소드 목록 중 println이다. 예상대로다. out은 System클래스의 필드이면서 동시에 자신이 속한 자료형인 PrintStream 클래스의 메소드를 사용할 수 있는 객체가 된 것이다.
결론. 어떤 함수를 불러오는데 System.out.println(); 이런 식으로 3개의 덩이로 구성되어 있다면. 실질적으로 첫번째 덩어리 System은 카테고리의 역할만 할 뿐이고 기능은 out이라는 객체와 그 객체에서 뽑아온 println();이라는 함수가 하는 것이다.