Last Modified : 2010.12.26

static 키워드

static 키워드는 클래스 차원의 변수와 메소드를 만들 때 사용한다.
정확한 명칭은 static 변수, static 메소드이다.
클래스가 로딩될 때 한번 결정된 메모리 공간이 변하지 않는다 하여 정적이라는 표현을 쓴다.
static 변수와 메소드는 객체를 생성하지 않고 클래스 이름으로 접근할 수 있으며 생성된 모든 객체에서 공유된다.

자바 프로그램이 실행되기 위해서는 클래스가 우선 메모리에 로딩되어야 한다.
클래스 로더(Class Loader)가 클래스를 찾아서 메모리에 로딩한다.
클래스가 로딩되는 메모리 공간과 객체가 활동하는 메모리 공간은 다르다.
클래스가 메모리에 로딩될 때 static변수와 static메소드를 위한 공간이 할당된다.
객체가 생성될 때마다 정적 변수와 정적 메소드를 위한 메모리 공간이 할당되지 않는다.
이와 달리 static이 아닌 인스턴스 변수는 객체가 생성될 때마나 메모리 공간이 할당된다.

static 변수, static 메소드 사용법

  • 클래스명.static변수
  • 클래스명.static메소드()

정적 메소드 안에서는 인스턴스 변수를 쓸 수 없다.
인스턴스 변수는 객체가 생성되고 각 객체 고유의 속성을 저장하기 위한 변수이다.
아직 만들어 지지도 않는 객체의 속성을 참조한다는 것이 말이 되지 않기 때문이다.
반대의 경우, 인스턴스 메소드 내에서 static 변수나 static 메소드를 참조하는 것은 가능하다.

정적 변수 사용예

package hyundai;

public class Car {

	static int total; // 생성된 차 객체 수를 저장
	String model;
	
	public Car(String model) {
		this.model = model;
		total++;
	}
	public static void main(String[] args) {
		Car car1 = new Car("아반떼");
		Car car2 = new Car("소나타2");
		Car car3 = new Car("소나타EF");
		Car car4 = new Car("그랜저");
		System.out.println("총차량수 : " + Car.total);
	}

}

결과는 4가 나온다.

Singleton pattern

객체가 단 하나만 만들어져야 할 때 사용하는 디자인 패턴인 싱글턴 패턴을 소개한다.
변수는 메모리 공간이 할당될 때 초기화 된다.
이때 초기값이 없다면 불린형은 false, 숫자형은 0 에 준하는 값으로, 레퍼런스 형은 null로 초기화된다.
static변수가 초기화되는 시점은 클래스가 로딩될 때이고 static이 아닌 멤버 변수가 초기화되는 시점은 객체가 생성될 때이다.

package net.java_school.db.dbpool;

public class DBConnectionPoolManager {

	private static DBConnectionPoolManager instance = new DBConnectionPoolManager();
	
	public static DBConnectionPoolManager getInstance() {
		return instance;
	}
	
	private DBConnectionPoolManager() {}
  
}

초기화 순서문제

지난 시간 설명을 잘못했음.(2010.12.23)
static 변수 -> 인스턴스 변수 -> 생성자 순만 기억하면 되겠다.
잘못 설명한 부분을 바로 잡으면,
static 변수와 static 블록은 같은 레벨이다. 즉 먼저 나온 것이 먼저 실행된다.
인스턴스 변수가 초기화가 먼저 되고 인스턴스 블록의 구현부는 컴파일러가 모든 생성자에 복사한다.
다음 문제의 결과를 실행하지말고 풀어보자.

package net.java_school.classvar;

public class Test {
	public Test() {
		System.out.println("테스트 생성자 실행");
	}
}
package net.java_school.classvar;

public class TestMain {
	private Test test = new Test();
	{
		System.out.println("인스턴스 블록 실행");
	}
	static {
		System.out.println("static 블록 실행");
	}
	private static TestMain staticVar = new TestMain();

	
	private TestMain() {
		System.out.println("테스트메인() 생성자 실행");
	}
	public TestMain(int a) {
		System.out.println("테스트메인(int) 생성자 실행");
	}

	public static void main(String[] args) {
		new TestMain();
		new TestMain(1);
	}
}