static 이란?
static 이란?
static은 정적으로 할당되는 변수, 함수, 클래스 등에 사용되는 키워드이다.
전역으로 공유되는 고정된 변수나 메서드를 정의할 때 사용되며, 프로그램의 생성과 동시에 static 영역에 할당되고 프로그램이 종료될 때 까지 유지된다.
사용 예시
static 키워드 사용 시 개발자가 별도의 객채 생성 과정을 거치지 않고 변수를 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Hello {
public static final int good = 1;
}
class Bye {
public int good = 1;
}
public class main {
public static void main(String[] args) {
System.out.println(Hello.good);
// new를 통한 별도의 생성과정 없이 접근 가능
// 1
Bye bye = new Bye();
System.out.println(bye.good);
// static 키워드가 없다면 new를 통해 관련 클래스를 생성해줘야 접근 가능
// 1
}
}
이러한 방식은 이미 메모리에 존재하는 변수와 메서드를 사용하므로 빠른 속도로 작동한다.
하지만 static 키워드가 붙은 메소드에서는 일반 멤버변수를 사용할 수 없다.
1
2
3
4
5
6
7
8
9
10
11
12
class hi {
int good = 1;
public static void hello(){
System.out.println(good); // 불가능
}
}
이는 둘의 생성 시점이 다르기 때문인데, static 키워드가 붙은 메소드는 인스턴스 생성 전부터 호출이 가능하지만 static이 붙지 않은 멤버 변수는 인스턴스가 생성 전에는 존재하지 않는다. static 메소드 입장에서는 알 수 없는, 혹은 존재하지 않는 변수를 사용하라는 코드이니 당연히 작동하지 않는다. 그래서 해당 코드는 컴파일 단계에서 막히게 된다.
고로 클래스간에 지속적으로 공유해서 사용하는, 변하지 않는 변수나 멤버변수와 같은 인스턴스 변수를 사용하지 않는 메서드 작성 시에 static 키워드를 사용하면 유용하다.
static의 장점을 살려서 나온 디자인 패턴이 싱글톤 패턴이며, 프로그램에서 오로지 하나의 객체만 생성되어야 하는 곳에 주로 사용된다.
1
2
3
4
5
6
7
8
9
public class Singleton {
private static class singleInstanceHolder {
private static final Singleton INSTACE = new Singleton();
}
public static Singleton getInstance(){
return singleInstanceHolder.INSTANCE;
}
}
데이터베이스 호출 코드, 스프링의 빈 컨테이너 기본 전략 등이 싱글톤을 활용한 사례이다.
모든 함수나 객체를 static으로 사용한다면?
static이 만능 해결사는 아니기에 다음과 같은 상황을 고려할 필요가 있다.
메모리 사용량
모든 변수, 메서드를 static으로 정의할 경우 불필요한 메모리 사용량이 증가할 수 있다.
new 를 통해 생성된 객체들은 GC를 통해 사용하지 않을 경우 해제될 수 있지만, static으로 정의된 자원들은 프로그램이 종료될 때 까지 유지되기 때문에 필요한 곳에만 사용해야 한다.
다중 스레드 환경
다중 스레드 환경에서의 안정성 또한 고려하여야 한다.
만약 final, const 등과 같이 불변 키워드 변수라면 크게 상관없을 수도 있지만, 값이 변할수 있는 가변적인 환경이라면 문제의 소지가 있다.
여러 스레드에서 각자 상태에 맞게 값을 변경한다면 기대하지 않았던 동작을 할 수 있고, 이는 에러의 소지가 다분한 코드가 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Value {
public static boolean available = true;
}
class Process {
public void work(){
while(!Value.available){
// wait...
}
Value.available = false;
// dosomething()...
Value.available = true;
}
}
위의 코드에서 work() 메소드가 단일 스레드로 한번씩 처리될 때는 큰 문제가 없을 수 있지만, 여러 스레드에서 동시에 해당 메소드에 진입해서 작업한다면 이후 동작은 예측하기 힘들어지게 된다.
참고
- Vaert Street, Static 키워드 바로 알고 사용하자, https://vaert.tistory.com/101
- 점프 투 자바, 07-03 스태틱, https://wikidocs.net/228
- Baeldung, A Guide to the Static Keyword in Java, https://www.baeldung.com/java-static
- JOINC, static 키워드, https://www.joinc.co.kr/w/man/12/static