[Static 키워드의 개념]
Java에서 Static 키워드는 클래스의 멤버(필드, 메서드, 이너클래스)에 사용하며,
변수 앞에 사용되면 정적 변수, 메서드 앞에 사용되면 정적 메서드라고 한다.
즉, Static 키워드가 붙는 멤버는 정적 멤버라 부르고, Static 키워드가 없는 멤버는 인스턴스 멤버라 부른다.
정적 멤버는 프로그램 시작 시, 클래스 로더가 클래스를 로딩하면 메모리(Method Area/Static Area)에 할당한다. 이 클래스 로더를 이해하려면 JVM 메모리 구조를 살펴봐야 한다.
[해당 포스팅 참고]
https://dvdhan.tistory.com/163
JVM (Java Virtual Machine) ?
JVM (Java Virtual Machine) 1. 자바 프로그램이 어떠한 운영체제 상에서도 실행될 수 있도록 하는 도구. 2. Java 프로그램 런타임시 메모리를 관리하고 최적화 하는 것. [JVM 구성 요소] #Compiler (컴파일러)
dvdhan.tistory.com
[JVM 동작 과정]
1. 자바 코드파일 작성(.java)
2. 자바 코드 파일(.java)을 #컴파일러가 바이트 코드 파일(.class)로 변환
3. 변환된 바이트코드 파일(.class)을 #클래스 로더가 메모리 (Runtime Data Area)에 적재.
이 때 Runtime Data Area의 5가지 영역 중 static을 이해하는데 필요한 영역인
Method Area(Static Area)는 초기 로드에 필요한 정보들, 즉 패키지 클래스, 인터페이스, 상수,
static 변수, final 변수(상수), 클래스 멤버 변수 등이 로드된 후 항상 상주하고 있는 메모리 영역이다.
Stack Area는 클래스 안 메서드 실행 시 해당 영역이 할당되며
메서드에서 직접 사용할 지역 변수, 파라미터, 리턴 값, 참조 변수 등의 주소 값들이 저장되는 영역이다.
Heap Area는 메서드 안에서 사용되는 객체들을 위한 영역으로
new 를 통해 생성된 객체, 배열, immutal 객체 들이 저장되는 영역이다.
즉, 일반적으로 우리가 만든 Class는 Static Area에 생성되고,
new 연산자를 통해 생성한 객체는 Heap Area에 생성이 된다.
특히 Heap Area는 Garbage Collector를 통해 수시로 관리되어
호출되지 않은 객체는 삭제되어 메모리 관리가 되지만
Static Area에 저장된 객체들은 Garbage Collector의 관리 범위 밖이므로
프로그램의 종료까지 유지되어 시스템에 악영향을 미칠 수 있다.
[Static 키워드 특징]
클래스 로더가 .class 파일들을 탐색하는 과정에서 static 키워드를 보는 순간,
객체가 생성되지 않아도 항상 메모리를 할당해야할 대상으로 보고 Method Area(Static Area)에 할당한다.
그래서 static 키워드가 붙은 멤버들은 객체에 소속된 변수가 아니라 클래스에 소속된 변수이기에
클래스 변수 or 클래스 메서드라고 부른다. 또한 new 키워드를 통해 생성된 객체들은 서로 독립적인 반면, static 키워드가 붙은 멤버들은 모든 객체가 메모리 영역을 공유한다.
그래서 주로 Static은 전역적으로 쉽게 재사용되는 멤버나 잘 변하지 않는 변수, 메서드에 사용된다.
1. 정적 필드는 객체 간 공유 변수의 성질이 있다.
public class StaticFieldTest {
public static void main(String[] args) {
StaticField staticField1 = new StaticField(); // 객체 생성
StaticField staticField2 = new StaticField();
staticField1.num1 = 100;
staticField2.num1 = 1000;
System.out.println(staticField1.num1);
System.out.println(staticField2.num1);
staticField1.num2 = 150;
staticField2.num2 = 1500;
System.out.println(staticField1.num2);
System.out.println(staticField2.num2);
}
}
class StaticField {
int num1 = 10;
static int num2 = 15;
}
//출력값
100
1000
1500
1500
1. StaticField 클래스에 인스턴스 필드 num1, 정적 필드 num2 생성.
2. 대조를 위해 staticField1, staticField2 객체 생성
3. 인스턴스 필드 num1의 경우, 각각의 변수가 고유성을 가지기 때문에 각 객체마다 100, 1000이 출력.
4. static 필드 num2의 경우 정적 멤버의 특성인 공유 변수의 성질로 인해 값 공유가 일어나
맨 마지막에 입력된 staticField2 객체에서 선언한 값이 설정되어 staticField1, 2 둘 다 1500으로 출력된다.
2. 정적 메서드의 경우, 인스턴스 변수 또는 인스턴스 메서드를 사용할 수 없다.
정적 메서드의 경우, 인스턴스 생성 없이 호출이 가능하기 때문에
정적 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수 있다.
[Static 키워드 단점]
1. static 변수는 글로벌 변수에 가까우므로 인스턴스 변수보다 테스트가 까다롭다.
2. static 변수는 객체지향 프로그램의 원칙인 각 객체의 데이터들이 캡슐화되어야 한다는 원칙을 위배.
3. static 변수를 공유한 순간 서로에 영향을 주게 되어 어떤 사이드 이펙트가 발생할지 알기 어렵다.
4. 프로그램이 종료되기 전에 항상 메모리에 상주하고 있고 Static Area는 Garbage Collector의 관리 범위가 아니므로 높은 가능성으로 메모리 낭비가 발생하게 된다.
[정적 멤버 VS 인스턴스 멤버 사용 방법의 차이]
인스턴스 멤버, 반드시 소속된 클래스의 객체를 생성하고, 그 객체를 통해 인스턴스 멤버에 접근하는 반면
정적 멤버의 경우, 인스턴스 생성 없이도 해당 정적 멤버가 있는 클래스명.정적멤버만으로 사용 가능.
Ex)
public class StaticTest {
public static void main(String[] args) {
// static이 없으므로 staticExample 인스턴스 선언
StaticExample staticExample = new StaticExample();
// static 키워드가 없는 인스턴스 변수 num1.
System.out.println("인스턴스 변수: " + staticExample.num1);
// 인스턴스 생성 이후 호출.
System.out.println("클래스 변수: " + StaticExample.num2); //static 키워드가 있는 클래스 변수
}
}
class StaticExample {
int num1 = 10;
static int num2 = -10;
}
1. StaticExample 클래스에 인스턴스 변수 num1, 정적 멤버 num2 생성.
2. 인스턴스 변수 num1을 사용하기 위해서는 StaticExample 클래스를 객체화하고 인스턴스 변수를 사용.
3. 정적 멤버 num2를 사용하기 위해서는 StaticExample(클래스명)과 .정적 멤버 num2를 바로 호출.
[static 변수]
정적 변수에 대해서는 정적 메서드, 인스턴스 메서드 둘 다 변화를 줄 수 있는데
정적 메서드는 클래스 그 자체를 사용해서 static 메서드 or 변수를 통해 static 변수에 변화를 줄 수 있고,
인스턴스 메서드는 클래스의 객체인 인스턴스를 사용하여 메서드 or 변수를 통해 static 변수에 변화 가능.
'백엔드 기술 > Java' 카테고리의 다른 글
이너 클래스의 장점 (0) | 2023.04.17 |
---|---|
접근 제어자 (0) | 2023.04.17 |
메서드 오버라이딩 VS 오버로딩 (0) | 2023.04.15 |
OOP (객체지향 프로그래밍) 이란 ? (0) | 2023.04.15 |
추상 클래스와 인터페이스 차이 (0) | 2023.04.12 |