final과 non-final
final 키워드는 초기화된 변수의 값을 수정할 수 없도록 불병성(immutable)을 부여합니다.
final int var = 100;
// final 변수는 값을 변경 불가
var = 200;
non-final은 자바 프로그래밍에서 제공하는 키워드는 아닙니다. 단순히 final 키워드를 사용하는 변수의 반대 의미로써, 일반 변수를 뜻합니다.
자바에서 non-final 기본(Primitive) 타입의 지역 변수는 스택 메모리에서 관리됩니다. 어떤 메소드에서 지역 변수를 선언하면, 메소드가 종료되는 시점에 지역 변수는 스택 메모리에서 제거됩니다.
반면 final 기본 타입의 지역 변수는 non-final과 달리 JVM 상수 풀에서 관리됩니다. 메소드에서 final 지역 변수를 선언하면, non-final과 생명 주기를 달리 합니다.
effective-final
자바의 람다(lambda)와 익명(annonymous) 객체는 외부의 매개 변수와 지역 변수에 접근 할 수 있습니다. 예시는 익명 객체 Calculatable을 선언하고 있는 메소드의 매개 변수(_arg0, _arg1)와 지역 변수(localVar0, localVar1)의 합을 반환합니다.
static interface Calculatable {
int sum();
}
static class AnnonymousExample {
void method(int _arg0, int _arg1) {
int localvar0 = 5;
int localVar1 = 10;
Calculatable calc = new Calculatable() {
@Override
public int sum() {
return _arg0 + _arg1 + localvar0 + localVar1;
}
};
System.out.println(calc.sum());
}
}
메소드의 매개 변수(_arg0, _arg1)와 지역 변수(localVar0, localVar1)는 메소드가 종료되는 시점에 스택 메모리에서 제거됩니다. 반면 익명 객체는 참조(Reference) 타입이므로 힙 메모리에서 관리됩니다. 힙 메모리에서 관리되는 익명 객체는 스택 메모리에서 관리되는 매개 변수 및 지역 변수와 생명 주기를 달리합니다.
익명 객체는 외부의 매개 변수 및 지역 변수를 참조 할 수 있으나, 서로 간에 생명 주기가 다릅니다. 이미 스택 메모리에서 제거된 매개 변수와 지역 변수를 익명 객체에서 여전히 참조할 수 있다는 문제가 있습니다. 때문에 익명 객체가 참조하는 외부 변수는 final 키워드를 사용하여 JVM 상수 풀에서 관리하도록 해야 합니다.
static interface Calculatable {
int sum();
}
static class AnnonymousExample {
// 매개 변수를 final로 선언
void method(final int _arg0, final int _arg1) {
// 지역 변수를 final로 선언
final int localvar0 = 5;
final int localVar1 = 10;
Calculatable calc = new Calculatable() {
@Override
public int sum() {
return _arg0 + _arg1 + localvar0 + localVar1;
}
};
System.out.println(calc.sum());
}
}
하지만 자바 8부터는 effective-final 기능을 제공하여 람다 또는 익명 객체가 참조하는 외부 변수가 non-final인 경우 컴파일러가 자동으로 final 키워드를 추가하기 때문에 별도로 final 키워드를 지정할 필요가 없습니다.
- 자바 7 이하
람다 또는 익명 객체가 참조하는 외부 변수에 final 키워드 사용 - 자바 8 이상
effective-final을 제공하여 람다 또는 익명 객체가 참조하는 외부 변수에 자동으로 final 키워드 추가
'Java > Java SE, EE' 카테고리의 다른 글
[Java/Java SE, EE] 예외 처리 try-catch-finally, throws (0) | 2022.03.17 |
---|---|
[Java/Java SE, EE] 예외(Exception)와 런타임 예외(Runtime exception) (0) | 2022.03.14 |
[Java/Java SE, EE] 익명(Annnonymous) 객체 (0) | 2022.03.14 |
[Java/Java SE, EE] 클래스, 인터페이스의 중첩 선언 (0) | 2022.03.02 |
[Java/Java SE, EE] 인터페이스(Interface) (0) | 2022.02.21 |