사실상 final(effective final)이란?
2023. 6. 6. 20:46ㆍHigh Level Programming Language/Learning the Java Language
“사실상 final인 바깥쪽 블록의 로컬 변수 및 파라미터”란 자바 람다와 익명 클래스에서 매우 중요한 개념입니다.
이 개념을 완전히 이해하려면 ‘final’과 ‘effectively final(사실상 final)’의 차이부터 설명드리는 게 핵심입니다.
🧠 사실상 final(effective final)이란?
✅ 정의
사실상 final(effective final)이란,
"코드에서 단 한 번만 값이 할당되고, 이후 변경되지 않는 지역 변수나 파라미터를 말합니다."
즉, 명시적으로 final 키워드를 붙이지 않아도 실제로는 변경되지 않는 변수입니다.
🔍 예제 1 – final
과 사실상 final
변수
public void test() {
final int a = 10; // 명시적으로 final
int b = 20; // 사실상 final (값을 변경하지 않음)
int c = 30;
c = 40; // c는 더 이상 사실상 final이 아님
Runnable r = () -> {
System.out.println(a); // OK
System.out.println(b); // OK (사실상 final)
// System.out.println(c); // ❌ 컴파일 오류 - c는 변경되었음
};
r.run();
}
🔎 위 코드에서 분석
변수 | 값 변경 여부 | final 여부 | 사용 가능 여부 |
---|---|---|---|
a |
변경 없음 | final |
✅ 가능 |
b |
변경 없음 | (없음) | ✅ 가능 (사실상 final) |
c |
변경함 | (없음) | ❌ 불가능 |
📌 왜 이런 제약이 있는가?
람다나 익명 클래스는 외부 메서드의 지역 변수를 참조할 수 있지만,
그 변수는 스택 프레임에 저장되고 메서드 종료 시 사라집니다.
그래서 자바는 내부적으로 복사본을 만들어 저장하는 방식을 사용합니다.
그런데 이 복사본이 실제 변수와 다르게 변경된다면 버그와 불일치가 발생할 수 있기 때문에,
"람다에서 접근하는 외부 변수는 반드시 변하지 않아야 한다"는 제약을 둡니다.
즉, “람다에서 외부 변수를 참조할 수는 있지만, 절대 변경하면 안 된다”는 안전장치입니다.
📎 참고: 파라미터도 동일한 규칙 적용
public void printMessage(String message) {
// message는 사실상 final이므로 람다에서 접근 가능
Runnable r = () -> System.out.println(message);
r.run();
}
- 여기서
message
는 메서드 파라미터입니다. - 이 파라미터를 다른 값으로 대입하지 않았기 때문에, 사실상 final로 간주됩니다.
- 따라서 람다에서 접근 가능합니다.
🚫 변경 시 예외
public void printMessage(String message) {
message = "new message"; // 값 변경함 → 더 이상 사실상 final 아님
Runnable r = () -> System.out.println(message); // ❌ 컴파일 오류 발생
}
🧾 정리
용어 | 의미 |
---|---|
final 변수 |
명시적으로 변경 불가 |
사실상 final | 코드 상으로 변경하지 않았지만, final 키워드는 안 붙은 변수 |
람다에서 접근 가능한 외부 변수 | final 또는 사실상 final 인 지역 변수/파라미터만 가능 |
변경된 변수 | ❌ 접근 불가 (컴파일 오류) |
💬 결론
자바에서 람다 표현식은 외부 로컬 변수나 파라미터에 접근할 수 있지만,해당 변수는 반드시 final이거나 사실상 final이어야 합니다.
이 제약은 람다 내부에서 변수 복사본을 안전하게 유지하고, 사이드 이펙트를 방지하기 위한 설계입니다.
'High Level Programming Language > Learning the Java Language' 카테고리의 다른 글
Lesson: Generics (0) | 2023.06.17 |
---|---|
자바 예외 처리(feat.Linux Exception Handling) (0) | 2023.06.07 |
String Class (0) | 2023.06.06 |
Lesson: Classes and Objects [Nested Classes, Local and Anonymous Classes] (0) | 2023.06.04 |
Expression and Statement (0) | 2023.06.01 |