안녕하세요. 개발자 Jindory입니다.
오늘은 Static이 의미하는 바와 사용법 그리고 사용시 주의사항에 대해서 알아보고자 합니다.
# 글 작성 이유
Java 기초 공부를 다시하는 과정에서 static에 대한 개념이 명확하게 잡히지 않은것 같아 이번 기회에 정리해보고자 합니다.
static이란?
클래스 수준에서 작동하는 변수나 메소드를 의미합니다. static 키워드가 붙은 변수나 메소드는 특정 인스턴스에 속하지 않고 클래스 자체에 속하게 됩니다.
static이 선언되면 아래와 같은 특징을 가집니다.
- static 변수는 모든 인스턴스에 공유됩니다.
- 인스턴스를 생성하지 않고 Class를 통해 변수와 메소드를 호출할 수 있습니다.
- static 키워드가 붙은 변수나 메소드는 클래스 로드시 static 영역에 메모리에 할당되고, 클래스 언로드시 해제됩니다.
- static 키워드는 Garbage Collector에 의해 수집되지 않고 프로그램이 실행되고 종료될 때 까지 유지되기 때문에 static 키워드를 많이 사용할 경우 메모리를 많이 차지 할 수 있습니다.
- static은 전역에서 접근이 가능하므로 별도의 동기화 전략을 수립해야 합니다.
static 키워드가 붙은 변수, 메서드가 관리되는 영역
static 키워드를 붙혀서 생성한 Class, Method, Variable은 객체를 생성하지 않고도 사용할 수 있는데, 이는 static이 메모리가 적재되는 시기가 Instance의 Variable, Instance method와 다르기 때문입니다.
기본적으로 인스턴스(객체)는 Heap 영역에 생성되며, Method 영역에 로드된 클래스만 생성이 가능합니다. 또한 Method 영역에 정의된 Method를 호출시 새로운 Stack Frame이 생성되며, Method가 소멸되면 해당 Stack Frame도 같이 소멸되게 됩니다.
Stack Frame에는 메소드 안에서 사용되는 매개변수, 지역변수, 리턴값 및 연산시 일어나는 값들을 임시로 저장합니다.
정리하자면 인스턴스 생성시 인스턴스와 인스턴스 변수는 함께 Heap에 생성되고, Method 영역에 있는 Method 호출시 Stack Frame에 Method에 선언된 변수들이 관리 됩니다.
하지만 static 키워드가 붙은 변수와 method는 JVM에서 Class를 읽어들일때 static 영역에 자동으로 적재됩니다.
그렇기 때문에 객체 생성 없이 JVM이 Class를 읽어 들일 때 적재해둔 메모리를 참고하여 static 변수나 method를 이용하는 것입니다.
static 키워드 사용법
static 키워드는 주로 메모리 관리를 위해 사용되며, 변수, 메소드, 블록, 중첩 클래스에 적용할 수 있습니다.
static 키워드가 붙은 멤버는 클래스 수준에서 작동하므로, 특정 인스턴스에 속하지 않고 클래스 자체에 속하게 됩니다.
static 키워드를 사용하는 방법은 아래와 같습니다.
- 변수
static 키워드를 변수 앞에 선언하면, 그 변수는 클래스 변수가 됩니다. 클래스 변수는 모든 인스턴스에서 공유되며, 클래스 로드시 메모리에 한번만 할당됩니다. - 메소드
static 키워드를 메서드 앞에 선언하면 그 메서드는 클래스 메서드가 됩니다. 클래스 메소드는 인스턴스를 생성하지 않고도 호출할 수 있습니다. - 블록
static 키워드가 붙은 블록을 선언하면 그 블록은 static 초기화 블록이 됩니다. static 초기화 블록은 클래스가 로드될 때 한번만 실행됩니다. - 중첩 클래스
static 키워드가 붙은 중첩 클래스를 선언하면, 그 클래스는 static 중첩 클래스가 됩니다. static 중첩 클래스는 외부 클래스의 인스턴스 없이도 접근할 수 있습니다.
public class Main {
public static void main(String[] args) {
// Static 변수 사용
int value = Counter.count;
System.out.println("Counter.count: " + value); // 100
// Static 메서드 사용
String result = Counter.getCount();
System.out.println("result: " + result); // 100
// Static 블록 사용
Counter.init();
value = Counter.count;
System.out.println("Counter.count: " + value); //100
// Nested 클래스 사용
Outer outer = new Outer();
Inner inner = outer.new Inner();
inner.printMessage(); // Hello World!
}
}
class Counter {
private static int count = 0;
static {
init();
}
public static void init() {
count = 100;
}
public static String getCount() {
return Integer.toString(count++);
}
}
class Outer {
public class Inner {
public void printMessage() {
System.out.println("Hello World!");
}
}
}
static 키워드 사용시 주의사항
static 키워드를 잘못 사용하면 여러가지 문제가 발생할 수 있습니다. 이는 변수, 메소드, 블록, 클래스 관점에서 각각 다르게 나타날 수 있습니다.
- 변수
- 동시성 문제 : static 변수는 클래스 수준에서 작동하므로 모든 인스턴스에서 공유됩니다. 따라서 static 변수를 잘못 사용하면, 여러 스레드가 동시에 같은 변수에 접근하고 수정하려고 할 때 동시성 문제가 발생할 수 있습니다.
- 메모리 누수 : static 변수가 더 이상 필요하지 않을 때 적절히 해제되거나 처리되지 않으면, 시간이 지남에 따라 메모리 누수와 기타 성능 문제가 발생할 수 있습니다.
- 메소드
- 인스턴스 변수에 접근 제한 : static 메소드는 클래스 수준에서 작동하므로 인스턴스 변수에 직접 접근할 수 없습니다. 따라서 static 메소드를 잘못 사용하면, 인스턴스 변수에 접근하려는 시도가 실패하거나 예상치 못한 결과를 초래할 수 있습니다.
- 멀티스레딩 문제 : static 메서드는 모든 인스턴스에서 공유되므로, 여러 스레드에서 동시에 접근하려고 할 때 동시성 문제가 발생할 수 있습니다.
- 블록
- 명시적 호출 불가 : static 블록은 명시적으로 호출할 수 없습니다. 이는 static 블록이 클래스가 메모리 될 때 자동으로 한번만 실행되기 때문입니다.
- 예외 처리 : static 블록 내에서 예외가 발생하면, 해당 예외를 try-catch 블록을 묶어 처리해야하 합니다. static 블록에서는 예외를 던질 수 없습니다.
- this와 super 키워드 사용 불가 : static 블록 내에서는 this와 super 키워드를 사용할 수 없습니다. 이는 static 블록이 클래스 수준에소 작동하므로, 특정 인스턴스에 접근할 수 없기 때문입니다.
- 실행 순서 : 여러개의 static 블록이 있는 경우, 그들은 소스 코드에서 나타나는 순서대로 실행됩니다. 이는 static 블록의 실행 순서를 동적으로 제어할 수 없음을 의미합니다.
- 클래스
Java에서 static 클래스는 주로 중첩 클래스로 사용됩니다. static 클래스는 인스턴스를 생성할 수 없으므로, 이는 클래스 로더가 클래스를 메모리에 로드할 때 클래스 수준의 객체만 생성하기 때문입니다. 따라서 static 클래스를 잘못 사용하면, 클래스의 인스턴스를 생성하려는 시도가 실패하거나 예상치 못한 결과를 초래할 수 있습니다.
이렇게 static이 의미하는 바와 사용법 그리고 사용시 주의사항에 대해서 알아봤습니다.
혹시라도 정정할 내용이나 추가적으로 필요하신 정보가 있다면 댓글 남겨주시면 감사하겠습니다.
오늘도 Jindory 블로그에 방문해주셔서 감사합니다.
[ 참조 ]
https://programmingnote.tistory.com/22
'개발 > Java' 카테고리의 다른 글
[Java] Java에서 Thread Unsafe한 상황 이해하기 (0) | 2023.12.15 |
---|---|
[Java] Mutable Object와 Immutable Object (2) | 2023.12.15 |
[JAVA] JVM 메모리 구조 (0) | 2023.12.13 |
[Java] 컴퓨터가 실수를 표현하는 방법과 실수 연산시 주의사항(IEEE 754) (0) | 2023.12.12 |
[Java] LocalDate,LocalTime,LocalDateTime 활용하기 (0) | 2022.11.02 |