(** 자바를 기반으로 설명하지만 C++도 크게 다르지 않습니다. 다만, C++은 전역변수를 사용할 수 있기 때문에 static 변수외에도 다른 방법으로 값을 공유 할 수 있습니다 **)
자바는 class를 만들고 class 내부에 속성과 메서드를 정의하는 것을 기반으로 프로그램이 이루어집니다. 여기에 선언된 변수는 추후 new 키워드를 통해서 힙 메모리에 공간을 차지하여 생성되는데 우리는 이를 인스턴스(instance)라 부릅니다. 각 인스턴스는 같은 클래스 기반으로 생성되지만 각각 차지하는 메모리의 공간이 다른 개별 객체로 여기에 속한 속성 값(멤버 변수 값) 또한 각각 다른 값을 가지게 되지요. 따라서 이런 멤버 변수를 다른 말로 인스턴스 변수라 합니다.
그런데 우리가 프로그래밍을 하다 보면 같은 클래스에서 생성된 여러 인스턴스가 공유해야 하는 값이 있을 수 있습니다. C++의 경우 (좋은 방법은 아니지만) global 변수를 하나 선언하고 이를 여러 인스턴스나 외부 파일에서 공유해서 사용할 수가 있지요. 하지만 자바는 오류의 가능성이 있는 부분을 모두 지양한 언어이고, class 외부에서는 어떤 변수나 메서드도 선언할 수 없습니다. 이렇게 여러 인스턴스가 공유해서 사용할 수 있는 변수가 static 변수입니다.
static변수는 인스턴스 변수처럼 객체가 new(인스턴스화) 될때 생성되는 변수가 아닌, 프로세스가 메모리에 로드되는 순간 정적변수 영역(데이터 영역)에 생성되는 변수이고, 이는 프로세스가 끝나서 언로드 될때까지 메모리에 상주하게 되는 변수입니다. 따라서 인스턴스의 생성과 상관 없이 사용할 수 있는 변수이며, 여러번 생성되는 변수가 아닌 한번만 생성되는 변수입니다.
가령 이런 경우를 생각해보죠. 학교에 학생들이 입학하면 한번을 부여하게 되는데, 학생 한 명이 새로 등록할 때마다 새로운 학번을 부여해주고 싶습니다. 그런 경우 기준이 되는 어떤 값이 있어야 하고, 그 값을 기준으로 어떤 연산을 수행하여 순차적인 학번을 부여하게 구현한다면 기준이 되는 그 값은 여러 인스턴스가 공유할 수 있어야 합니다.

다음과 같은 Student 클래스가 있다고 해보죠.
public class Student {
public static int serialNum = 1000;
int studentID;
String studentName;
int grade;
String address;
public Student(){
serialNum++;
studentID = serialNum;
}
…….
}
위 코드에서 serialNum 값은 생성자가 호출 될때마다 증가할 것이고 이 값는 학생의 studentID의 값으로 할당이 됩니다. 즉, 기준이 되는 serialNum 이라는 값을 static으로 선언하여 학생이 한명 새로 생성이 될 때마다 그 값을 증가시켜 새로운 studentID를 부여할 수 있습니다.
public class StudentTest {
Student studentLee = new Student();
studentLee.setStudentName(“이순신”);
Student studentSon = new Student();
studentSon.setStudentName(“손기정”);
}
위와 같이 Student 외부 클래스에서 두명의 학생을 생성을 하게 되었을 때 변수의 메모리 구조를 간단히 그려보면 다음과 같습니다.

위에서 static 변수는 인스턴스의 생성과 무관하게 사용한다고 했습니다. 따라서 클래스 외부에서 static 변수를 사용할 때는 참조변수(생성된 인스턴스가 대입된 변수)가 아닌 클래스의 이름으로 직접 참조해서 사용할 수 있고 이를 더 권장합니다. 그래서 static 변수를 다른 말로 클래스 변수라고 합니다.
Student.serialNum; // 클래스 이름으로 참조
static 변수가 있다고 하면 static 메서드도 존재하겠죠? 메서드의 반환 값 앞에 static키워드가 붙은 메서드가 static 메서드 입니다. 주로 static 변수에 대한 기능을 제공하는데 사용하지만, 인스턴스가 생성되지 않더라도 호출이 필요한 메서드는 static으로 선언합니다. 역시 인스턴스 생성과 무관하게 클래스 이름으로 호출하여 사용할수 있으므로 클래스 메서드라고도 합니다.
위에 선언했던 serialNum변수에 대한 getter/setter를 구현하면 다음과 같습니다.
public static int getSerialNum() {
int i = 10;
studentName = “aaa”; //오류 발생
return serialNum;
}
public static void setSerialNum(int serialNum) {
Student.serialNum = serialNum;
}
static 변수는 static 메서드에서만 사용할 수 있는 것은 아닙니다. 다른 인스턴스 메서드에서도 static 변수를 사용할 수 있습니다. 다만, static메서드에서는 인스턴스 변수를 사용할 수 없습니다. 위 코드중 getSerialNum() 메서드에서 지역변수 (int i), 인스턴스 변수(studentName) 그리고 클래스 변수 serialNum 세 가지 타입의 변수가 있습니다. 이중 인스턴스 변수인 studentName에서는 오류가 납니다. 왜그럴까요?
이는 변수의 생성 주기와 함께 생각해보면 알수 있습니다. 인스턴스 변수는 꼭 객체가 생성되어야 메모리가 할당되는 변수 입니다. 따라서 인스턴스의 생성과 상관없이 Student.getSerialNum()과 같이 호출되는 경우 생성된 인스턴스가 없는 경우 studentName 변수는 그 값이 없습니다. 따라서 여러 책에서 클래스 메서드(static 메서드) 에서는 인스턴스 변수를 사용할 수 없다는것은 이런이유입니다. (지역변수는 메서드 호출될때 스택에 자리잡는 변수이므로 당연히 사용할 수 있습니다.)
오늘은 간단히 자바에서 사용하는 static 변수와 메서드에 대해 살펴보았습니다~ 그럼 다음 시간에 또~~~^^