programing

최종과 실제 최종의 차이

prostudy 2022. 6. 11. 11:46
반응형

최종과 실제 최종의 차이

를 가지고 하는 것을 요.local variables referenced from a lambda expression must be final or effectively final익명 클래스 내에서 변수를 사용할 경우 외부 클래스에서는 최종 변수여야 하지만 최종 변수와 실제 최종 변수의 차이점은 무엇입니까?

...Java SE 8부터는 로컬 클래스가 최종 또는 사실상 최종인 인클로징 블록의 로컬 변수 및 파라미터에 액세스할 수 있습니다.초기화된 후 값이 변경되지 않는 변수 또는 파라미터는 사실상 최종 변수입니다.

를 들어 " ", " 가numberLength합니다.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변수 선언의 수식자.이 변경으로 프로그램이 컴파일 시 및 실행 시 모두 동일한 방식으로 계속 동작한다면 해당 변수는 사실상 최종적인 것입니다.

문서에 따르면:

초기화된 후 값이 변경되지 않는 변수 또는 파라미터는 사실상 최종 변수입니다.

기본적으로 컴파일러가 변수가 초기화 이외의 할당에 나타나지 않는 것을 발견하면 변수는 사실상 최종적인 것으로 간주됩니다.

예를 들어, 다음과 같은 클래스가 있습니다.

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;
    }
}

아래 변수는 최종 변수이므로 초기화된 값은 변경할 수 없습니다.이렇게 하면 컴파일 오류가 발생합니다.

final int variable = 123;

하지만 우리가 이런 변수를 만들면, 그 값을 바꿀 수 있어...

int variable = 123;
variable = 456;

그러나 Java 8에서는 기본적으로 모든 변수가 최종 변수입니다.하지만 코드에 두 번째 행이 있기 때문에 최종적이지 않습니다.따라서 위의 코드에서 두 번째 줄을 제거하면 변수가 "사실상 최종"이 됩니다.

int variable = 123;

즉, 한 번만 할당된 변수는 "효과적인 최종" 변수입니다.

'effective final'은 'final' 뒤에 추가될 경우 컴파일러 오류를 발생시키지 않는 변수입니다.

'브라이언 괴츠'의 기사를 보면

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

람다 스테이트 파이널 브라이언 괴츠

변수는 한 번 초기화되고 소유자 클래스에서 변환되지 않은 경우 최종 또는 사실상 최종입니다.루프나 내부 클래스에서는 초기화할 없습니다.

최종:

final int number;
number = 23;

사실상 최종:

int number;
number = 34;

주의: Final과 Effective Final은 비슷합니다(할당 후 값은 변경되지 않습니다).단, 유효한 Final 변수는 키워드로 선언되지 않습니다.final.

람다 표현식이 주변 공간에서 할당된 로컬 변수를 사용하는 경우 중요한 제한이 있습니다.람다 식은 값이 변경되지 않는 로컬 변수만 사용할 수 있습니다.이 제한은 변수가 아닌 람다캡처 값으로 설명되는 "변수 캡처"라고 합니다.
람다 식에서 사용할 수 있는 로컬 변수를 "효과적인 최종 변수"라고 합니다.
효과적인 최종 변수는 값이 처음 할당된 후에도 변경되지 않는 변수입니다.이러한 변수를 final로 명시적으로 선언할 필요는 없지만, 그렇게 한다고 해서 오류가 되는 것은 아닙니다.
예를 들어 람다 식에서는 i에 새로운 값을 할당하여 값을 변경하려고 하는 로컬 변수 i가 값 7로 초기화되어 있습니다. 경우 컴파일러 오류가 발생합니다. "포함된 범위에서 정의된 로컬 변수 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;
        };
    }   
}

효과적인 최종 토픽은 JLS 4.12.4에 기술되어 있으며, 마지막 단락은 명확한 설명을 포함하고 있다.

변수가 사실상 최종적인 경우 선언에 최종 수식자를 추가해도 컴파일 시간 오류가 발생하지 않습니다.반대로 유효한 프로그램에서 final로 선언된 로컬 변수 또는 파라미터는 최종 수식자가 삭제되면 사실상 final이 됩니다.

final은 키워드를 포함한 변수 선언입니다.final, 예:

final double pi = 3.14 ;

남아 있다final프로그램을 통해 이 줄 이후에 pi를 변경하는 것은 절대 허용되지 않습니다.

effective final : 현재 1회(또는 1회만 갱신) 값이 할당된 로컬 변수 또는 파라미터.프로그램 전체에 걸쳐 효과적으로 최종 상태를 유지하지 못할 수 있습니다., 최종 변수가 할당되거나 하나 이상의 추가 할당을 받은 직후에 효과적으로 최종 속성을 잃을 수 있습니다.예:

class EffectivelyFinal {
    
    public static void main(String[] args) {
        calculate(124,53);
    }
    
    public static void calculate( int operand1, int operand2){   
     int rem = 0;  //   operand1, operand2 and rem are effectively final here
     rem = operand1%2  // rem lost its effectively final property here because it gets its second assignment 
                       // operand1, operand2 are still effectively final here 
        class operators{

            void setNum(){
                operand1 =   operand2%2;  // operand1 lost its effectively final property here because it gets its second assignment
            }
            
            int add(){
                return rem + operand2;  // does not compile because rem is not effectively final
            }
            int multiply(){
                return rem * operand1;  // does not compile because both rem and operand1 are not effectively final
            }
        }   
   }    
}
public class LambdaScopeTest {
    public int x = 0;        
    class FirstLevel {
        public int x = 1;    
        void methodInFirstLevel(int x) {

            // The following statement causes the compiler to generate
            // the error "local variables referenced from a lambda expression
            // must be final or effectively final" in statement A:
            //
            // x = 99; 

        }
    }    
}

다른 사람들이 말했듯이 초기화된 후 값이 변경되지 않는 변수 또는 파라미터는 사실상 최종적인 것입니다.위의 코드에서 다음 값을 변경하면x내적 계급에서.FirstLevel그러면 컴파일러가 다음 오류 메시지를 표시합니다.

람다 식에서 참조되는 로컬 변수는 최종 변수이거나 사실상 최종 변수여야 합니다.

를 추가할 수 있는 경우final로컬 변수에 대한 수정자, 사실상 최종 변수였습니다.

Lambda 식에서 액세스할 수 있습니다.

  • 정적 변수,

  • 인스턴스 변수,

  • 효과적인 최종 방법 매개 변수 및

  • 효과적으로 최종 로컬 변수입니다.

출처 : OCP : Oracle Certified Professional Java SE 8 Programmer II Study Guide, Jeanne Boyarsky, Scott Selikoff

또한.

effectively finalvariable은 값이 변경되지 않는 변수입니다.단, 이 변수에는final키워드를 지정합니다.

출처 : Java에서 시작 : Control Structures to Objects (제6판), Tony Gaddis

게다가, 그 의미를 잊지 마세요.final처음 사용하기 전에 정확히 한 번 초기화됩니다.

변수 선언final또는 선언하지 않음final그러나 실제로 최종 상태를 유지하면 (컴파일러에 따라) 다른 바이트코드가 될 수 있습니다.

다음으로 작은 예를 제시하겠습니다.

    public static void main(String[] args) {
        final boolean i = true;   // 6  // final by declaration
        boolean j = true;         // 7  // effectively final

        if (i) {                  // 9
            System.out.println(i);// 10
        }
        if (!i) {                 // 12
            System.out.println(i);// 13
        }
        if (j) {                  // 15
            System.out.println(j);// 16
        }
        if (!j) {                 // 18
            System.out.println(j);// 19
        }
    }

대응하는 바이트 코드main메서드(Windows 64비트에서는 Java 8u161):

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_1
       3: istore_2
       4: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       7: iconst_1
       8: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
      11: iload_2
      12: ifeq          22
      15: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
      18: iload_2
      19: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
      22: iload_2
      23: ifne          33
      26: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
      29: iload_2
      30: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
      33: return

대응하는 회선 번호 테이블:

 LineNumberTable:
   line 6: 0
   line 7: 2
   line 10: 4
   line 15: 11
   line 16: 15
   line 18: 22
   line 19: 26
   line 21: 33

행에 소스코드가 표시되어 있듯이12,13,14바이트 코드에 표시되지 않습니다.그 이유는itrue상태를 바꾸지 않을 것입니다.따라서 이 코드는 도달할 수 없습니다(자세한 내용은 이 답변).같은 이유로 코드가 줄지어 있습니다.9그리워요.의 상태i평가하지 않아도 됩니다.true★★★★★★ 。

, 「」는j같은 방식으로 처리되지 않는 사실상 최종적인 것입니다.이러한 최적화는 적용되지 않습니다.의 상태j2번입니다.는 이트음음음음음음음음음음음음음 the the에 관계없이 .j사실상 최종적인 것입니다.

Effective final 변수는 다음과 같은 로컬 변수입니다.

  1. 「」로 .final
  2. 한 번만 할당됩니다.

최종 변수는 다음과 같은 변수입니다.

  1. 「」로 .final키워드를 지정합니다.

단, Java SE 8부터는 로컬클래스가 최종 또는 사실상 최종인> 클로징블록의 로컬 변수와 파라미터에 접근할 수 있습니다.

자바8에서 시작한 게 아니라 오래 전부터 쓰고 있어요.이 코드는 (Java 8 이전) 합법적으로 사용되었습니다.

String str = ""; //<-- not accesible from anonymous classes implementation
final String strFin = ""; //<-- accesible 
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
         String ann = str; // <---- error, must be final (IDE's gives the hint);
         String ann = strFin; // <---- legal;
         String str = "legal statement on java 7,"
                +"Java 8 doesn't allow this, it thinks that I'm trying to use the str declared before the anonymous impl."; 
         //we are forced to use another name than str
    }
);

언급URL : https://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final

반응형