final

변수·메서드·클래스에 붙어 "변경 불가"를 선언하는 키워드입니다.

final 변수

한 번 할당 후 재할당 불가.

// 상수 (관례: 대문자 + 언더스코어)
static final int MAX_SIZE = 100;

// final 지역 변수
final int x = 10;
x = 20;   // X 컴파일 에러

// final 참조 변수 — 참조 자체를 바꿀 수 없을 뿐, 내부 상태는 변경 가능
final List<String> list = new ArrayList<>();
list.add("hello");   // O 내부 상태 변경 가능
list = new ArrayList<>();  // X 참조 재할당 불가

final 메서드

자식 클래스가 오버라이딩 불가.

class Parent {
    final void template() {
        step1();
        step2();    // 핵심 흐름 변경 방지
    }

    void step1() {}
    void step2() {}
}

class Child extends Parent {
    // void template() {}  // X 컴파일 에러
    void step1() {}        // O 오버라이딩 가능 (final 아님)
}

final 클래스

상속 불가. String, Integer, Math 등이 final 클래스.

final class ImmutablePoint {
    private final int x;
    private final int y;

    ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

// class Sub extends ImmutablePoint {}  // X 컴파일 에러

String이 final인 이유: 불변성 보장 → String Pool 공유 가능, 해시코드 캐싱 가능, 보안.

effectively final (Java 8+)

final 키워드 없이도 람다·익명 클래스에서 사용하려면 사실상 final이어야 함.

int x = 10;
// x = 20;  // 이 줄이 있으면 아래 람다에서 컴파일 에러

Runnable r = () -> System.out.println(x);  // x가 effectively final이면 OK

static final vs final

final 인스턴스 변수static final 상수
메모리인스턴스마다 존재클래스에 1개
초기화생성자에서 가능선언 시 또는 static 블록
용도인스턴스 불변 필드전역 상수

핵심 정리

→ 불변 객체 | static

CSLOG에서 보기