[java] 최종과 실제 최종의 차이점

Java 8에서 람다를 가지고 놀고 있는데 경고가 나왔습니다 local variables referenced from a lambda expression must be final or effectively final. 익명 클래스에서 변수를 사용할 때 외부 클래스에서 최종 변수 여야하지만 여전히 final효과적으로 final 의 차이점은 무엇 입니까?



답변

… Java SE 8부터 로컬 클래스는 최종 또는 효과적으로 최종 블록의 로컬 변수 및 매개 변수에 액세스 할 수 있습니다. 초기화 후에 값이 변경되지 않는 변수 또는 매개 변수는 사실상 최종입니다.

예를 들어 변수 numberLength가 final로 선언되지 않고 PhoneNumber생성자 에 표시된 대 입문을 추가 한다고 가정 하십시오 .

public class OutterClass {

  int numberLength; // <== not *final*

  class PhoneNumber {

    PhoneNumber(String phoneNumber) {
        numberLength = 7;   // <== assignment to numberLength
        String currentNumber = phoneNumber.replaceAll(
            regularExpression, "");
        if (currentNumber.length() == numberLength)
            formattedPhoneNumber = currentNumber;
        else
            formattedPhoneNumber = null;
     }

  ...

  }

...

}

이 대 입문 때문에 변수 numberLength는 더 이상 최종적으로 유효하지 않습니다. 결과적으로 Java 컴파일러 는 내부 클래스 PhoneNumber가 numberLength 변수에 액세스하려고 시도하는 “내부 클래스에서 참조 된 로컬 변수는 최종적이거나 효과적으로 최종적이어야합니다”와 유사한 오류 메시지를 생성 합니다.

http://codeinventions.blogspot.in/2014/07/difference-between-final-and.html

http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html


답변

“효과적으로 최종”을 설명하는 가장 간단한 방법 final은 변수 선언에 수정자를 추가하는 것을 상상하는 것 입니다. 이 변경으로 인해 프로그램이 컴파일 타임과 런타임 모두에서 동일한 방식으로 계속 작동하면 해당 변수는 사실상 최종입니다.


답변

문서 에 따르면 :

초기화 후에 값이 변경되지 않는 변수 또는 매개 변수는 사실상 최종입니다.

기본적으로 컴파일러가 초기화 외부의 할당에 변수가 나타나지 않으면 변수는 효과적으로 final 로 간주됩니다 .

예를 들어 다음과 같은 클래스를 고려하십시오.

public class Foo {

    public void baz(int bar) {
        // While the next line is commented, bar is effectively final
        // and while it is uncommented, the assignment means it is not
        // effectively final.

        // bar = 2;
    }
}


답변

‘Effectively final’은 ‘final’에 의해 추가 될 경우 컴파일러 오류를 발생시키지 않는 변수입니다.

‘Brian Goetz’의 기사에서

비공식적으로, 로컬 변수는 초기 값이 변경되지 않으면 사실상 최종입니다. 즉, 최종 선언하면 컴파일 실패가 발생하지 않습니다.

람다 국가 결승전 브라이언 괴츠


답변

아래의이 변수는 final 이므로 초기화되면 값을 변경할 수 없습니다. 우리가 시도하면 컴파일 오류가 발생합니다 …

final int variable = 123;

그러나 이와 같은 변수를 만들면 값을 변경할 수 있습니다.

int variable = 123;
variable = 456;

그러나 Java 8 에서는 모든 변수가 기본적으로 최종 변수 입니다. 그러나 코드에 두 번째 줄이 있으면 최종적이지 않습니다 . 따라서 위 코드에서 두 번째 줄을 제거하면 변수가 “효과적으로 최종”입니다 .

int variable = 123;

그래서 .. 한 번만 할당 된 모든 변수는, “효과적으로 최종”입니다 .


답변

변수는 최종 또는 효과적으로 마지막그것이 한 번 초기화 된 것 과는 적도 돌연변이하지 소유자 클래스. 그리고 우리는 초기화 할 수 없습니다 그것을 루프 또는 내부 클래스 .

최종 :

final int number;
number = 23;

효과적으로 최종 :

int number;
number = 34;

참고 : FinalEffective Final 은 비슷하지만 (지정 후 값이 변경되지 않음) 효과적인 Final 변수는 Keyword로 선언되지 않습니다 final.


답변

람다식이 둘러싸는 공간에서 할당 된 로컬 변수를 사용하는 경우 중요한 제한이 있습니다. 람다 식은 값이 변경되지 않는 로컬 변수 만 사용할 수 있습니다. 이러한 제한을 ” 변수 캡처 ” 라고 합니다 . 변수가 아닌 람다 식 캡처 값 .
람다식이 사용할 수있는 지역 변수를 ” 실제로 최종 “이라고합니다.
효과적으로 최종 변수는 처음 지정된 후에 값이 변경되지 않는 변수입니다. 이러한 변수를 final로 명시 적으로 선언 할 필요는 없지만 오류는 아닙니다.
예를 들어 보자. 우리는 지역 변수 i를 값 7로 초기화했다. 람다 식에서 우리는 i에 새로운 값을 할당하여 그 값을 변경하려고한다. 이로 인해 컴파일러 오류가 발생합니다. ” 둘러싸는 범위에 정의 된 로컬 변수 i는 최종적이거나 효과적으로 최종적이어야합니다.

@FunctionalInterface
interface IFuncInt {
    int func(int num1, int num2);
    public String toString();
}

public class LambdaVarDemo {

    public static void main(String[] args){
        int i = 7;
        IFuncInt funcInt = (num1, num2) -> {
            i = num1 + num2;
            return i;
        };
    }
}