지난번 JVM 포스팅에서 다음과 같은 개념을 다뤘다.
이때 Method Area에는 클래스, 인터페이스, 메소드, 필드, Static 변수가 보관되고
Heap Area에는 new 키워드로 생성된 객체와 배열이 보관된다고 했었다.
Method Area에 저장되는 Static 키워드는 지금까지 어디엔가 많이 붙혀서 써오긴 했는데 정확히 뭐하는 놈인지 모호했다. 이 기회에 정리해보자.
한 줄 요약
static 키워드를 사용한 변수는 클래스가 메모리에 올라갈 때 자동으로 생성이 된다.
즉, 인스턴스(객체) 생성 없이 바로 사용가능 하다. (그래서 편리하고 빠르다)
non-static 멤버 VS static 멤버
non-static 멤버
1. 공간적 특성: 멤버는 객체마다 별도로 존재한다.
1.1. 인스턴스 멤버 라고 부른다.
2. 시간적 특성: 객체 생성 시에 멤버가 생성된다.
2.1. 객체가 생길 때 멤버도 생성된다.
2.2. 객체 생성 후 멤버 사용이 가능하다.
2.3. 객체가 사라지면 멤버도 사라진다.
3. 공유의 특성: 공유되지 않는다.
3.1. 멤버는 객체 내에 각각의 공간을 유지한다.
static 멤버
1. 공간적 특성: 멤버는 클래스당 하나가 생성된다.
1.1. 멤버는 객체 내부가 아닌 별도의 공간에 생성된다.
1.2. 클래스 멤버 라고 부른다.
2. 시간적 특성: 클래스 로딩 시에 멤버가 생성된다.
2.1. 객체가 생기기 전에 이미 생성된다.
2.2. 객체가 생기기 전에도 사용이 가능하다. (즉, 객체를 생성하지 않고도 사용할 수 있다.)
2.3. 객체가 사라져도 멤버는 사라지지 않는다.
2.4. 멤버는 프로그램이 종료될 때 사라진다.
3. 공유의 특성: 동일한 클래스의 모든 객체들에 의해 공유된다.
Static 키워드를 사용하는 이유
1. 자주 변하지 않는 일정한 값이나 설정 정보같은 공용자원에 대한 접근시 매번 메모리에 로딩하는 것 보다 비용을 줄일 수 있고 효율을 높일 수 있기 때문.
2. 인스턴스 생성 없이 바로 사용가능하기 때문에 프로그램에서 공통으로 사용되는 데이터들을 관리할 때 사용된다.
예제로 알아보자
class Foo{
public static String s1 = "i am static";
public String s2 = "i am instance";
}
public class static_practice {
public static void main(String[] args) {
System.out.println(Foo.s1);
System.out.println(Foo.s2); //에러
Foo foo = new Foo();
System.out.println(foo.s1);
System.out.println(foo.s2);
}
}
Foo라는 클래스를 만들고 문자열 변수 두개를 초기화 시켰다. 한개는 static을 붙혔다.
여기서 주목할 것은 Foo.s1은 에러가 안떴고 Foo.s2는 에러가 발생했다는 것이다.
static 변수 s1은 new 키워드를 통해 객체를 생성하지 않아도 바로 사용할 수 있다. 반면 그냥 인스턴스 변수 s2는 객체를 생성한 후 접근이 가능하므로 에러가 발생한다.
class Foo{
public static String s1 = "i am static";
public String s2 = "i am instance";
}
public class static_practice {
public static void main(String[] args) {
//System.out.println(Foo.s1);
//System.out.println(Foo.s2);
Foo foo1 = new Foo();
System.out.println("foo1.s1: "+foo1.s1);
System.out.println("foo1.s2: "+foo1.s2);
Foo foo2 = new Foo();
System.out.println("foo2.s1: "+foo2.s1);
System.out.println("foo2.s2: "+foo2.s2);
System.out.println("====변경====");
foo2.s1 = "changed s1 (foo2)";
foo2.s2 = "changed s2 (foo2)";
System.out.println("foo1.s1: "+foo1.s1);
System.out.println("foo1.s2: "+foo1.s2);
System.out.println("foo2.s1: "+foo2.s1);
System.out.println("foo2.s2: "+foo2.s2);
}
}
이번에는 static의 공유 속성을 알아보는 예제다.
결과부터 보면 이러하다.
====변경==== 부분에서 foo2객체의 값들을 다 바꾸었더니 건들지도 않은 foo1 객체의 static 변수 값도 바뀌었다
foo2의 값들은 당연히 바뀌는것이고.
Foo클래스의 static 변수는 해당 클래스의 모든 객체에 공통으로 사용되기 때문이다.
참고:
'Java' 카테고리의 다른 글
[Java] Garbage Collection (4) | 2021.07.01 |
---|---|
[Java] Thread/MultiThread 4 - 동시성 문제 (0) | 2021.06.29 |
[Java] JVM 구조와 동작원리 (0) | 2021.06.27 |
[Java] Thread/MultiThread 3 - 쓰레드풀 (0) | 2021.06.19 |
[Java] Thread/MultiThread 2 - 쓰레드 구현 (0) | 2021.06.18 |