자바 람다에서 final이거나 final처럼 쓰인 지역 변수만 접근할 수 있는 이유는?
자유 변수는 람다 캡쳐링에 의해 복사되기 때문에 다른 스레드에서 참조할 수 있고,
람다 캡쳐링에 의해 복사된 참조 값을 변경하는 코드는 람다 실행 시점에 따라 복사된 참조 값이 어떤 값인지 예측할 수 없기 때문(= 동기(Sync)를 맞출 수 없기 때문)에 final 또는 effectively final로 쓰입니다.
조금 어려운 말로 표현하면 자바의 '스레드 한정(Thread Comfinement)' 기법(또는 원칙)을 위배하지 않기 위해서 final 또는 effectively final로 정했다고 합니다.
출처: https://jeong-pro.tistory.com/211?category=793347 [기본기를 쌓는 정아마추어 코딩블로그]
메서드 안에 위치한 지역클래스나 익명 클래스에서 외부의 지역변수를 사용하기 위해서는
final 지정을 해야만 사용이 가능하다. 책에서는 "메서드가 수행을 마쳐서 지역변수가 소멸된 시점에도,
지역(익명) 클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문이다."
라고 설명을 했지만 도통 이해가 안되서 좀 더 알아보았다.
지역변수를 final로 지정하면 JVM constant pool에서 따로 변수를 관리한다.
따라서 지역클래스를 포함하고 있는 메서드와 메서드 안에 있는 final 지역변수는
생명주기가 달라진다. 이 이유로 메서드가 가비지컬렉션에 반납되어도 메서드 안의
final 지역변수는 constant pool에서 계속 보관하고 있기 때문에 이를 참조하고 있는
지역 클래스의 인스턴스는 문제없이 동작할 수 있다.
즉, 생명주기가 달라지면 동작의 안전성을 보장하지 못하므로 지역(익명)클래스에서 외부의 변수를
사용하기 위해서는 final로 지정된 변수를 사용하도록 하고 있다.
출처 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=javaking75&logNo=140178355095
'무지성 메모' 카테고리의 다른 글
■ 오버헤드 ■ flatMap ■ 기본형 스트림 (IntStream, LongStream, DoubleStream)의 장점 ■ 스트림 ■ 람다 캡쳐링 ■ 스레드 한정 기법 (0) | 2021.10.14 |
---|---|
■렌더링 ■jpa ■프록시 (0) | 2021.10.10 |
■Map을 Key값이 아닌 Value를 이용하여 정렬 (0) | 2021.10.08 |
■split() vs StringTokenizer ■DFS vs 백트래킹 (0) | 2021.09.27 |
ifpresent의 인자를 람다식으로 주셨는데 m->{}형태가 아닌 ()->{}형태로 주면 오류가 나는데 이유를 잘 모르겠습니다. (0) | 2021.08.03 |