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
댓글
댓글 쓰기