[Java] 자바의 변수들 (일반 변수 vs 레퍼런스 변수, 클래스 변수 vs 인스턴스 변수)

주재완·2024년 1월 18일
0

Java

목록 보기
4/13
post-thumbnail

Introduction

어떤 언어를 배우든 간에 처음 배우면 Hello World! 출력하는 것부터 하고 다음 단계가 변수이다. 자바의 변수에 대해서, 또한 대분류에 대해서 살펴본다.

변수의 선언과 초기화

변수는 Java에서 아래와 같이 선언한다.

int num;

마치 C언어와 같은 모습을 띄고 있다. 여기에 값을 넣는것 까지 진행하면 어떨까? 이 역시도 C와 동일하다. 이롸 같이 변수에 값을 넣어 메모리를 할당 하는 것을 초기화라고 한다.

num = 5;

기본적으로 선언을 했으면 반드시 초기화를 해줘야 한다. 처음에 선언하면 메모리에 어떤 값이 들어갔는지 알 수 없기 때문이다. 그리고 선언과 초기화를 동시에도 진행 가능하다.

int num = 5;

일반적인 형태는 아래와 같다. 변수명 앞의 타입을 자료형(data type)이라 하고, 정해진 값리터럴(literal)이라 한다.

자료형 변수명 = 리터럴;

변수의 대분류

변수는 크게 일반 변수, 레퍼런스 변수로 분류가 가능하고, 지역 변수, 특별히 자바에서는 클래스 변수라는 개념도 존재한다.

일반 변수와 레퍼런스 변수

일반 변수(Primitive variables)

일반 변수는 앞에서 언급한 리터럴, 즉 값이 존재한다. 값을 가지고 있기 때문에, 컴파일 시점에 크기가 정해져 있다. 아래는 각종 일반 변수를 만드는 자료형 및 할당 받는 크기를 나타낸 표이다.
변수

따라서 변수를 출력하면 아래와 같이 바로 값이 나온다.

int num = 5;
System.out.println(num);
5

레퍼런스 변수(Reference variables)

레퍼런스 변수의 생성과 초기화는 아래와 같다.

Test test;
test = new Test();

일반 변수와 비슷한 면이 있는 것을 알 수 있는데, 가장 큰 차이점은 바로 new 연산자이다. 바로 변수를 초기화할 때 사용한다.

레퍼런스 변수(또는 참조 변수)는 따로 값을 가지고 있는 것이 아니라 주소를 가지고 있다. 즉 컴파일 시점에는 크기를 알 수 없고 실행할 때 new 명령어를 만나면 그제서야 메모리에 할당받게 된다. 할당 받는 과정을 살펴보자.

선언만 할 경우에는 아직 아무것도 없는 상태이다. 이 때 레퍼런스 변수는 초기값으로 null을 가지게 된다. 아무것도 지정이 안되었다는 뜻이다. 그리고 이 할당이 안되었을 때, 개발자들을 괴롭히는 NullPointerException이 발생하게 된다. 이제 초기화를 하면 어떻게 될까?

이 그림에서와 같이 Stack에서는 주소를 가지고 있고, 실제 데이터의 경우에는 Heap 메모리 상에 있는 것을 확인할 수 있다. Test의 인스턴스가 생성이 되고 Heap 메모리에 실제 데이터가, Stack에는 주소가 적혀있고, 실제 'test' 변수의 경우 값이 저장되는 것이 아닌 Heap 메모리에 있는 값을 참조할 뿐이다.

stack 과 heap에 대해서는 여기를 참고하면 된다.

만약, 여기서 test = new Test();가 또 있으면 어떻게 될까?

그림에서처럼 새로운 주소를 할당받게 된다. 그리고 기존에 있던 0x11 주소에 있는 객체는 더이상 연결할 수 없게 된다. 그리고 GC(Garbage Collector)가 이를 시간이 지나면 정리하게 된다.

그러면 왜 값을 직접 가지는게 아닌 값을 참조할 뿐일까? 바로 일반 변수와는 다르게 실행 시점까지 얼마나 메모리를 할당 받아야 하는지 알 수 없기 때문이다. 기존에 이미 크기가 정해진 일반 변수와는 달리 레퍼런스 변수는 크기가 정해져있지 않다. JVM은 관심법을 쓰는게 아니다. 실행이 되고 new를 만나야지만 그 메모리를 할당 받을 수 있다.

클래스 변수와 인스턴스 변수

클래스 변수

자바에는 클래스 변수라고 하는 것이 있다. 아래와 같이 선언하면 된다.

static int num;

바로 static이 붙으면 된다. 그러면 stack과 heap이 있는 쓰레드를 벗어나 JVM의 메소드 영역에 저장이 된다. 해당 영역에서는 컴파일을 하면서 필요한 클래스 정보들과 더불어 static이 붙은 모든 것들(클래스 변수, 클래스 메소드, ...)을 저장하게 된다.

즉, 이 변수는 객체와는 별개이다.

인스턴스 변수

클래스 변수와 반대 개념으로 각 객체마다 있는 변수가 인스턴스 변수이다.

참고

profile
언제나 탐구하고 공부하는 개발자, 주재완입니다.

0개의 댓글

관련 채용 정보