Last Modified : 2010.12.06

객체와 클래스

자바는 객체 지향 프로그래밍 언어라 했다.
객체 지향 프로그래밍에서는 객체와 객체가 서로 통신하면서 일을 해 나간다.
현실 세계의 객체를 프로그램 세계의 객체로 반영하여 프로그래밍 한다면 누구나 이해할 수 있는 프로그램이 될 것이다.

문제를 해결하기까지의 절차에 촛점을 맞춘 프로그래밍을 절차 지향 프로그래밍이라 한다.
절차지향 프로그래밍은 단점은 코드의 양이 증가할수록 객체 지향 프로그래밍에 비해 재사용성과 유지보수의 어려움이 급격하게 증가하는다는 것이다.
세계는 점점 더 복잡하게 될 것이고 그에 따라 프로그램에 요구하는 사항도 증가할 것이다.
이것이 객체 지향 프로그래밍이 주목을 받고 있는 이유이다.

객체 지향 프로그래밍에 입문하는 첫단계는 객체를 이해하는 것이다.
객체에 대한 개념은 쉽게 접근해야 한다.
실세계에서 여러분이 볼 수 있고 만질수 있는 것은 일단 모두 객체다.
예를 들면 당신은 객체다. 당신의 옆에 있는 동료 역시 객체다.

객체의 특징(현실 세계)

현실 세계의 객체를 프로그래밍 세계의 객체로 만들기 위해서 먼저 현실세계의 객체의 특징을 살펴본다.

속성을 가진다.

먼저 각각의 객체는 다른 객체와 구별되는 속성을 가지고 있다.
학생은 이름, 핸드폰 번호, 등록과정명이 속성이다.

행위(동작)를 가진다.

학생은 출석하다, 공부하다, 결석하다, 조퇴하다, 지각하다 같은 동작을 한다.

유일무이(unique)하다.

바로 당신이 객체라고 했다.
이 세상에서 당신이라는 존재는 유일무이하다.

객체 지향 프로그래밍에서의 객체의 정의

속성과 그 속성과 관련된 동작을 한 몸으로 가지는 것을 말한다.

객체를 만들기 위해서는 먼저 클래스를 만들어야 한다.

현실 세계의 학생 객체를 매핑하여 자바 프로그램에서 동작하는 학생 객체를 만들어 보자.
자바 프로그램 속에서 활동할 학생 객체를 만들려면 먼저 학생 클래스를 먼저 만들어야 한다.

학원에서 출결 관리를 위한 프로그램이 필요하고 조건은 아래와 같다고 가정하자.

수료는 수업의 80%를 출석해야 한다.
지각이나 조퇴 3번은 1번의 결석으로 계산한다.

학생의 속성과 행위는 아래와 같을 것이다.

속성 : 이름, 핸드폰 번호, 결석수, 조퇴수, 지각수
동작(행위) : 결석하다, 조퇴하다, 지각하다

이와 같이 클래스를 만들때는 속성과 행위를 유추해서 만든다.
실세계의 학생의 속성과 동작을 모두 유추하지 않는다. (가능하지도 않고 필요하지도 않다.)
이렇듯 실세계의 객체에서 프로그램에 필요한 부분만을 추려 내는 과정을 통해 클래스를 만들게 된다.
자 이제 학생 클래스를 실제로 작성해 보자.

Student.java

class Student {
	String name; // 이름
	String mobile; // 핸드폰 번호
	int absentSum; // 결석수
	int comLateSum; // 지각수
	int goEarlySum; // 조퇴수
	
	// 결석하다
	void absent() {
		absentSum = absentSum + 1;
	}
	
	// 지각하다
	void comeLate() {
		comeLateSum = comLateSum + 1;
	}
	// 조퇴하다
	void goEarly() {
		goEarlySum = goEarlySum + 1;
	}
}

위는 프로그래머가 작성한 자바 클래스 소스 파일이다.
확장자가 .java 인 클래스 소스 파일을 컴파일하면 확장자가 .class 인 자바 프로그램에서 객체를 만들기 위한 재료가 되는 클래스 파일이 된다.
확장자가 .class인 파일을 바이트 코드라고 부르는데 이는 바이트 단위로 해석되기 때문이다.

Student 클래스에서 객체의 속성(name, mobile, absentSum, comLateSum, goEarlySum)을 필드(field)라고 부른다.
absent(), comeLate(), goEarly()를 메소드(method)라고 부른다.
함수라고 하지 않고 메소드라고 부르는 이유는 객체를 동작하게 하는 방법(method)이란 의미이다.

학생 클래스(바이트 코드)가 클래스 로더에 의해 메모리에 로딩되면 학생 객체를 만들 준비가 완성된다.
객체를 생성하기 위해서는 new 라는 키워드가 사용 된다.
new 키워드를 사용하면 붕어빵틀을 통해 붕어빵을 찍어 내듯이 클래스 파일을 통해서 객체가 만들어진다.

위의 예제는 단독으로 실행할 수 없다.
그래서 불가피하게 위 소스에 main 메소드를 삽입하겠다.
main 메소드는 자바 애플리케이션에서 시작점이 된다.
자바 애플리케이션에서는 시작점이 되는 클래스에 main 메소드를 선언한다.
여기서 선언이라고 하는 단어가 중요하다.
메소드의 선언이라 하면 메소드의 구조를 만드는 코드를 의미한다.
만약 Student 클래스에 메인 메소드를 선언하고 명령프롬프트에서 java Student 로 실행한다면 JVM 이 Student 의 메인 메소드를 실행한다. 이것이 자바 프로그램이 시작하기 위한 약속이다.
다음은 main 메소드의 선언부를 나타내고 있다.

	public static void main (String[] args) {
 		// 구현 부분 ..
	}

간단히 main 메소드를 설명해 보겠다.
여기서 public 은 접근자 종류 중 하나이다.
접근자는 필드 선언부나 메소스 선언부에 붙어 외부에서 필드나 메소드에 접근할 수 있는지 여부를 결정한다.
여기서 public 이 쓰였다는 것은 외부에서 이 메소드를 호출할 수 있다는 것이다.
java Student 와 같이 실행할 때 외부(JVM 요소)에서 main 메소드를 호출하는 것이니 당연히 public 접근자이어야 한다.
접근자에 대해서는 팩키지와 접근자 에서 자세하게 다룬다.

키워드 static 은 정적(static)필드나 정적 메소드를 선언할 때 사용한다.
필드나 메소드 선언부에 static이 붙으면 클래스 차원의 필드나 메소드가 된다.
클래스차원의 필드와 메소드는 객체를 생성하지 않고도 해당 필드에 접근할 수 있고 해당 메소드를 호출할 수 있다.
java Student 와 같이 실행할 때 Student 클래스의 main 메소드가 호출된다고 했다.
이때 Student 객체가 생성되지 않은 상태에서 main메소드를 호출되는 것이니 main 메소드는 static이어야 한다.
static에 대해서는 static 키워드에서 자세히 다룬다.

void 는 자바에서 반환값이 없는 메소드를 선언할 때 사용한다.
자바에서는 반환값이 없는 메소드를 만들때는 메소드 이름 앞에 void를 붙여주어야 한다.

main 메소드의 매개변수(또는 파라미터) args 은 데이터 타입이 String배열이다.
배열은 동일한 타입의 값을 연이어 저장하는 변수이다.
예제는 args매개변수를 사용하지 않는다.
배열에 관해서는 배열에서 자세하게 다룬다.

이제 기존의 Student.java 소스을 열고 아래와 같은 내용으로 main 메소드를 추가한 후 컴파일하고 실행해 보자.
컴파일 방법은 명령 프롬프트에서 javac Student.java
실행 방법은 java Student 이다.

Student.java

class Student {
	String name; // 이름
	String mobile; // 핸드폰 번호
	int absentSum; // 결석수 누계
	int comeLateSum; // 지각수 누계
	int goEarlySum; // 조퇴수 누계
	
	// 결석하다
	void absent() {
		absentSum = absentSum + 1;
	}
	
	// 지각하다
	void comeLate() {
		comeLateSum = comeLateSum + 1;
	}
	
	// 조퇴하다
	void goEarly() {
		goEarlySum = goEarlySum + 1;
	}
	
	// 메인 메소드 추가
	public static void main(String[] args) {
		Student kim = null;
		Student hong = null;

		kim = new Student(); 
		kim.name = "김태희";
		kim.mobile = "010-1111-2222";

		hong = new Student();
		hong.name = "홍길동";
		hong.mobile = "010-3333-4444";

		kim.absent();
		hong.absent();
		kim.absent();

		System.out.println(kim.absentSum);
		System.out.println(hong.absentSum);
	}
}
C:\>javac Student.java

C:\>java Studnet
2
1

C:\>

Student kim = null;

25라인
Student객체를 참조할 수 있는 레퍼런스형 변수 kim을 선언하고 null로 초기화 시키는 코드이다.
kim은 레퍼런스(reference)형 변수로 Student클래스로 부터 생성된 객체를 가리킬 수 있다.
가리킬 수 있다는 것은 kim에는 생성된 객체를 참조할 수 있는 참조값이 대입된다는 것을 의미한다.
참조값은 메모리맵에서 객체가 생성된 곳의 4바이트 주소값이다.
자바에서 기존 언어(절차지향적 프로그래밍)의 변수 형태인 기본자료형과 함께 객체를 가리키는 변수인 레퍼런스 형(Reference) 변수가 존재한다.
만약 레퍼런스 형 변수 kim이 아무런 학생 객체를 가리키지 않는다고 명시하려면 null이라는 키워드를 사용한다.
null은 그래서 레퍼런스형 변수의 초기화에 쓰인다.

kim = new Student();

28라인
new키워드를 사용하여 Student객체를 만들고 kim에 생성한 Student객체의 참조값을 대입하는 코드이다.
레퍼런스 형 변수에 대입되는 값은 객체를 참조할 수 있는 값이 대입된다고 했다.
다시 말해 객체 자체가 대입되지 않는다.

kim.name = "김태희";

29라인
레퍼런스 kim이 가리키는 객체의 name속성을 설정하는 코드이다.
생성된 객체를 조작하기 위해서 레퍼런스 형 변수를 사용되는데 이때 예제처럼 레퍼런스 다음에 .(도트)을 이용하여 레퍼런스가 가리키고 있는 객체의 필드나 메소드에 접근 할 수 있다.

kim.absent();

레퍼런스 kim이 가리키는 Student객체에 결석하다()메소드 호출하는 코드이다.

표준 출력 메소드 [ System.out.print(), System.out.println() ]

학생 클래스를 만들고 클래스로부터 학생 객체를 생성하고 테스트해 보았다.
결과를 출력하기 위해 System.out.println()메소드를 사용했다.
자바 기초 예제에서는 결과를 보기 위해서 이 메소드를 자주 사용하게 된다.
아래 예제는 표준 출력 메소드의 모든 쓰임새를 보여준다.

참고로
System.out.print() 와 System.out.println() 의 차이점은 System.out.println() 메소드는 출력 후 라인을 바꾼다는 것 뿐이다.

StandardOutput.java

public class StandardOutput {

	public static void main(String[] args) {

		System.out.println(true);	// 불린값을 출력하고 개행
		System.out.println('A');	// char 'A'를 출력하고 개행
		
		char[] x = {'A','B','C'};
		
		System.out.println(x);		// char 형 배열을 출력하고 개행
		System.out.println(99.9);	// double 형 자료를 출력하고 개행
		System.out.println();		// 단순히 줄을 바꾼다(개행)
		System.out.println(99.9F);	// float 형 자료를 출력하고 개행
		System.out.println(100);	// int 형 자료를 출력하고 개행
		System.out.println(40000000L);	// long 형 자료를 출력하고 개행
		System.out.println(System.out);	// 해당 객체를 출력하고 개행
		System.out.println("표준출력메소드 테스트");	// 문자열을 출력하고 개행
	}
}
C:\>javac StandardOutput.java

C:\>java StandardOutput
true
A
ABC
99.9

99.9
100
40000000
java.io.PrintStream@de6ced
표준출력메소드 테스트