○ 로컬 클래스에서의 사용 제한
로컬 클래스에서의 여러 멤버들의 사용 제한 규칙에 대해서 살펴보겠습니다. 우선 로컬 클래스에서의 규칙과 관련해서는 인스턴스 멤버 클래스에 비해서 복잡한 내용이 많으니, 잊지 말고 로컬 클래스의 개념에 대해서 다시 한번 짚고 넘어가 보도록 하겠습니다.
로컬 클래스의 특성을 요약하면, 아래의 내용과 같습니다. 일단 기본적으로 특정 메서드의 하위로 선언되기 때문에 정적 멤버는 선언이 불가하다는 기본 특성이 있습니다.
· 로컬 클래스는 접근 제한자(public, private) / static을 붙이지 않는다.
: 메서드 내에서만 사용되므로 접근 제한을 선언할 필요가 없음
· 정적 필드와 메서드는 선언할 수 없다.
void method() {
/* 로컬 클래스 */
class D {
D() { }
int field1;
void method1() { }
}
/ * 로컬 클래스의 사용 */
D d = new D();
d.field1 = 3;
d.method1();
}
위의 예시를 통해서 설명해 볼까요? 위 method( )가 바깥 클래스 A의 메서드라고 가정해 보겠습니다.
· 일단 로컬 클래스 D의 경우, 바깥 클래스 A의 필드나 메서드는 제한 없이 사용이 가능합니다.
· 그런데 위에서 new를 통해 생성한 로컬 클래스 D의 인스턴스(d)를 봅시다. method( )의 실행이 끝나는 시점에 어떻게 될까요?메서드의 실행이 끝났으니 사라질까요? 예상과는 다르게 여전히 heap(힙)에 살아있는 상태가 됩니다.
▷ 그런데 만약 이 로컬 클래스 D가 애초에 method( )라는 메서드가 갖고 있던 메서드 자체의 로컬 변수나 해당 메서드의 파라미터를 사용하도록 선언했다면, 어떤 일이 벌어질까요?
▷ 로컬 클래스 D의 인스턴스는 살아 있는데, method( )의 실행은 끝났으므로 method( )의 로컬 별수나 파라미터는 stack(스택)에서 사라지게 됩니다. 결국 로컬 클래스 D의 인스턴스는 실행에 문제를 일으키게 됩니다. 사라진 값을 사용하는 꼴이니까요.
이러한 문제를 그대로 자바의 기본 규칙으로 방치하게 된다면, 사실상 특정 메서드의 로컬 클래스는 상위 메서드의 멤버들을 모두 사용할 수 없는 불편한 존재가 되고 맙니다. 그래서 JAVA에서는 이러한 문제를 해결하기 위해서, 로컬 클래스가 바깥 메서드('method()' 를 의미합니다)를 사용하는 경우에 대해 다음과 같은 규칙을 두고 있습니다.
로컬 클래스가 바깥 메서드의 매개변수 혹은 로컬 변수의 값을 사용하게 되면, 컴파일 할 때 해당 값을 로컬 클래스 내부에 복사해 두고 사용하게 된다.
자, 이제 이렇게 조치를 취한다면 어느 정도 로컬 클래스에서의 바깥 메서드 값 사용에 있어서 문제가 해결된 것 같습니다. 하지만! 100% 모든 것이 해결된 것은 아닙니다. 왜일까요? 생각해 봅시다. 로컬 클래스에서 method()의 로컬 변수나 파라미터 값을 복사해서 사용하고 있는데, 갑자기 바깥 클래스의 값들이 복사된 이후에 변경 된다면 또다시 문제가 발생하게 됩니다.
머리가 아프네요. 그럼 또 JAVA에서는 어떤 규칙을 사용하게 될까요?
JAVA 7 이전까지는 이 문제를 이렇게 해결했습니다. 선언 키워드 중에 우리는 [final]을 배웠습니다. final은 결국 단순하게 말해 '값을 수정할 수 없는' 속성을 갖게 되겠죠. 그럼 쉽게 정리하자면 '로컬 클래스에서는 final 키워드가 선언된 로컬 변수나 파라미터만 사용가능하다.'라고 정리하면 되겠습니다. 로컬 클래스를 선언할 때는 주의해서 final 키워드가 있는 값들만 사용하면 문제가 해결됩니다. 만약 final 키워드가 없는 로컬 변수 등을 로컬 클래스에서 사용하게 되면, 컴파일 에러를 발생시켰습니다.
하지만 JAVA 8에 이르러서는 이 규칙 역시 좀 더 확장되어서, 융통성 있게 바깥 클래스의 값들을 사용할 수 있도록 변경되었습니다. 바로 final이 없는 값이라도 로컬 클래스에서 사용할 수 있게 된 것이죠. 잠깐 - 그럼 우리가 위에서 설명한 문제는 어떻게 해결된 것일까요?
일단 final이 아닌 값들을 허용한다는 것은 아닙니다. 다만 컴파일 과정에서 값을 복사해 처리하는 방식이 바뀌어 값을 변경할 수 없는 final 속성을 부여하게 됩니다. 이 방식에 대해서는 다음 아티클에서 좀 더 상세히 살펴보겠습니다.
'Programming > JAVA' 카테고리의 다른 글
중첩 클래스&인터페이스(3) - 중첩 클래스의 접근 제한자 5 : 바깥 클래스 참조하기 (0) | 2023.04.11 |
---|---|
중첩 클래스&인터페이스(3) - 중첩 클래스의 접근 제한자 4 : 로컬 클래스 (0) | 2023.04.10 |
중첩 클래스&인터페이스(3) - 중첩 클래스의 접근 제한자 2 (0) | 2023.04.06 |
중첩 클래스&인터페이스(3) - 중첩 클래스의 접근 제한자 1 (0) | 2023.04.04 |
중첩 클래스&인터페이스(2) - 중첩 클래스의 종류 2 : 정적 멤버 / 로컬 클래스 (0) | 2023.04.03 |