지난 시간에 이어서 조금이라도 정리해보겠습니다.
03. 자바와 객체 지향
지난 정리에서 추상화를 통해 만든 클래스를 이용하여 객체를 만드는 부분까지 살펴보았습니다. 이렇게 객체를 만들면 T메모리에선 어떠한 변화가 일어날까요? 이 과정에서 지난 번에 쓰이지 않았던 Heap영역이 드디어 사용되게 됩니다. 한 번 살펴보겠습니다.
public class Dolphin {
public String name;
public int age;
public int bodySize;
public void swim() {
System.out.println("돌고리가 수영을 한다");
}
}
public class DolphinDriver {
public static void main(String[] args) {
Dolphin dolphin = new Dolphin();
dolphin.name = "슈";
dolphin.age = 3;
dolphin.bodySize = 200;
dolphin = null;
}
}
이러한 클래스와 main문이 있다고 생각을 하고 T메모리의 변화를 하나씩 살펴보겠습니다.
DolphinDriver
를 실행하기 전 Static영역에서 java.lang을 비롯한 모든 클래스들이 배치됩니다. 아직 객체가 생성이 안 되었기 때문에 Static영역에 이름만 존재할 뿐 변수 저장 공간은 없습니다.Dolphin dolphin
을 실행하였을 때 모습입니다.Dolphin
객체에 대한 참조 변수dolphin
을 만들었습니다.new Dolphin
을 실행하였을 때 모습입니다. 드디어 Heap영역에 무언가 생겼는데요. 생성된 객체가 Heap 영역에 배치되었습니다.Dolphin dolphin
와new Dolphin
사이의 대입문=
의 의미는Dolphin
객체에 대한 주소(포인터)를 참조 변수dolphin
에게 할당한다는 뜻이므로 화살표로 가리키게 합니다.- 4~6줄에 걸쳐 객체 참조 변수
dolphin
과 참조 연산자(.)를 이용하여 실제 Heap 상 객체에 접근하여 name, age, bodySize 속성에 값을 할당해줍니다. - 만약 객체 참조 변수에
null
을 할당하면 어떻게 될까요? 이 경우 더 이상 힙 영역에 존재하는dolphin
객체를 참조하지 않습니다. 이렇게 되면 힙 영역에 아무한테도 참조해 주지 않는 Dolphine 객체가 존재하는데요. 어느 시점에 가비지 컬렉터(Garbage Collector)는 이것을 쓰레기로 인식하고 수거합니다. - 가비지 컬렉터에 수거되면 결국 힙 영역에는 아무것도 남아있지 않습니다.
클래스 멤버 vs 객체 멤버 = static 멤버 vs 인스턴스 멤버
클래스 멤버와 객체 멤버의 구분은 static
예약어를 쓰느냐 안 쓰느냐로 구분을 할 수 있는데요. 그럼 어떨 때 클래스 멤버를 쓰고 객체 멤버를 쓸 수 있을까요? 우선 아래와 같은 상황을 생각해보겠습니다.
힙 영역에 3개의 객체가 들어있습니다. 3개의 객체의 속성을 들여다보면 bodySize
가 모두 중복된 값임을 볼 수 있습니다. 이와같이 모든 객체가 중복된 값을 가지고 있을 경우 그 값을 클래스 멤버로 저장할 수 있습니다. 우선 bodySize
를 static변수로 바꿉니다.(물론 bodySize
를 클래스 변수로 쓰는 것은 좋지 않습니다. bodySize
가 같은 건 우연일 가능성이 크기 때문이죠...)
public static int bodySize = 200;
그리고 T메모리는 다음과 같이 구성됩니다.
클래스 멤버 = static 멤버 = 정적 멤버 → 스태틱 영역
객체 멤버 = 인스턴스 멤버 → 힙 영역
지역 변수 → 스택 영역(스택 프레임 내부)
클래스 멤버는 static
키워드와 함께 사용되고 또 JVM이 종료될 때까지 Static영역에 상주하기 때문에 static(정적) 멤버라 하고, 객체 멤버는 클래스의 인스턴스1이므로 인스턴스 멤버라 합니다. 정적 속성은 기본적으로 모든 객체가 같은 값을 가질 때 사용합니다.
정적 메서드에 대해서도 잠깐 생각해보면 객체 생성되지 않아도 사용할 수 있는 메서드입니다. 왜냐하면 JVM 구동 시 객체가 생성되기도 전에 Static영역에 배치되고 메모리가 할당되기 때문이죠. 그렇기 때문에 main() 메서드는 바로 실행되어야 한다는 점에서 static 메서드인 것입니다. 보통 유틸리티성 메서드가 정적 메서드입니다.
또 알아야할 것은 객체 멤버와 정적 멤버는 생성 시 0, 0.0, false, null 등으로 초기화가 되는데 지역변수는 초기화 없이 쓰레기 값을 가지게 됩니다. 그 이유는 객체 멤버와 정적 멤버는 공유하는 변수의 성격을 가지고 있지만 지역 변수는 그 지역에서만 사용하기 때문2입니다. 따라서 지역 변수는 그 지역 안에서 초기화해주는 것이 맞고 공유 성격을 가진 변수들은 기본값으로 초기화해주어 배려를 해주는 것입니다.
'Book > programming' 카테고리의 다른 글
스프링 입문을 위한 자바 객체지향의 원리와 이해6 (2) | 2018.10.27 |
---|---|
스프링 입문을 위한 자바 객체지향의 원리와 이해5 (0) | 2018.10.21 |
스프링 입문을 위한 자바 객체지향의 원리와 이해4 (0) | 2018.10.18 |
스프링 입문을 위한 자바 객체지향의 원리와 이해2 (0) | 2018.10.14 |
스프링 입문을 위한 자바 객체지향의 원리와 이해1 (4) | 2018.10.14 |