본문 바로가기

Java

[Java] 정적 멤버와 static

개발하거나 알고리즘 문제 풀면서 객체를 생성하지 않고 변수나 메소드를 바로 사용하고 싶을때 static 키워드를 붙여서 사용하곤 했는데 정확한 이해없이 사용하고 있는 것 같아서 책보면서 정리해보려고 합니다.

 

static은 정적인, 고정된 이라는 뜻을 가지고 있다. 그렇기 때문에 static 변수나 메소드를 정적 변수, 정적 메소드라고도 부른다. 또한 정적 변수와 정적 메소드를 포함하는 정적 멤버의 경우 객체에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 클래스 멤버라고 부른다.

정적 멤버 선언

정적 멤버 선언은 아래와 같이 static 키워드를 붙여서 선언할 수 있다.

public class 클래스명 {
    // 정적 변수
    public static 타입 변수명 [= 초기값];
    
    // 정적 메소드
    public static 리턴타입 메소드명( 매개변수 ) { ... }
}

정적 변수와 정적 메모리는 클래스에 고정된 멤버이므로 JVM의 클래스로더를 통해 메소드 영역에 적재될때 클래스별로 관리되어 객체를 생성하지 않고 클래스 로딩이 끝나면 바로 사용할 수 있다.

static 키워드 사용 상황

정적 변수를 선언해야 하는 상황은 객체마다 가지고 있어야 할 고유한 데이터의 경우 인스턴스 변수로 선언하고 공용적인 데이터라면 정적 변수로 선언하는 것이 좋다. 예를 들어 아래 Calculator 클래스를 보면 3.14159로 값이 고정되어있는 파이의 경우 공용적인 데이터이기 때문에 정적 변수로 선언해주었고 color의 경우 클래스마다 값이 다를 수 있기 때문에 인스턴스 변수로 선언해 주었다.

public class Calculator {
    public String color;
    public static double pi = 3.14159;
}

 

정적 메소드의 경우에는 만약 인스턴스 변수를 사용한다면 인스턴스 메소드로 선언하고 그렇지 않은 경우에는 정적 메소드로 선언하는 것이 좋다. 예를 들어 Calculator의 인스턴스 변수인 color 값을 초기화 하기 위해 setColor() 메소드를 선언해야 한다면 아래와 같이 인스턴스 메소드로 선언하고 plus 메소드의 경우에는 인스턴수 변수가 아닌 외부 매개변수 값을 사용하기 때문에 정적 메소드로 선언해 주었다.

public class Calculator {
    public String color;
    public static double pi = 3.14159;
    
    public void setColor(String color) {
    	this.color = color;
    }
    
    static int plus(int x, int y) {
        return x + y;
    }
}

정적 초기화 블록

정적 변수의 경우 아래와 같이 변수 선언과 동시에 초기값을 주는 것이 보통이지만 계산이 필요한 초기화 작업이 있을 수 있다.

public static double pi = 3.14159;

인스턴스 변수의 경우에는 생성자에서 초기화 작업을 수행할 수 있지만 정적 변수의 경우에는 객체 생성없이 정적 변수를 사용해야 하기 때문에 객체 생성시에 실행되는 생성자에서 초기화 작업을 수행할 수 없다. 대신 자바는 정적 필드의 초기화 작업을 수행할 수 있는 정적 블록이라는 기능을 제공해 준다.

 

정적 블록은 아래와 같은 형태로 사용되며 클래스가 메모리로 로딩될 떄 자동적으로 실행된다.

static { ... }

 

정적 블록은 여러 개가 선언될 수 있으며 선언된 순서대로 실행된다.

정적 블록 사용 예시

public class Television {
    public static String company = "SAMSUNG";
    public static String model = "LCD";
    public static String info;
    
    static {
    	info = company + "-" + model;
    }
}

static 키워드 사용시 주의할 점

정적 메소와 정적 블록을 선언할 때 인스턴스 필드나 인스턴스 메소드를 사용할 수 없다. 또한 객체 자신을 참조하는 this 키워드도 사용할 수 없다. 만약 사용하려고 하면 컴파일 에러가 발생한다. 또한 static 키워드가 선언된 정적 멤버가 JVM에 로드될때 static 영역에 할당되는데 이 static 영역은 Garbage Collector 관리 영역 밖에 있어 GC에 의해 메모리가 관리되지 않는다. 그렇기 때문에 너무 남발하게 되면 성능에 악영향을 줄 수 있다.