[Java/자바] 클래스 변수, 인스턴스 변수, 지역 변수란?

이 글을 읽기 앞서 자바의 클래스와 객체란? 인스턴스란 ? 무엇인지 모른다면 아래 포스팅을 참고하시면 좋습니다.

 

(Java/자바) 클래스와 객체

클래스와 객체 클래스와 객체를 설명하는 예시로 여러 예시가 있습니다. 게임 비유 : 클래스(직업)에 따라 클래스(직업)에 맞는 아이템과 동작들이 주어져서 객채가 생성되는 것. 붕어빵 비유 :

hstory0208.tistory.com

 

자바에서 변수는 클래스 변수, 인스턴스 변수, 지역 변수로 모두 3가지의 변수가 있습니다.

그리고 클래스 변수와, 인스턴스 변수를 "멤버변수"라고 합니다.

class test {
	int a; 		// 인스턴스 변수
        static int b;	// 클래스 변수 (static 변수, 공유 변수)

        // 메서드 영영
        void method() {  
        int a = 0; // 지역변수
    }
 }

 

변수의 종류 선언 위치 생성시기
클래스 변수 클래스 영역 클래스가 메모리에 올라 갔을 때
인스턴스 변수 인스턴스가 생성되었을 때
지역 변수 클래스 영역 이외의 영역
( 메서드, 생성자, 초기화 블럭 내부)
변수 선언문이 수행되었을 때

 

인스턴스 변수

클래스 영역에 선언되며, 클래스의 인스턴스를 생성할 때 만들어 집니다.

그렇기 때문에 인스턴스 변수의 값을 읽어 오거나 저장하기 위해서는 먼저 인스턴스를 생성해야합니다.

인스턴스는 독립적인 저장공간(변수)을 가져 서로 다른 값을 가질 수 있습니다.

인스턴스마다 각기 다른 상태를 유지해야하는 경우, 인스턴스 변수로 선언합니다.

  • 클래스 내에 선언된 변수
  • 객체 생성 시마다 매번 새로운 변수가 생성된다.
  • 클래스 변수와 달리 공유되지 않는다.

 

클래스 변수

클래스 변수는 인스턴스 변수 앞에 static을 붙이기만 하면 됩니다.

클래스 변수는 모든 인스턴스가 공통된 저장공간(변수)을 공유하기 때문에,

한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우, 클래스 변수로 선언해야합니다.

클래스 변수는 인스턴스와 달리 인스턴스를 생성하지 않고도 바로 사용할 수 있다는 특징을 가지며,

"클래스이름.클래스변수"와 같은 형식으로 사용합니다.

위 코드를 예를 들어 test 클래스의 클래스 변수 b를 사용하려면 test.b와 같이 사용할 수 있습니다.

public을 앞에 붙이면 같은 프로그램 내에서 어디서나 접근할 수 있는 전역변수의 성격을 갖습니다.

 

  • 클래스 내에 Static 키워드로 선언된 변수
  • 처음 JVM이 실행되어 클래스가 메모리에 올라갈 때부터 프로그램이 종료될 때까지 유지
  • 클래스가 여러 번 생성되어도 Static 변수는 처음 딱 한 번만 생성된다.
  • 동일한 클래스의 모든 객체들에 의해서 공유된다.

 

지역변수

메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸됩니다.

for문 또는 while문의 블럭 내에 선언된 지역변수는, 지역변수가 선언된 블럭 {} 내에서만 사용 가능하며,

블럭{}을 벗어나면 소멸되어 사용할 수 없게 됩니다.


변수의 초기화 ( 멤버변수, 지역변수 )

변수를 선언하고 처음으로 값을 저장하는 것을 변수의 초기화라고 합니다. ( Ex: int x = 1 )

멤버변 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이뤄지므로 초기화를 하지 않아도 됩니다.

하지만, 지역변수 사용하기 전에 반드시 초기화를 해야 합니다.

 

아래 예시 코드를 봅시다.

class InitTest {
    int x; // 인스턴스 변수
    int y = x; // 인스턴스 변수

    void method1() {
        int i;	// 지역변수
        int j = i; // 에러 : 지역변수를 초기화하지 않고 사용했기 때문.
    }
}

위 코드에서 x와 y는 인스턴스 변수이고, i와 j는 지역변수 입니다.

인스턴스 변수는 선언만하고 초기화하지 않았음에도 에러가 나지 않았는데, 그 이유는

인스턴스 변수는 초기화하지 않아도 자동적으로 int형의 기본값인 0으로 초기화되었기 때문에 x에는 0이 저장되어있으며 y = x 도 마찬가지로 y = 0이 됩니다.

 

하지만, method1() {}안에 선언된 지역변수 i자동적으로 초기화되지 않으므로, 초기화 되지 않은 상태에서 변수 j를 초기화하는데에 사용할 수 없어 위처럼 에러가 발생합니다.

에러를 발생하지 않기 위해서는 i를 초기화 해야합니다. ( Ex : int i = 10 )

 

 

  • 변수의  초기화 예시들
선언 예시 설 명
int i = 10;
int j = 10;
int형 변수 i를 선언하고 10으로 초기화 한다.
int형 변수 j를 선언하고 10으로 초기화 한다.
int i = 10, j = 10; 같은 타임의 변수는 콤마(,)를 사용해 함께 선언하거나 초기화 할 수 있다.
int i =10, long j = 10; 에러 : 타입이 다른 변수는 함께 선언하거나 초기화 할 수 없다.
int i = 10;
int j = i;
변수 i에 저장된 값으로 변수 j를 초기화 한다.
변수 j는 i의 값인 10으로 초기화 한다.
int j = i;
int i = 10;
에러 : 변수 i가 선언되기 전에 i를 사용할 수 없다.

 


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

 

클래스 변수와 인스턴스 변수의 차이를 이해하기 위해 아주 좋은 예시로 "포커 카드"가 있습니다.

포커 카드는 아래 처럼 카드의 높이와 폭은 전부 동일하고, 카드마다 문자, 숫자가 다릅니다.

이 "포커 카드"를 클래스 변수와 인스턴스 변수로 나누면 다음과 같습니다.

class card {
	String kind; // 무늬
        int number; // 숫자

        static int width = 100; // 폭
        static int height = 250; // 높이
        }

카드마다 무늬와 숫자는 각각 다르기 때문에 인스턴스 변수로 선언하였고, 폭과 높이는 전부 동일한 값을 가지기에 static을 붙여 클래스 변수로 선언하였습니다.

 


Example Code

class Card {
	String kind ;				// 카드의 무늬 - 인스턴스 변수
	int number;				    // 카드의 숫자 - 인스턴스 변수
	static int width = 100;		// 카드의 폭  - 클래스 변수
	static int height = 250;	// 카드의 높이 - 클래스 변수
}

class CardTest{
	public static void main(String args[]) {
		System.out.println("Card.width = "  + Card.width);
		System.out.println("Card.height = " + Card.height);

		Card c1 = new Card();
		c1.kind = "Heart";
		c1.number = 7;

		Card c2 = new Card();
		c2.kind = "Spade";
		c2.number = 4;

		System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
		System.out.println("c2는 " + c2.kind + ", " + c2.number + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );		

		System.out.println("c1의 width와 height를 각각 50, 80으로 변경합니다.");
		c1.width = 50;
		c1.height = 80;

		System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
		System.out.println("c2는 " + c2.kind + ", " + c2.number + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );
	}
 }

출력 결과

위 예시 코드를 보면 인스턴스 변수인 kind와 number는 Card 클래스를 가지고 Card c1 = new Card(), Card c2 = new Card() 로 인스턴스를 생성하였습니다.

하지만 클래스 변수인 width와 heigth는 인스턴스를 생성하지 않고 '클래스이름.클래스변수'와 같은 방식으로 사용할 수 있습니다.

Card 인스턴스인 c1과 c2는 클래스변수인 width와 heigth를 공유하기 때문에,

c1의 width와 heigth를 변경하면 c2의 width와 heigth의 값도 위처럼 바뀐 결과를 얻습니다.

 

즉, Card.width, c1.width, c2.width, Card.heigth, c1.heigth, c2.heigth는 모두 같은 저장공간을 참조하므로 항상같은 값을 갖게 됩니다.

 


참고자료
자바의 정석3