클래스 맴버 vs 객체 멤버

클래스 맴버 vs 객체 멤버

 

클래스 맴버 vs 객체 멤버 = static 멤버 vs 인스턴스 멤버

 

클래스와 객체를 구별하는 법

 

-생물인 경우 “나이가 어떻게 되죠?”

-무생물인 경우 “제조일자가 어떻게 되죠?”

 

객체는 유일무이하게 존재하는 실체이기 때문에 속성에 값을 가지고 있다.

클래스는 개념이면서 분류 체계일 뿐이므로 속성에 값을 가질 수 없다.

 

하지만 아래 질문은 어떤가?

 

미키의 꼬리는 몇개인가?

쥐의 꼬리는 몇개인가?

 

모든 질문의 답은 한개다. 위 질문에서 미키마우스는 객체다. 당연히 꼬리 개수에 답이 있다.

그런데 쥐는 클래스인데 꼬리 개수에 답이 있다.

 

꼬리 개수는 객체의 속성이지만 모든 객체가 같은 값을 가지고 있기에 클래스를 통해 질문해도 하나라는 답을 알 수 있다.

위 그림을 보면 Mouse 객체가 모두 같은 값을 갖는 꼬리 개수 (countOfTail) 속성이 있음에도 Mouse 객체 수만큼 아까운 메모리를 잡아먹고 있다.

 

그래서 같은 유형(클래스)의 모든 객체가 같은 값을 가지고 있다면 그 값을 클래스에 저장하는 건 어떨까?

 

코드로는 아래와 같이 작성할 수 있다.

 

 

이제 countOfTail 속성은 T메모리의 스태틱 영역에 단 하나의 저장 공간을 갖게 된다.

countOfTail 속성에 접근하기 위해서는 객체를 이용해 객체_참조변수.countOfTail로 접근할 수 있으며, 

클래스를 이용해서 클래스명.coutOfTail 로도 접근할 수 있다.

 

 

6번째와 18번째 줄을 보면 Mouse.countOfTail 형식, 즉, 클래스명.속성명 형식으로 접근했다.

 

13,14,15번째 줄은 객체참조변수.속성명 형식으로 접근했다.

 

이렇게 static 키워드가 붙은 속성을 클래스 멤버 속성이라고 한다.(메서드도 마찬가지다)

 

 

추상화를 통해서 모델링을 하면 위와 같이 4가지 요소를 설계하게 되는 것이다.

 

클래스 멤버 = static 멤버 = 정적 멤버

객체 멤버 = 인스턴스 멤버

 

정적 멤버 속성은 해당 클래스의 모든 객체들이 같은 값을 가질 때 사용하는 것이 정석이다.

 

정적 메서드는 언제 사용하는 것이 좋을까?

 

정적 메서드는 객체들의 존재 여부와 상관 없이 쓸 수 있는 메서드다.

 

정적 멤버들은 객체가 아닌 클래스에 속해 있으며, 클래스는 JVM 구동시 T 메모리의 스태틱 영역에 배치되기 때문에 객체의 존재 여부에 관계 없이 쓸 수 있다.

 

일단 main () 메서드는 당연히 정적 메서드여야 한다.

 

메모리가 초기화 되는 순간 객체는 하나도 존재 하지 않기 때문이다. 그래서 객체 멤버 메서드를 바로 실행할 수는 없다.

 

따라서 main 메서드는 정적 메서드여야 한다.

정적 속성인 경우 메모리의 스태틱 영역에 클래스가 배치될 때 클래스 내부에 메모리 공간이 확보되는 것을 보여준다.

이에 반해 객체 속성은 속성명만 있지 실제 메모리 공간은 확보하지 않는다.

객체 속성은 힙 영역에 객체가 생성되면 바로 그때 각 객체안에 멤버 속성을 위한 메모리 공간이 할당된다.

 

스택 영역에 생기는 변수 = 지역변수

 

지역 변수는 개발자가 별도로 초기화 하지 않으면 쓰레기 값을 갖게 된다.

클래스 속성과 객체 속성은 별도의 초기화를 해주지 않아도 정수형은 0, 논리형은 false, 객체는 null로 초기화 된다.

 

지역 변수는 별도로 초기화해야 하는데 멤버 변수는 왜 자동으로 초기화 해줄까?

 

그것은 지역 변수는 한 지역에서만 쓰는 변수이지만 멤버 변수는 공유 변수의 성격을 가지고 있기 때문이다.

 

객체 변수는 하나의 객체 안에서 다수의 객체 메서드가 공유하는 변수이고, 클래스 변수는 전역 변수로서 프로그램 어디든 접근 가능한 공유변수다.

 

이러한 공유 변수의 초기화는 누가 해야 할까?

 

객체 멤버인 경우는 생성자를 통해서, 정적 멤버는 정적 실행 영역을 통해서 초기화 하는 경우가 있긴 한데, 공유 변수를 딱히 누가 초기화 해야 한다고 규정할 수 없다.

 

그래서 공유변수는 별도로 초기화를 해주지 않아도 기본값으로 초기화 되는 것이다.

 

지역 변수는 당연히 한 지역에서만 사용되고 소멸되는 변수이기에 그 지역에서 초기화 하는 것이 논리적으로 맞다.

 

 

참고 : 스프링 입문을 위한 자바 객체 지향의 원리와 이해