JAVA
Java - Static
상상날개
2022. 8. 14. 16:14
1. 필드(Field)
- ‘클래스에 포함된 변수'를 의미하는 것으로 객체의 속성을 정의한다
- 변수는 클래스 변수(cv, class variable), 인스턴스 변수(iv, instance variable), 지역 변수(lv, local variable) 세 가지로 구분될 수 있다
- 필드는 클래스 변수와 인스턴스 변수이며, static 키워드의 유무로 구분할 수 있다
- static 키워드가 함께 선언된 것은 클래스 변수이다
- static 키워드가 없는 것은 인스턴스 변수이다 - 두 가지 변수 유형에 포함되지 않고 메서드 내에 포함된 모든 변수를 지역변수라고 한다
- 세 가지 유형의 변수들은 주로 선언된 위치에 따라 그 종류가 결정되며 각각 다른 유효 범위(scope)를 가진다
class Area { //클래스 영역 시작
int instanceVariable; // 인스턴스 변수
static int classVariable; // 클래스 변수(static 변수, 공유변수)
void method() {
// 메서드 영역 시작
int localVariable = 0; // 지역 변수. 속해있는 {}블록 안에서만 유효
} //메서드 영역 끝
}//클래스 영역 끝
1) 인스턴스 변수(iv)
- 인스턴스가 가지는 각각의 고유한 속성을 저장하기 위한 변수이다
- new 생성자() 를 통해 인스턴스가 생성될 때 만들어진다
- 클래스를 통해 만들어진 인스턴스는 힙 메모리의 독립적인 공간에 저장된다
- 동일한 클래스로부터 생성되었지만 객체의 고유한 개별성을 가진다
- 사람마다 성별, 이름, 나이, MBTI가 다 다르듯 인스턴스 변수는 그 고유한 특성을 정의하기 위한 용도로 사용한다
2) 클래스 변수(cv)
- static 키워드를 통해 선언한다
- 클래스 변수는 독립적인 저장 공간을 가지는 인스턴스 변수와 다르게 공통된 저장공간을 공유한다
- 한 클래스로부터 생성되는 모든 인스턴스 들이 특정한 값을 공유해야하는 경우에 주로 static 키워드를 사용하여 클래스 변수를 선언한다
- 사람을 예로 들면 손가락과 발가락 개수와 같이 모든 사람이 공유하는 특성을 저장하는 데에 사용된다
- 클래스 변수는 인스턴스 변수와 달리 인스턴스를 따로 생성하지 않고 '클래스명.클래스변수명' 을 통해 사용이 가능하다
- area.classVariable 처럼 클래스 변수를 사용할 수 있다
3) 지역변수(lv)
- 지역변수는 메서드 내에 선언된다
- 메서드 내({} 블록)에서만 사용가능한 변수이다
- 멤버 변수와는 다르게 지역변수는 스택 메모리에 저장되어 메서드가 종료되는 것과 동시에 함께 소멸되어 더이상 사용할 수 없게 된다
- 힙 메모리에 저장되는 필드 변수는 객체가 없어지지 않는 한 절대로 삭제되지 않지만, 스택 메모리에 저장되는 지역변수는 한동안 사용되지 않는 경우 가상 머신에 의해 자동으로 삭제된다
4) 필드변수와 지역변수의 차이
- 필드 변수와 지역 변수의 주요한 한 가지 차이점은 초기값에 있다
- 지역변수는 직접 초기화하지 않으면 값을 출력할 때에 오류가 발생한다
- 필드 변수는 직접적으로 초기화를 실행하지 않더라도 강제로 초기화가 이뤄진다
- 메모리의 저장 위치와 긴밀한 연관성을 가진다
- 힙 메모리에는 빈 공간이 저장될 수 없기 때문에 저장되는 필드는 강제로 초기화된다
- 스택 메모리는 강제로 초기화되지 않으므로 지역 변수는 선언시 반드시 초기화를 실행해야 한다
2. static & instance 변수
1) static 변수
- 공유의 개념을 가지고 있다
- 클래스 변수를 생성하는데 사용한다
- 예제1)
public class StaticTest0 {
public static void main(String[] args) {
}
class Car {
public String str1 = "Instance Variable";
public static String str2 = "class Variable";
public static void method() {
System.out.println(str1);
System.out.println(str2);
}
public void method() {
System.out.println(str1);
System.out.println(str2);
}
}
}
<결과>
java: non-static variable str1 cannot be referenced from a static context
java: 정적 컨텍스트에서 비정적 변수 str1을 참조할 수 없습니다.
- 위의 코드에서 어느 부분에서 에러가 발생할까?
- public static void method() {
System.out.println(str1);
: 출력 명령에서 발생한다
: str1은 인스턴스 변수로써 클래스 메서드 내에서는 참조를 할 수 없다
: 클래스 메서드 내에서는 클래스 변수만이 참조가 가능하다
- 예제2)
public class StaticTest1 {
public static void main(String[] args) {
Car.method1();
Car.method2();
System.out.println(Car.str1);
System.out.println(Car.str2);
}
class Car {
public String str1 = "Instance variable";
public static String str2 = "class variable";
public static void method1() {
// System.out.println(str1);
System.out.println(str2);
}
public void method2() {
System.out.println(str1);
System.out.println(str2);
}
}
}
java: non-static method method2() cannot be referenced from a static context
java: 정적 메서드2는 정적 컨텍스트에서 참조할 수 없습니다.
- Car.method2();
System.out.println(Car.str1);
: 참조와 출력 명령에서 에러가 발생한다
: method2 메서드는 인스턴스 메서드이므로 공유가 되지 않는다
: str1 역시 인스턴스 변수로써 공유가 되지 않는다
- 인스턴스 메서드를 참조하고져 하면 인스턴스를 new 연산자로 생성하여야 한다
- 예제 3) 클래스 변수의 내용을 변경할 경우 전체가 변경된다
public class StaticTest1 {
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
car1.cv = "car1.str1 = Instance variable";
System.out.println(car1.cv);
System.out.println(car2.cv);
System.out.println(Car.cv);
}
static class Car {
public String iv = "Instance variable";
public static String cv = "class variable";
public static void method1() {
System.out.println(cv);
}
}
}
- 예제 4) 인스턴스 변수의 내용을 변경할 경우 변경한 iv만 적용된다
public class StaticTest1 {
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
car1.iv = "car1.str1 = Instance variable";
System.out.println(car1.iv);
System.out.println(car2.iv);
// System.out.println(Car.iv);
}
static class Car {
public String iv = "Instance variable";
public static String cv = "class variable";
public static void method1() {
// System.out.println(iv);
}
}
}