본문 바로가기

Language/Java

[Java] static 변수

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());  //인스턴스 생성 없이 호출 가능
	}
}

 

클래스 메서드는 인스턴스가 생성되지 않아도 언제든 호출할 수 있다. 인스턴스가 생성되어야 메모리가 할당되는 인스턴스 변수는 클래스 메서드에서 사용할 수 없다.

 

 

 

 📌 정리

  1. 클래스 메서드 내부에서 지역변수와 클래스 변수는 사용할 수 있지만 인스턴스 변수는 사용할 수 없다.
  2. 클래스 메서드에서 인스턴스 변수를 사용할 수는 없지만, 일반 메서드에서는 클래스 변수를 사용할 수 있다. (일반 메서드는 인스턴스가 생성될 때 호출하는 메서드이고, 클래스 변수는 이미 만들어진 변수이기 때문)

'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