안녕하세요, 스코리아입니다.
오늘은 자바 static 변수의 의미와 선언/구현 방법에 대해서 알아보고 어떠한 주의사항이 있는지 알아보겠습니다.
static 변수란?
- 여러 인스턴스에서 공통으로 사용하는 변수를 선언할 때 static 변수를 사용합니다.
- 즉, 모든 인스턴스가 static 변수를 공유하는 형태로 작동합니다.
- [예] 그러면 공통으로 사용하는 변수가 필요한 경우는 언제일까요?
- 여러 인스턴스가 공유하는 기준값이 필요한 경우
- 학생마다 새로운 학번을 생성해야 하는 경우
- 회사에 신입사원이 입사할 때 새로운 사번이 필요한 경우
- 카드 회사에서 카드를 새로 발급할 때마다 새로운 카드 번호를 발급해야 하는 경우
static 변수 선언, 사용방법
public class Student {
static int serialNum; // static 변수 선언
}
- static 변수는 인스턴스가 생성될 때 만들어지는 변수가 아닌, 처음 프로그램이 메모리에 로딩될 때 메모리를 할당합니다.
- 클래스 변수, 정적변수라고도 합니다.
- 인스턴스 생성과 상관없이 사용 가능하므로 아래와 같이 클래스 이름으로 직접 참조가 가능합니다.
Student.serialNum = 100; // 클래스이름으로 직접 참조
static 변수 예제 - 구현하기
- Employee.java 파일을 만들고, serialNum 변수를 static 변수로 지정하여 인스턴스가 생성될 때마다 1씩 증가되도록 구현해 봅시다.
- 그리고 serialNum 변수를 1씩 증가한 후, 사원 번호인 employeeId에 저장하여 고유한 사원 번호로 만들어봅시다.
- 즉, 회사원이 입사할 때마다 새로운 사번이 부여되는 시스템입니다.
public class Employee {
private static int serialNum = 1000; // static 변수
private int employeeId; // 멤버 변수
private String employeeName;
public Employee()
{
employeeId = ++serialNum;
}
public static int getSerialNum() {
return serialNum;
}
public static void setSerialNum(int serialNum) {
// int i = 0; // 지역 변수
// this.employeeName = "Lee"; //오류발생 => 인스턴스 호출전이기 때문에
Employee.serialNum = serialNum;
}
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
}
- ++serialNum 은 serialNum을 우선 1을 더한 뒤, employeeId에 대입한다는 뜻입니다. (serialNum++ 은 serialNum을 employeeId에 먼저 대입 후 1을 더합니다)
- serialNum, employeeId, employeeName 변수 모두 private로 선언하여, 외부에서 참조되지 못하도록 막았고, 모두 getter, setter를 구현해 두었습니다. (왜 public이 아니라 private 로 선언했을까요? 정보은닉 참고하기: https://skorea6.tistory.com/10 )
- serialNum은 static 변수입니다. static 메소드인 setSerialNum()은 인스턴스 생성전에 호출될 수 있으므로, 메소드 내부에서는 인스턴스 변수를 사용할 수 없습니다. 즉, this.employeeName과 같은 멤버변수(인스턴스 변수)를 가져오는 행위는 불가합니다.
static 변수 예제 - 테스트하기
public class EmployeeTest {
public static void main(String[] args) {
Employee employeeLee = new Employee();
employeeLee.setEmployeeName("이순신");
System.out.println(Employee.getSerialNum());
Employee employeeKim = new Employee();
employeeKim.setEmployeeName("김유신");
System.out.println(Employee.getSerialNum());
System.out.println(employeeLee.getEmployeeName() + "," + employeeLee.getEmployeeId());
System.out.println(employeeKim.getEmployeeName() + "," + employeeKim.getEmployeeId());
System.out.println(Employee.getSerialNum());
Employee.setSerialNum(1003);
System.out.println(Employee.getSerialNum());
}
}
- static 변수와 메소드는 인스턴스 변수, 메소드와 다르게, 클래스이름으로 직접 참조가 가능합니다. 즉, 인스턴스 생성과 무관하게(인스턴스 생성을 하지 않아도) 클래스 이름으로 호출할 수 있습니다.
// [static 변수 특징] 클래스 이름으로 직접 참조하기
System.out.println(Employee.serialNum); // 참조로 호출
System.out.println(Employee.getSerialNum()); // getter 로 호출
- 위 코드와 같이, 참조로 호출할 경우, 현재 serialNum이 private으로 막아두었기 때문에, 오류가 뜰 것입니다.
- 그러므로, 클래스 이름으로 직접 참조하는 방법으로 getter 인 getSerialNum()으로 호출하여 사용할 수 있습니다.
변수의 유효 범위와 메모리
- 변수의 유효 범위(scope)와 생성, 소멸(life cycle)은 각 변수의 종류마다 다릅니다.
- 지역변수, 멤버변수, 클래스 변수는 유효범위와 생성과 소멸, 사용하는 메모리도 모두 다릅니다. 차이점을 알아보겠습니다
- 멤버 변수의 경우 멤버변수나 메소드가 private이 아니면, employeeLee 인스턴스를 활용하여 employeeLee.employeeName이나 employeeLee.getEmployeeName()과 같이 참조 변수로 다른 클래스에서 사용이 가능합니다.
- static 변수의 경우 멤버변수나 메소드가 private이 아니면, Employee 클래스 이름을 직접 사용하여 Employee.serialNum이나 Employee.getSerialNum()으로 다른 클래스에서 사용이 가능합니다.
static 사용 시 주의사항
- static 변수는 프로그램이 메모리에 있는 동안 계속 그 영역을 차지합니다. 그러므로 너무 큰 메모리를 할당하면 좋지 않습니다.
- 클래스 내부의 여러 메소드에서는 사용하는 변수는 static이 아닌 멤버 변수로 선언해야 합니다.
- 멤버 변수가 너무 많으면 인스턴스 생성 시 쓸데없는 메모리가 사용됩니다.
- 즉, 공통으로 사용하는 변수가 필요할 때만 static을 사용하는 등, 상황에 따라 적절하게 변수를 사용해야 합니다.
지금까지 자바(Java) static 변수의 의미와 사용방법, 주의사항과 변수의 유효범위에 대해서 폭넓게 알아보았습니다.
읽어주셔서, 감사합니다.
'JAVA > 객체지향' 카테고리의 다른 글
자바 객체 간의 상속(extend) 의미, 구현방법 (2) | 2023.08.25 |
---|---|
자바 싱글톤 패턴 의미, static 활용한 구현 (singleton pattern) (2) | 2023.08.18 |
자바 this / this() 뜻, 의미, 사용방법에 대해서 (1) | 2023.08.15 |
자바 접근 제어 지시자와 정보은닉을 활용한 캡슐화 (객체지향) (0) | 2023.08.14 |
자바 참조 자료형 변수 정의하기, 사용 방법 (feat. 객체) (2) | 2023.08.12 |