티스토리 뷰

차곡차곡/Java

[Java] Static 변수

p퐝유p 2022. 5. 8. 01:07

★ static 변수의 정의와 사용 방법

 

☆ static 변수

 

- 다른 용어로 '정적 변수'라고도 한다. 

  자바에서는 클래스 내부에 선언한다. 변수를 선언할 때  자료형 앞에 static 예약어를 사용한다. 

 

일반 멤버 변수는 인스턴스가 생성될 때마다 새로 생성되어 각각 다른 studentName을 가지게 됨

static 변수는 인스턴스 생성과 상관없이 먼저 생성, 그 값을 모든 인스턴스가 공유하게 됨

 

이 때문에, static 변수를 클래스에 기반한 변수라고 해서 '클래스 변수(class variable)' 라고도 함.

 


★ static 변수 사용해보기

 

- 학생이 새로 생성되면 학번을 차례로 부여하여 static 변수 사용해보자.

Student 클래스에서 기준 값 역할을 하는 serialNum 변수를 선언하고 기준 값으로 1000을 대입한다.

 

다음의 테스트 코드에서

학생 두 명 생성 후,

serialNum이 증가했을 때, 두 인스턴스에서 증가된 값이 공유되는가 확인해보자.

 

이강인 학생과 손흥민 학생이 왔다. 얼른 냉큼 학번을 드려야된다. 

 

1. studentLee를 먼저 생성한다.

2. 이 참조 변수를 사용하여, 전체 인스턴스에서 공통으로 사용하는 serialNum 변수 값을 1 증가시킨다.

3. studentSon을 생성한다. 생성된 studentSon으로는 아무 연산도 수행하지 않는다.

4. studentLee와 studentSon으로 변수값을 출력해보면 둘 다 1001로 증가된 serialNum 값이 출력된다.

 

즉, 두 개의 참조 변수가 동일한 변수의 메모리를 가리키고 있다는 것을 알 수 있다.

 


★ static 변수 이용하여  학번 자동으로 부여하기

 

static 변수를 그냥 바로 학번으로 사용하면 안 된다.

왜냐하면 static 변수는 모든 인스턴스가 공유하는 변수이므로

이 변수를 바로 학번으로 사용하면 모든 학생이 동일한 학번 값을 가지게 되기 때문이다.

 

학번은 학생의 고유 번호이므로 학생의 멤버 변수로 선언해주고,

학생 한 명 생성될 때매다 증가한 serialNum 값을 studentID에 대입해 주면 이 문제가 해결된다.

 

1. Student 클래스에 생성자를 추가

2. 생성자에서 serialNum값을 증가시킴

3. 증가된 값을 studentID 변수에 대입

 

자 이제, 손흥민과 이강인은 학번을 부여받는데 성공했다. 


★ 클래스 이름으로 static 변수 참조하기

- 위의 내용처럼 static 변수는 인스턴스를 생성할 때마다 만들어지는 것이 아니고,  클래스를 선언할 때 특정 메모리에 저장되어 모든 인스턴스가 공유하는 변수이다.   static 변수는 인스턴스 생성과는 별개이므로 인스턴스보다 먼저 생성된다.

  그러므로 인스턴스가 아닌 클래스 이름으로도 참조하여 사용할 수 있다.

  따라서, 자바에서는 static 변수를 클래스 변수라고도 한다.

 

위의 studentTest2.java 파일처럼 static 변수 serialNum을 studentLee.serialNum과 같이 인스턴스로 참조 가능하다.

하지만 static 변수는 인스턴스가 생성되지 않아도 사용할 수 있기 때문에

보통은 Student.serialNum과 같이 클래스 이름과 함께 사용된다. 

 

이때까지 static 변수, 정적 변수, 클래스 변수라는 세가지 용어를 사용했다.

셋 모두 자바에서 static 변수를 의미한다.

 

자바에서 static 변수를 클래스 변수라고 하는 이유는

인스턴스마다 생성되는 변수가 클래스에 속해 한번만 생성되는 변수이고 이를 여러 인스턴스가 공유하기 때문이다. 

 


★ 클래스 메서드

 

- 일반 멤버 변수를 위한 메서드가 존재하듯이 static 변수를 위한 메서드도 있다.

  이런 메서드를  'static메서드'  또는 '클래스 메서드'라고 한다.

 

여기에서는 serialNum변수를 사용하는 메서드를 만들어보자.

 

1. 외부 클래스에서 serialNum 변수를 직접 참조하지 못하도록 일단 Private으로 선언한다. 

 

2/3. 이 변수에 대한 get( ) 메서드와 set( ) 메서드를 생성한다. 

     

 

- Student 클래스의 serialNum 변수를 private으로 변경하면 

  기존의 StudentTest1,2,3에서 직접 참조할 수 없어 오류가 발생하므로 Studen2 클래스를 한번 더 생성한다. 

   

  외부 클래스에서 serialNum 값을 사용하려면 get( ) 메서드를 호출하고,

                        serialNum 값을 변경하려면 set( ) 메서드를 사용해야한다.

 

  확인해보겠다. 

 

serialNum을 직접 참조하지 않고, getSerialNum( ) 메서드를 호출하여 참조한다.

static 메서드 또한 static 변수처럼 인스턴스 참조 변수가 아닌 클래스 이름으로 직접 호출 가능하다. 

 


★ 클래스 메서드와 인스턴스 변수

클래스 메서드 내부에서는 인스턴스 변수를 사용할 수 없다. 

private 변수로 변경했다.

 

getSerialNum( ) 메서드는 static 예약어를 붙인 클래스 메서드이다.

이 메서드는 3가지 종류의 변수를 사용하고 있다.

 

변수 1. int i

- 메서드 내부에 선언

   ☆ 지역 변수 (local variable)

      - 메서드 내부에서 선언한 변수를 그 지역에서만 사용한다고 해서 지역 변수(local variable) 라고 한다.

        메서드가 호출될 때 메모리에 생성되어 메서드가 끝나면 사라지는 변수이다.

 

변수 2. studentName 

- 이 변수는  Student2 클래스의 멤버 변수로, 인스턴스가 생성될 때 만들어지는 인스턴스 변수이기 때문이다. 

 

변수 3.  serialNum ( )

- static 변수이다. 그래서 클래스 메서드인 getSerialNum( ) 메서드 내부에서도 사용할 수 있다. 

 


★ 인스턴스 생성 없이 클래스  메서드와 클래스 변수 사용하기

 

 

 

출력 화면

인스턴스가 생성되지 않아도 언제든 호출할 수 있다.

따라서 StudentName처럼 인스턴스가 생성되어야 메모리가 할당되는 인스턴스 변수는

클래스 메서드에서 사용할 수 없다.

 

 

Summary

 

1. 클래스 메서드 내부에서 지역변수와 클래스 변수는 사용 가능 / 인스턴스 변수는 사용 불가능

 

2. 클래스 메서드에서 인스턴스 변수 사용 불가 / 일반 메서드에서는 클래스 변수 사용 가능

    Why? 일반 메서드는 인스턴스가 생성될 때 호출되는 메서드이고,

             클래스는 이미 만들어진 변수이기 때문에 일반 메서드에서 클래스 변수 호출 가능  


이해가 정말 안되었던 static 변수에 대해 리뷰를 완료했다.

이해가 되는 듯 하지만 나중에 프로젝트를 할 때, 잘 써먹을 수 있을지 모르겠다.

최선을 다하자.  벗어나려고 발버둥이라도 치면 언젠간 목적지에 도착하지 않을까. 화이팅.

 

 

※ 이 게시물은 <Do it!> 자바 프로그래밍 입문 책을 참고했습니다.