우리가 만든 class는 static영역에 생성되고 , new 연산을 통해 Heap영역에 생성되어 GC에 관리를 받는다.
static 영역에 할당 된 메모리는 모든 객체가 공유하는 메모리라는 장점을 지닌다.
static을 난무하게 되면 메모리가 할당 된 채로 존재하므로 자주 사용하게 되면 시스템의 성능의 악영향을 준다.
static 변수의 특징
객체를 생성하지 않아도 static 자원에 접근이 가능하다.
클래스 로더가 .class 파일을 탐색 중 static 키워드를 보는 순간 객체가 생성되지 않아도 항상 메모리를 할당해야하 하는 멤버로 보고 Method Area(Static Area)에 메모리를 할당한다.
그래서 static 키워드가 붙은 멤버들은 객체(인스턴스)에 소속된 변수가 아니라 클래스에 소속된 변수이기 때문에 클래스 변수 혹 클래스 메소드라고 부른다.
new를 통해 객체를 생성하면 각 인스턴스는 서로 독립적이지만 이러한 특징때문에 static 키워드가 붙은 멤버들은 모든 객체가 메모리 영역을 공유한다.
public class MyCalculator {
public static appName = "MyCalculator";
public static int add(int x, int y) {
return x + y;
}
public int min(int x, int y) {
return x - y;
}
}
MyCalculator.add(1, 2); // static 메소드 이므로 객체 생성 없이 사용 가능
MyCalculator.min(1, 2); // static 메소드가 아니므로 객체 생성후에 사용가능
MyCalculator cal = new MyCalculator();
cal.add(1, 2); // o 가능은 하지만 권장하지 않는 방법
cal.min(1, 2); // o
static 변수(정적 변수)
메모리에 고정적으로 할당되어, 프로그램이 종료될 때 해제되는 변수
static 변수는 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 변수로, 메모리에 한번 할당되므로 여러 객체가 해당 메모리를 공유하게 된다.
public class Person {
private String name = "person";
public void printName() {
System.out.println(this.name);
}
}
하지만 100명의 person객체를 생성하면, 100개의 동일한 person 이라는 name 이 중복해서 생성된다. 이 때 static을 사용해서 여러 객체가 하나의 메모리를 참조하도록 하면 100개의 중복 메모리를 제거하여 효율이 있어지게 된다.
private final static String name = "person";
게다가 불변하지 않는 특성도 있어 final을 추가해준다.
static 메소드
객체 생성 없이 호출이 가능하며, 객체에서는 호출이 불가능 하다.
static 키워드를 만나는 순간 메모리에 적재시켜야 하는데 static 이 붙지 않은 변수를 접근하려면 에러가 난다.
객체를 생성해야 인스턴스 변수가 적재되기 때문에 순서적으로 맞지 않는다.
일반적으로 유틸리티 관련 함수들은 여러 번 사용되므로 static메소드로 구현을 하는 것이 적합한데, static메소드를 사용하는 대표적인 Util class 로는 Math가 있다.
ex) Math.max(100,1000)
※ static 이슈
전체 프로그램과 동일한 라이프사이클.
메소드 호출 시간이 짧아 진다고 무분별한 static 은 지양한다.(= 데이터 접근이 빠르다는 이유로 사용을 지양한다.)
static 은 글로벌 변수에 가까우므로 인스턴스 변수보다 테스트가 까다롭다.
오버라이딩 또한 불가하여 코드의 재사용성이 떨어진다.
GC 관리 받는 영역이 아니라서 메모리 낭비가 발생한다.
Thread safe 하지 못한다.
한 스레드에서 값을 변경하는 경우 다른 모든 스레드에 영향을 받는 동시성 문제가 발생할 수 있다.
Thread Safe하기 위해 추가적인 작업이 필요하다.
Serialization이 불가하다.
객체 직렬화는 인스턴스에 대해 적용되기 때문에 클래스 자체 정보인 static 멤버는 포함되지 않는다.
댓글