본문 바로가기

WEB/Java

static, final 키워드에 대하여 - ① static 키워드

static, final 키워드에 대한 정리
이론적인 의미와 선언, 사용법, 그리고 활용되는 케이스

static

  • '고정된'이라는 의미.
  • static 멤버: 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메서드를 의미
  • static 멤버는 클래스에 고정된 멤버이므로, 클래스 로더가 클래스(바이트 코드)를 로딩해서 Method Area에 적재할 때 클래스별로 관리된다. 따라서 클래스의 로딩이 끝나면 바로 사용할 수 있다.

1. static 멤버 선언 방법

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

2. 사용법

클래스.필드;
클래스.메소드(매개값, ...);
  • 원칙적으로 클래스 이름으로 접근해야 한다.
double result1 = 10 * 10 * Calculator.pi;
int result1 = Calculator.plus(10, 5);
int result2 = Calculator.minus(10, 5);
  • 객체 참조 변수로도 접근이 가능하긴 하다.
Calculator myCalc = new Calculator();
double result1 = 10 * 10 * myCalc.pi;
int result1 = myCalc.plus(10, 5);
int result2 = myCalc.minus(10, 5);

3. static 필드와 static 메소드

3.1 static 필드

❓ 필드를 선언할 때 인스턴스 필드로 선언할 것인가, static 필드로 선언할 것인가의 판단 기준

  • 객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언
  • 객체마다 가지고 있을 필요가 없는 데이터라면 정적 필드로 선언 
  • ex) Calculator 클래스에서, 계산기 색깔은 인스턴스 필드. pi(π) 값은 static 필드

3.2 static 메소드

❓메소드를 선언할 때 인스턴스 메소드로 선언할 것인가, static 메소드로 선언할 것인가의 판단 기준

  • 인스턴스 필드를 이용해서 실행해야 한다면 인스턴스 메소드로 선언
  • 인스턴스 필드를 이용하지 않는다면 static 메소드로 선언
  • ex) Calculator 클래스에서, 계산기 색깔 변경 메소드는 인스턴스 메소드, 외부 매개변수만 받아서 사용하는 덧셈뺄셈 메소드는 static 메소드

3.3 정적 초기화 블록

static 필드는 다음과 같이 필드 선언과 동시에 초기값을 주는 것이 보통이다.

static double pi = 3.14159;

인스턴스 필드는 생성자에서 초기화하지만, static 필드는 객체 없이도 사용해야 하므로 생성자에서 초기화 작업을 할 수 없다. 그런데 계산이 필요한 초기화 작업이 있을 수 있다. 이런 경우를 위해 자바는 정적 블록 (static block)을 제공한다.

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

 

❗️정적 블록, 정적 메소드 사용 시 주의할 점

  • 객체가 없어도 실행된다는 특징 때문에, 인스턴스 필드나 인스턴스 메소드를 사용할 수 없다.
  • 객체 자신의 참조인 this 키워드도 사용할 수 없다.
  • 사용하면 컴파일 에러가 발생한다.
  • 사용하고 싶다면 다음과 같이 정적 블록 내부에서 객체를 먼저 생성하고, 참조변수로 접근해야 한다.
public class ClassName {
    // 인스턴스 필드와 메소드
    int field1;
    void method1() { ... }
    // 정적 필드와 메소드
    static int field2;
    static void method2();
    
    static void Method3 {
    	this.field1 = 10;    // (X) 컴파일에러
        this.method1();      // (X) 컴파일에러
        
        ClassName obj = new ClassName();
        obj.field1 = 10;    // (O) 정상작동
        obj.method1();      // (O) 정상작동
}
  • public static void main(String[] args)

main() 메소드 또한 static 메소드이므로 객체 생성 없이 인스턴스 필드와 인스턴스 메소드를 바로 사용할 수 없다.

public Class Car {
    int speed;
    
    void run() { ... }
    
    public static void main(String[] args) {
        speed = 60;    // (X) 컴파일에러
        run();        // (X) 컴파일에러
        
        Car myCar = new Car();
        myCar.speed = 60;    // (O) 정상실행
        myCar.run();        // (O) 정상실행
    }
}

 

4. 활용

4.1 싱글톤(Singleton)

  • 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다. 스레드 풀, 캐시, 대화상자, 레지스트리 설정을 처리하는 객체 등...
  • 싱글톤 패턴 구현 방법

1) 생성자 앞에 private 접근 제한자를 붙인다. 외부에서 생성자를 호출할 수 없게하기 위함이다.

2) 자신의 타입인 static 필드를 하나 선언하고 자신의 객체를 생성해 초기화한다.

3) static 필드도 private 접근 제한자를 붙여 외부에서 필드값을 변경하지 못하게 막는다.

4) 대신 외부에서 호출할 수 있는 static 메소드인 getInstance() 를 선언하고 static 필드에서 참조하고 있는 자신의 객체를 리턴해준다.

 

public Class Singleton {
    // 정적 필드
    private static Singleton singleton = new Singleton();
    
    // 생성자
    private Singleton() {}
    
    // 정적 메소드
    static Singleton getInstance() {
    	return singleton;
    }
}
  • 싱글턴 객체를 얻는 방법
// obj1과 obj2는 동일한 객체를 참조한다
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();

 

출처

- 이것이 자바다

- Head First Design Patterns