지역 클래스 지역 변수 캡쳐 질문
321
작성한 질문수 37
안녕하세요.
자바의 설계상 동기화 등의 문제로 지역 클래스가 생성되 때 지역 변수의 값을 캡쳐하기 때문에 값을 변경하면 컴파일 에러가 난다는 설명에서 문의드릴 게 있습니다.
설명해주신 예제로 확인하면 순서가
1.process() 호출 -> 스택 프레임 생성
2. 해당 메서드 바디의 코드 실행
3. LocalPrinter() 객체 생성
인데, 여기서 3번 LocalPrinter() 객체가 생성이 될 때 지역 변수를 쓰는 게 있다면 그 지역 변수를 LocalPrinter() 객체 내부로 변수를 캡쳐해서 활용한다는 것이잖아요 ?
그러면 설명해주신 것과 같이 객체 생성 이후에 값을 변경하려고 하면 동기화 문제가 발생할 수 있어서 자바에서 그렇게 설계를 안했다는 건 이해를 하겠는데, 객체 생성 전에 값을 바꾸는 건 어떻게 이해를 해야 할까요 ?
생성 전에 값을 바꾸면 사실상 객체 생성 이후 캡쳐를 하더라도 바뀐 값으로 캡쳐를 하면 되니 동기화 문제가 전혀 없을 거 같아서요.
캡쳐본 중 위에는 객체 생성(캡쳐) 이후 바꾸면 안되는 예시이고 동기화 등을 고려하였을 때 제가 궁금한 건 캡쳐 전의 값 변경이 왜 캡쳐에 영향을 주느냐는 겁니다. (아래 캡쳐본)
public Printer process(int param){
int localVar = 1;
class LocalPrinter implements Printer{
int value = 0;
@Override
public void print(){
System.out.println("value = " + value);
System.out.println("local value = " + localVar);
System.out.println("param = " + param);
System.out.println("outInstance = " + outInstance);
}
}
LocalPrinter printer = new LocalPrinter();
localVar = 10;
// printer.print();
return printer;
}public Printer process(int param){
int localVar = 1;
localVar = 10;
class LocalPrinter implements Printer{
int value = 0;
@Override
public void print(){
System.out.println("value = " + value);
System.out.println("local value = " + localVar);
System.out.println("param = " + param);
System.out.println("outInstance = " + outInstance);
}
}
LocalPrinter printer = new LocalPrinter();
//localVar = 10;
// printer.print();
return printer;
}
답변 2
0
안녕하세요, 인프런 AI 인턴입니다.
인프린님의 질문에 답변 드리겠습니다. 자바에서는 메서드 내부에서 정의된 지역 클래스나 익명 클래스가 외부 메서드의 지역 변수를 참조할 때, 해당 변수가 사실상 final인 경우에만 참조가 허용됩니다. ‘사실상 final’이란, 변수에 재할당이 일어나지 않는 경우를 말합니다. 이는 지역 변수가 스택에 저장되며 메서드 실행이 끝나면 사라지는데 반해, 지역 클래스의 객체가 힙 메모리에 저장되어 메서드 실행이 끝난 이후에도 존재할 수 있기 때문입니다. 따라서 안정성을 위해 Java는 값을 변경할 수 없는 (final 또는 사실상 final) 지역 변수만을 캡처할 수 있도록 제한합니다.
첫 번째 예제에서는 localVar의 값을 LocalPrinter 객체 생성 이후에 재할당하려고 시도하였기 때문에 컴파일 에러가 발생합니다. 이 경우, localVar가 사실상 final이 아니게 되어 지역 클래스 내부에서의 사용이 불가능해집니다.
두 번째 예제의 경우, 객체 생성 전에 localVar 값을 변경하는 것은 문제가 없습니다. 이 경우 localVar가 객체 생성 시점에 사실상 final 특성을 유지한다면, 즉 객체 생성 후에는 해당 변수에 대한 재할당이 일어나지 않는다면, 이후 지역 클래스에서 이 값을 안전하게 참조할 수 있습니다.
따라서 객체 생성 전의 값 변경은 객체 생성 시점에 변수가 final이거나 사실상 final 조건을 충족한다면 영향을 주지 않습니다. 핵심은 객체 생성 시점 이후에 해당 변수의 변경 여부이며, 변경이 없다면 동기화 문제나 다른 부작용 없이 값이 캡처되어 사용될 수 있습니다.
문제와 풀이
0
25
1
섹션 2 퀴즈 9번
0
34
2
강의노트 내용이 이해가 되지 않아서 문의드립니다.
0
48
1
중급1편, 래퍼클래스 문제와풀이2 로또제너레이터 질문
0
68
1
setVlaue질문
0
95
3
안녕하세요 코딩테스트와 병행하고 싶어서 질문드립니다.
0
95
1
findValue의 파라메터까지 래퍼클래스 배열인 이유가 있을까요?
0
76
1
아래 글처럼 toString() 강의부터 화면이 안보여요
0
99
2
TemporalAdjusters의 lastDayOfNextMonth(), lastDayOfNextYear() 메서드 지원 안함
0
84
2
오타 제보도 되나요?
0
90
2
지역 클래스 예제3 지역변수 질문
0
69
2
래퍼클래스 박싱 출력
0
60
1
자바 equals() 메소드에 대한 물리적 동일성, 논리적 동등성 질문
0
107
3
강의록 오타 제보
0
69
2
자바의 기본 클래스들에 관하여
0
71
1
실무에서 중첩(내부) 클래스 사용하나요?
0
80
1
지역 클래스 - 지역 변수 캡처3
0
55
1
12:30 의 newClassGrade 질문이 있습니다.
0
57
1
날짜와 시간 문제풀이가 막히는데
0
100
2
내부 클래스의 바깥 클래스 참조
0
68
1
스트링 풀, new String()
0
105
3
정적 중첩 클래스 사용 이유
0
97
1
status.getCode() 대신 status.code 사용
1
81
1
메서드의 지역변수명과 내부클래스의 멤버메서드에서의 지역변수명의 중복관련
0
75
1





