본문 바로가기
Programming/JAVA

Effectively final

by 한 땀; 한 땀; 2020. 12. 11.
class JustSort {
    public void sort(List<?> list) {
        Collections.reverse(list);
    }
}

class TestMain {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, -2, 6, -4, 0);
        list = new ArrayList<>(list);
        JustSort js = new JustSort();

        Consumer<List<Integer>> c1 = e -> js.sort(e); // 인스턴스 생성에 같은 지역에 선언된 참조변수에 접근

        Consumer<List<Integer>> c2=new Consumer<List<Integer>>() {
            @Override
            public void accept(List<Integer> integers) {
                js.sort(integers); // 인스턴스 생성에 같은 지역에 선언된 참조변수에 접근
            }
        };

        c1.accept(list);

        System.out.print(list);
    }
}

 

람다식에서 참조하는 지역변수는  final로 선언되었거나 effectively final 변수여야 한다.

즉, 위의 람다식에서 쓰인 참조변수 js는 참조하는 인스턴스가 변경될 수 없다.

따라서 다음과 같은 코드가 작성 될 경우 컴파일 에러가 발생한다.

 

class JustSort {
    public void sort(List<?> list) {
        Collections.reverse(list);
    }
}

class TestMain {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, -2, 6, -4, 0);
        list = new ArrayList<>(list);
        JustSort js = new JustSort();
        js=new JustSort(); // final 또는 effectively final 성격이 깨져서 컴파일 에러가 발생한다.
        Consumer<List<Integer>> c1 = e -> js.sort(e);

        Consumer<List<Integer>> c2=new Consumer<List<Integer>>() {
            @Override
            public void accept(List<Integer> integers) {
                js.sort(integers);
            }
        };

        c1.accept(list);

        System.out.print(list);
    }
}

 

만약 위 코드가 컴파일 에러를 발생하지 않고 final 또는 effectively final 변수가 아니여도 허용을 해서 js가 참조하는 인스턴스를 변경할 수 있다면 js.sort 메소드의 결과는 예측할 수가 없게 된다. 

 

참고

 

인스턴스의 생성은 힙 영역에 할당이 이뤄지고 지역 변수는 스택 영역에 할당이 이뤄진다.

'Programming > JAVA' 카테고리의 다른 글

Optional Map  (0) 2020.12.12
Lambda Expression  (0) 2020.12.10
Nested Class, Inner Class  (0) 2020.12.08

댓글