기본 콘텐츠로 건너뛰기

Java 람다함수에서 외부지역변수를 수정할 수 없는 이유

 C++ 하다 보면, 람다함수에서 외부지역변수 수정을 숨쉬듯이 하는 편인데, Java 에서 동일한 형태로 람다함수를 사용하려고 하면, 오류난다.

// Java
import java.util.function.Consumer;

public class MyClass {
    public String getString() {
        String result = "";

        Consumer<String> lamda = (String name) -> {
            result = "<<" + name + ">>";
        };

        return result;
    }

    public static void main(String[] args) {
        System.out.println("new MyClass().getString(): " + new MyClass().getString());
    }
}
// 컴파일 결과
// javac MyClass.java
// MyClass.java:8: error: local variables referenced from a lambda expression must be final or effectively final
//             result = "<<" + name + ">>";
//             ^
// 1 error
// C++
#include <iostream>
#include <string>
using namespace std;

class MyClass {
    public:
        string getString() {
            string result;

            auto lamda = [&] (string name) {
                result = "<<" + name + ">>";
            };

            lamda("Purewell");

            return result;
        }
};

int
main(int argc, char* argv[]) {
    cout << "(new MyClass())->getString()): " << (new MyClass())->getString() << endl;
}

// 실행결과: (new MyClass())->getString()): <<Purewell>>

위와 같이 C++에선 지역변수에 접근해서 값을 수정하였으나, Java에선 컴파일 타임에 문법 오류 난다.

사유는 Java에서 적극 사용하는 Thread인 듯 싶다.

지역변수는 Java에서 Thread끼리 공유하지 않는 Stack영역에 있고, 클래스 멤버변수들은 공유 가능한 Heap 영역에 있어서...라는데, 난 잘 모르겠다.

지역변수는 해당 메서드가 끝나면, 스택에서 사라진다. 만약 람다함수가 스레드를 사용하는 객체라면, 호출한 메서드(MyClass.getString())가 끝나도, 람다함수가 실행 중일 수 있다. 이때 캡쳐한 지역변수를 변경하려고 접근하려면, 이미 스택에서 사라진 변수에 접근하면서 오류가 발생할 것이다.

C++ 식이라면, 알아서 척척척 스스로 개발자가 모두 처리를 해야하지만, Java는 그런 경우를 아예 용납하지 않는 것 같다.

참조: https://www.baeldung.com/java-lambda-effectively-final-local-variables


댓글

이 블로그의 인기 게시물

탐색기에서 OneDrive 이 2개로 보이는 문제

왜 2개가 보이는지 모르겠지만, Registry 삭제하면 됨 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace 하위 키에서 OneDrive 둘 중에 하나만 지워도 바로 반영됨. 참조:  https://answers.microsoft.com/en-us/msoffice/forum/all/duplicate-onedrives-in-file-explorer/49c935a6-287b-43a5-aed5-2dee2a1c1b22