본문 바로가기

프로그래밍언어/Java

[Java 기본] final 변수와 상수

final 변수와 상수


변수에 final 키워드가 붙으면 값을 변경할 수 없다.

final은 클래스, 메서드를 포함한 여러 곳에 붙을 수 있다. 일단 final 변수부터 알아보자. 

 

예제


=> 값을 한번 할당하면 변경할 수 없다. 값 변경시 오류가 발생하는 것을 확인할 수 있다. 

 


public class FinalLocalMain {
    public static void main(String[] args) {
        //final 지역변수
        final int data1;
        data1 = 10; // 최소 한번만 할당 가능
       // data2 = 20;

        final int data2  = 10;
        // data2 = 20; 
    }
    
    static void method(final int parameter) {
        // 파라미터의 값을 바꿀 수 없다. 
        //parameter = 20; 
    }
}

=> final을 지역변수에 설정할 경우 최초 한번만 할당할 수 있다. 

지역변수 선언 시 바로 초기화 한 경우 이미 값이 할당되었으므로 재 할당할 수 없다. 

매개변수에 final이 붙으면 메서드 내부에서 값을 변경할 수 없다. 

 

final 필드 - 멤버변수


멤버 변수로 사용한 경우 생성자를 통해 초기화 할 수 있다. 

package final1;

public class ConstructInit {
    
    final int value1;
    
    public ConstructInit(int value1) {
        this.value1 = value1;
    }
}

 

멤버 변수를 final로 선언하고 초기화 한 경우 생성자를 통해서 값을 바꿀수 없다. 

package final1;

public class FieldInit {

    static final int CONST_VALUE = 10;
    final int value1 = 20;

}

 

FinalFieldMain.java

public class FinalFieldMain {

    public static void main(String[] args) {
        //final 필드 - 생성자 초기화
        System.out.println("생성자 초기화");
        ConstructInit constructInit1 = new ConstructInit(10);
        ConstructInit constructInit2 = new ConstructInit(20);
        System.out.println(constructInit1.value1);
        System.out.println(constructInit2.value1);

        // final 필드 - 필드 초기화
        System.out.println("필드 초기화");
        FieldInit fieldInit1 = new FieldInit();
        FieldInit fieldInit2 = new FieldInit();
        FieldInit fieldInit3 = new FieldInit();

        System.out.println(fieldInit1.value1);
        System.out.println(fieldInit2.value1);
        System.out.println(fieldInit3.value1);

        // 상수
        System.out.println("상수");
        System.out.println(FieldInit.CONST_VALUE);

    }
}

 

 

 

ConstructInit과 같이 생성자를 사용해서 final 필드를 초기화 하는 경우, 각 인스턴스마다 final 필드에 다른 값을 할당할 수 있다. 물론 이 이후에 값을 변경하는 것은 불가능하다. 

 

- 그림으로 확인해보자. 

finalInit으로 final 필드를 초기화 하는 경우 모든 value값은 10이된다. 

모든 인스턴스가 같은 값을 사용하기 때문에 결과적으로는 메모리를 낭비하게 된다. 또한 같은 값이 계속 사용되는 것은 중복이다. 이럴 때는 static을 사용하는 것이 좋다. 

 

FieldInit.MY_VALUE 는 static 영역에 존재한다. 그리고 final 을 사용했기 때문에 값이 변하지 않는다. 

static 영역은 단 하나만 존재하는 영역이다. MY_VALUE는 JVM상에서 하나만 존재하므로 중복과 메모리 비효율 문제를 모두 해결할 수 있다. 

 

이런 이유로 final + 필드 초기화를 하는 경우 static을 붙이는 것이 효과적이다. 

 

상수(Constant)


변하지 않고 일정한 값을 갖는 수를 말한다. 자바에서는 보통 단 하나만 존재하는 변하지 않는 고정된 값을 의미한다. 

이런 이유로 상수는 static final 키워드를 사용한다. 

 

자바 상수 특징


  • static final 키워드를 사용한다. 
  • 대문자를 사용하고 _(언더스코어)로 구분해서 쓰는 것이 관례이다. 
  • 필드를 직접 접근해서 사용한다. 

 

final 변수와 참조


final을 참조형 변수에 사용하면 참조값을 변경할 수 없다. 

package final1;

public class Data {
    public int value;
}

 

package final1;

public class FinalRefMain {
    public static void main(String[] args) {
        final Data data = new Data(); // 참조형을 final로 선언

        //참조 대상의 값은 변경 가능
        data.value = 10;
        System.out.println(data.value);
        data.value = 20;
        System.out.println(data.value);
    }
}

 

참조형 변수 data에 final이 붙었다. 변수 선언 시점에 참조값을 할당했으므로 더는 참조값을 변경할 수 없다. 

 data = new Data(); 로 참조값 변경 불가

그러나 참조 대상의 값은 변경 가능하다. 

 

참조형 변수 data에 final이 붙었다. 이 경우 참조형 변수에 들어있는 참조값을 다른 값으로 변경하지 못한다. 그러나 Data.value는 final이 아니므로 값을 변경할 수 있다. 

 

 

 

 

* 인프런 '김영한의 실전 자바 - 기본편'을 참고하여 작성하였습니다. 

'프로그래밍언어 > Java' 카테고리의 다른 글

[Java 기본] 상속과 메모리 구조  (0) 2024.07.15
[Java 기본] 상속  (0) 2024.07.15
[Java 기본] static 메서드  (0) 2024.07.12
[Java 기본] static 변수  (0) 2024.07.10
[Java 기본] 스택 영역과 힙 영역  (0) 2024.07.10