[Java] 클래스 변수 vs. 인스턴스 변수 vs. 로컬 변수
Table of Contents
변수의 종류#
변수에는 스태틱변수, 인스턴스변수, 지역변수 3가지가 존재한다. 메서드 내부에서 선언된 변수가 지역변수인데, 그 변수는 그 메서드의 중괄호{} 내에서만 유효하다.
class Variables{
int iv; //인스턴스 변수
static int cv; // 클래스변수(static 변수)
void method(){
int lv = 0; //지역변수
}
}
인스턴스 변수(instance variable)#
클래스 영역에 선언되고, 새로운 인스턴스가 만들어질 때 생성된다. 그래서 인스턴스 변수의 값을 읽어오기 위해서는 새로운 인스턴스를 만들어야 한다. 위의 예시에서 iv 에 접근하려면, 아래 방식처럼 접근해야 한다.
Variables myVariable = new Vairiable();
System.out.println(myVariable.iv);
인스턴스는 독립적인 저장공간을 가지므로, 서로 다른 값을 가질 수 있다. 인스턴스마다 다른 값을 가지는 변수를 인스턴스 변수로 선언한다.
클래스 변수(static variable)#
클래스변수는 새로운 인스턴스를 만들어도, 모든 인스턴스가 공통된 변수를 사용한다. 한 클래스로 만들어진 모든 인스턴스들이 공통적인 클래스 변수 값을 가진다. 클래스 변수는 인스턴스를 생성하지 않아도 접근가능하다. 클래스이름.클래스변수 식으로 접근가능하다.
System.out.println(Variables.cv);
클래스가 메모리에 로딩될 때 생성되어 프로그램이 종료될 때까지 유지되며, public 을 붙이면 같은 프로그램 내 어디에서나 접근가능하다.
지역 변수(local variable)#
메서드 내에서 선언되며, 그 메서드 안에서만 사용가능하다. 메서드가 종료되면 소멸되어서 사용이 불가능해진다.
예시#
public class Application{
public static void main(String[] args){
Calculator teacher = new Calculator();
System.out.println(teacher.add(1,2));
System.out.println(teacher.result); // 3
System.out.println(teacher.sharedResult); // 3
Calculator student = new Calculator();
System.out.println(student.add(3,4)) // 7
System.out.println(student.result); // 7
System.out.println(student.sharedResult); // 7
System.out.println(teacher.sharedResult); // 7
System.out.println(Calculator.MADE_DATE); // 1223
}
}
public class Calculator{
public static int sharedResult = 0; //클래스 변수
public int result; // 인스턴스 변수
public static int final MADE_DATE = 1223; // 상수
public int add(int input1, int input2){
result = input1 + input2;
sharedResult = result;
return result;
}
}
위의 코드를 보았을 때, Calculator 클래스 내에 result , sharedResult 변수 2개가 있다. 위의 Application 클래스를 실행시켰을 때, teacher.result 는 3이 나오고, 와 student.result 는 7이 나온다. 같은 result 변수여도, 이것은 인스턴스 변수여서 Calculation 클래스의 인스턴스들이 생길 때마다 새롭게 생겨난다.
그러나 아래 teacher.sharedResult 는 맨 마지막 줄에서 7이 나온다. 왜냐하면 sharedResult 변수는 모든 인스턴스에서 공유하는 변수이기 때문이다. 따라서 student.sharedResult 가 7로 변하면, 인스턴스에 상관없이 Calculator 의 sharedResult 값은 7이 된다. 그 후에 다른 인스턴스가 접근하거나, 혹은 그냥 Calculator.sharedResult 로 값이 변경될 수 있다. 그래서 클래스 변수는 인스턴스.클래스변수 로 접근하는 의미가 없다. 그냥 클래스이름.클래스변수 로 접근하면 된다.
그러면 만약에, 변수가 모든 인스턴스에서 공유할 수 있지만(=클래스 변수), 값은 변경할 수 없게 하려면 ? final 을 사용하면 된다. 이것은 여전히 클래스 변수이므로 클래스이름을 통해 접근가능하지만, 값은 수정할 수 없다. 이것을 상수 라고 한다.
변수의 초기화#
멤버변수를 초기화 하는 방법은 3가지가 있다.
- 명시적 초기화
선언과 동시에 초기화 하는 방법이다.
int width = 4;
이렇게 작성한다. - 생성자
- 초기화 블럭 복잡한 초기화를 할 때 사용한다.
멤버변수의 초기화 시기와 순서#
- 클래스 변수의 초기화 시점 : 클래스가 처음 로딩될 때 단 한번 초기화 된다.
- 인스턴스 변수의 초기화 시점 : 인스턴스가 생성될 때마다 각 인스턴스 별로 초기화가 이루어진다.
- 클래스 변수의 초기화 순서 : 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭
- 인스턴스 변수의 초기화 순서 : 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자
Reference#
- Java 의 정석, 3rd Edition
- 우테코 1주차 피드백