본문 바로가기

Java

🤷🏻 상수는 왜 Static과 Final을 같이 사용할까?

서론

아는 사람에게 상수는 아래와 같이 사용한다고 알려줬다. 그러자 static과 final은 왜 같이 써야하냐고 물어봤는데 대충 말했긴 했지만, 제대로 알지 못하면 모른다고 생각하기 때문에 이번 기회에 블로그에 정리하려고 한다.

private static final String MESSAGE = "Hello World!";  

상수란?

일반적으로 상수는 불변의 값을 의미한다. 즉, 변하지 않는 값을 말한다. 예를 들어 수학에서 파이는 변하지 않는 값으로 이를 상수라고 한다. 자바에서 상수를 만들 때는 아래와 같이 사용하고 있다.

private static final String MESSAGE = "Hello World!";  

 

다시, static과 final은 왜 같이 사용하는지 알아보자.

final은 어떤 의미일까?

final 최종적이라는 뜻을 가진다. 자바에서 final도 마찬가지이다. 초깃값이 저장되면, 수정할 수 없는 값이 된다. 그렇다면 final이 변수, 메소드, 클래스에 붙으면 어떤 의미를 가지는지 알아보자.

  1. final 변수
    생성자나 대입 연산자(=)를 통해 한 번만 초기화 할 수 있다.
  2. final 메소드
    해당 메소드를 오버 라이드하거나 숨길 수 없다.
  3. final 클래스
    해당 클래스는 상속할 수 없다. (상속 계층 구조에서 마지막 클래스가 된다)

final만 있어도 상수 아닌가?

"final만 붙어도 변할 수 없는 값이니 상수가 아닐까?" 라는 생각을 할 수 있다. 그렇다면 상수(불변의 값)의 조건에 대해 알아보자.

  1. 객체마다 저장할 필요가 없어, 공통으로 사용할 수 있어야 한다.
  2. 여러 가지값으로 초기화될 수 없다.

"과연 위 조건에 만족할 수 있을까?"

public class User {  
    private final String name;

    public User(String name) {  
        this.name = name;  
    }  
}  

 

위 코드를 보면, final만 있어도 상수라고 불릴 수 있는지 없는지 알 수 있다. 위 코드는 객체마다 저장되고, 생성자를 통해 여러 가지값을 가질 수 있다. 따라서, final만으로는 상수라고 할 수 없다. 그렇다면 앞으로 남은 건 static. (1번 조건이 힌트가 될 수 있다.)

static은 어떤 의미일까?

static은 정적인 의미를 가진다. 그렇다면 주로 필드나 메소드에 static을 붙이곤 하는데 어떤 의미로 사용하는지 알아보자.

  1. static 필드
    해당 필드는 컴파일 타임에 메모리를 할당하여, 주로 공유하기 위해 사용한다.
  2. static 메소드
    해당 메소드는 객체를 생성하지 않아도 접근이 가능하여, 주로 유틸리티 성 메소드를 위해 사용한다. (예를 들어 연산, 오늘 날짜 구하기 등)

전에 "객체마다 저장할 필요가 없고, 공통으로 사용할 수 있어야 한다. (1번 조건)"는 조건이 힌트가 될 수 있다고 했다. 따라서 static을 붙이면 컴파일 타임에 메모리를 할당하여 공통으로 사용할 수 있기 때문에 static을 붙이면 조건을 만족한다.

결론

그림 [1]

그림 [1]에서 static 키워드를 사용하면 컴파일 타임에 리모컨을 생성하여, 하루가 지나도 같은 리모컨가족들이 공통으로 사용할 수 있다.

따라서 1번 조건인 "객체마다 저장할 필요가 없어, 공통으로 사용할 수 있어야 한다." 라는 조건을 만족하게 된다.

그림 [2]

그림 [2]에서 final 키워드를 사용하면 거실에 있는 TV 리모컨안방에 있는 TV 리모컨으로 조작할 수 없다.

따라서 2번 조건인 "여러 가지값으로 초기화될 수 없다." 라는 조건을 만족하게 된다.

그래서 결론은 static과 final을 같이 쓰면 아래 조건에 만족하기 때문에 같이 사용한다고 알고있자.

"객체마다 저장할 필요가 없어, 공통으로 사용할 수 있어야 한다."
"여러 가지값으로 초기화될 수 없다." 
private static final String MESSAGE = "Hello World!";