static 변수란 다른 용어로 ‘정적 변수’라 한다.
다른 멤버 변수처럼 클래스 내부에 선언하지만, 다른 멤버 변수처럼 인스턴스가 생성될 때마다 새로 생성되는 변수가 아니다.
프로그램이 실행되어 메모리에 올라갔을 때 딱 한번 메모리 공간이 할당되어 그 값은 모든 인스턴스가 공유한다.
그래서 static 변수를 클래스에 기반한 변수라 해서 ‘클래스 변수(class variable)’이라고도 한다.
static int serialNum;
[실습] static 변수 사용하기
package staticex;
public class Student {
public static int srialNum = 1000;
public int studentID;
public String studentName;
public int grade;
public String address;
public String getStudentName() {
return studentName;
}
public void setStudentName(String name) {
studentName = name;
}
}
[실습] static 변수 테스트하기
package staticex;
public class StudentTest1 {
public static void main(String[] args) {
Student studentLee = new Student();
studentLee.setStudentName("이지원");
System.out.println(studentLee.serialNum);
studentLee.serialNum++;
Student studentSon = new Student();
studentSon.setStudentName("손수경");
System.out.println(studentSon.serialNum);
System.out.println(studentLee.serialNum);
}
}
위의 예시는 static으로 선언한 serialNum 변수를 모든 인스턴스가 공유하기 때문에 위와 같은 결과 화면이 나온다.
즉, 두 개의 참조 변수가 동일한 변수의 메모리를 가리키고 있다는 것을 알 수 있다.
학번 자동으로 부여하는 프로그램 만들기
[실습] 학번 자동으로 부여하기
package staticex;
public class Student1 {
public static int serialNum = 1000;
public int studentID;
public String studentName;
public int grade;
public String address;
public Student1() {
serialNum++; //학생이 생성될 때마다
studentID = serialNum; //증가된 값을 학번 인스턴스 변수에 부여
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String name) {
studentName = name;
}
}
여기에서 주의할 점.
static 변수를 바로 학번으로 사용하면 안 된다는 것이다.
왜냐하면 static변수는 모든 인스턴스가 공유하는 변수이므로 이 변수를 바로 학번으로 사용하면 모든 학생이 동일한 학번을 가지게 된다.
[실습] 학번 확인하기
package staticex;
public class StudentTest2 {
public static void main(String[] args) {
Student1 studentLee = new Student1();
studentLee.setStudentName("이지원");
System.out.println(studentLee.serialNum);
System.out.println(studentLee.studentName + " 학번 : " + studentLee.studentID);
Student1 studentSon = new Student1();
studentSon.setStudentName("손수경");
System.out.println(studentSon.serialNum);
System.out.println(studentSon.studentName + " 학번 : " + studentSon.studentID);
}
}
클래스 변수
static 변수는 인스턴스 생성과는 별개이므로 인스턴스보다 먼저 생성된다. 그러므로 인스턴스가 아닌 클래스 이름으로도 다음과 같이 참조하여 사용할 수 있다.
[실습] 클래스 이름으로 static 변수 참조하기
package staticex;
public class StudentSTest3 {
public static void main(String[] args) {
Student1 studentLee = new Student1();
studentLee.setStudentName("이지원");
System.out.println(Student1.serialNum); //serialNum 변수를 직접 클래스 이름으로 참조
System.out.println(studentLee.studentName + " 학번 : " + studentLee.studentID);
Student1 studentSon = new Student1();
studentSon.setStudentName("손수경");
System.out.println(Student1.serialNum); //serialNum 변수를 직접 클래스 이름으로 참조
System.out.println(studentSon.studentName + " 학번 : " + studentSon.studentID);
}
}
static 변수, 정적 변수, 클래스 변수 이 세 가지 용어 모두 static변수를 의미한다.
자바에서 static 변수를 클래스 변수라고 하는 이유는 인스턴스마다 생성되는 변수가 아니라 클래스에 속해 한 번만 생성되는 변수이고, 이를 여러 인스턴스가 공유하기 때문이다.
클래스 메서드
static 변수를 위한 메서드도 있는데 이를 ‘static 메서드’ 또는 ‘클래스 메서드(class method)’라고 한다.
[실습] serialNum의 get(), set() 메서드 사용하기
package staticex;
public class Student2 {
private static int serialNum = 1000;
int studentID;
String studentName;
int grade;
String address;
public Student2() {
serialNum++;
studentID = serialNum;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String name) {
studentName = name;
}
public static int getSerialNum() { //serialNum의 get()메서드
int i = 10;
return serialNum;
}
public static void setSerialNum(int serialNum) { //serialNum의 set()메서드
Student2.serialNum = serialNum;
}
}
[실습] 학번 출력하기
package staticex;
public class StudentTest4 {
public static void main(String[] args) {
Student2 studentLee = new Student2();
studentLee.setStudentName("이지원");
System.out.println(Student2.getSerialNum());
System.out.println(studentLee.studentName + " 학번 : " + studentLee.studentID);
Student2 studentSon = new Student2();
studentSon.setStudentName("손수경");
System.out.println(Student2.getSerialNum());
System.out.println(studentSon.studentName + " 학번 : " + studentSon.studentID);
}
}
static 메서드 또한 static 변수처럼 인스턴스 참조 변수가 아닌 클래스 이름으로 직접 호출할 수 있다.
클래스 메서드와 인스턴스 변수
클래스 메서드 내부에서는 인스턴스 변수를 사용할 수 없다.
public class Student2 {
private static int serialNum = 1000;
int studentID;
String studentName;
int grade;
String address;
...
public static int getSerialNum() { //serialNum의 get()메서드(클래스 메서드)
int i = 10;
studentName = "이지원"; //오류 발생
return serialNum;
}
...
getSerialNum() 메서드는 static 예약어를 붙인 클래스 메서드이다. 이 메서드는 세 종류의 변수를 사용하고 있는데,
먼저 int i는 메서드 내부에 선언하여 지역변수(local variable)이라 한다. 지역변수는 메서드가 호출될 때 메모리에 생성되어 메서드가 끝나면 사라지는 변수여서 메서드 내부에서만 사용할 수 있다.
return serialNum;을 보면 serialNum 변수는 static 변수이다. 그러므로 클래스 메서드인 getSerialNum() 메서드 내부에서도 사용할 수 있다.
studentName 변수는 오류가 발생한다. 이 변수는 Student2 클래스의 멤버 변수로, 인스턴스가 생성될 때 만들어지는 인스턴스 변수이기 때문이다.
[실습] studentName 변수 살펴보기
package staticex;
public class StudentTest5 {
public static void main(String[] args) {
System.out.println(Student2.getSerialNum()); //인스턴스 생성 없이 호출 가능
}
}
클래스 메서드는 인스턴스가 생성되지 않아도 언제든 호출할 수 있다. 인스턴스가 생성되어야 메모리가 할당되는 인스턴스 변수는 클래스 메서드에서 사용할 수 없다.
📌 정리
- 클래스 메서드 내부에서 지역변수와 클래스 변수는 사용할 수 있지만 인스턴스 변수는 사용할 수 없다.
- 클래스 메서드에서 인스턴스 변수를 사용할 수는 없지만, 일반 메서드에서는 클래스 변수를 사용할 수 있다. (일반 메서드는 인스턴스가 생성될 때 호출하는 메서드이고, 클래스 변수는 이미 만들어진 변수이기 때문)
'Language > Java' 카테고리의 다른 글
[Java] static 응용 - 싱글톤 패턴 (0) | 2022.11.03 |
---|---|
[Java] 변수 유효 범위 (0) | 2022.10.20 |
[Java] 객체 간 협력 (0) | 2022.10.17 |
[Java] this 예약어 (0) | 2022.10.12 |
[Java] 정보 은닉 (0) | 2022.10.10 |