문제

나는 종종 다음과 같은 것처럼 보이는 방법을 발견합니다.

public void foo(final String a, final int[] b, final Object1 c){
}

이 방법이 최종 매개 변수를 전달하지 않고 호출되면 어떻게됩니까? 즉, 나중에 변경된 객체 1 (따라서 최종으로 선언되지 않음) 은이 방법으로 전달 될 수 있습니다.

도움이 되었습니까?

해결책

Java는 항상 메소드로 보내기 전에 매개 변수 사본을 만듭니다. 이것은 마지막이 호출 코드의 차이를 의미하지 않는다는 것을 의미합니다. 이것은 메소드 내에서 변수를 재 할당 할 수 없음을 의미합니다. (최종 객체가있는 경우에도 개체의 속성을 변경할 수 있습니다).

다른 팁

당신이있는 상황이 있습니다 필수의 최종적으로 선언하려면-다른 경우에 컴파일 오류가 발생합니다. 즉, 익명 클래스로 전달합니다. 기본 예 :

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = new FileFilter() {
        public boolean accept(File pathname) {
            return pathname.getName().endsWith(extension);
        }
    };

    // What would happen when it's allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}

제거 final 수정자는 더 이상 값이 런타임 상수임을 보장하지 않기 때문에 컴파일 오류가 발생합니다. 익명 클래스 외부에서 값을 바꾸면 익명 클래스 인스턴스가 창조 순간에 다르게 행동하게됩니다.

Java는 단지 패스 별 가치입니다. (또는 더 나은-패스 참조 별 값)

그래서 통과 된 논쟁과 방법 내의 논쟁은 두 가지 다른 같은 개체 (값)를 가리키는 핸들러.

그러므로 당신이 변하면 상태 객체의 경우, 참조하는 다른 모든 변수에 반영됩니다. 그러나 새로운 객체 (값)를 인수에 다시 할당하면이 객체 (값)를 가리키는 다른 변수는 다시 할당되지 않습니다.

그만큼 final 메소드 매개 변수의 키워드는 발신자에게 전혀 아무것도 의미하지 않습니다. 또한 존재 또는 부재가 바이트 코드를 변경하지 않기 때문에 실행 프로그램에는 전혀 아무것도 의미하지 않습니다. 매개 변수 변수가 메소드 내에서 재 할당 된 경우 컴파일러가 불만을 제기 할 수 있습니다. 그게 다야. 그러나 충분합니다.

일부 프로그래머 (나 같은)는 그것이 아주 좋은 일이며 사용한다고 생각합니다. final 거의 모든 매개 변수에서. 길고 복잡한 방법을 이해하는 것이 더 쉬워집니다 (길고 복잡한 방법이 리팩토링되어야한다고 주장 할 수 있지만) 그렇지 않습니다 표시되어 있습니다 final.

이 foo () 구현을 고려하십시오.

public void foo(final String a) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.print(a);
        }
    }); 
}

때문에 Runnable 인스턴스는이 방법을 오래 살면 final 키워드 - final 컴파일러에게 참조 사본을 가져 오는 것이 안전하다고 알려줍니다 (나중에 참조하기 위해). 따라서 그것은입니다 참조 그것은 최종으로 간주됩니다 . 다시 말해 : 발신자로서, 당신은 아무것도 엉망으로 만들 수 없습니다 ...

결정적인 변수가 할당되면 해당 변수의 값을 변경할 수 없음을 의미합니다.

한편, 사용 결정적인 이러한 방법의 주장은 의미합니다 메소드 실행 중에 프로그래머가 값을 변경할 수 없습니다.. 이것은 단지 메소드 내부를 의미합니다 결정적인 변수는 재 할당 할 수 없습니다.

매개 변수를 최종으로 선언하면 값을 변경할 수 없습니다.

class Bike11 {  
    int cube(final int n) {  
        n=n+2;//can't be changed as n is final  
        n*n*n;  
     }  
    public static void main(String args[]) {  
        Bike11 b=new Bike11();  
        b.cube(5);  
    }  
}   

출력 : 시간 오류를 컴파일합니다

자세한 내용은 내 블로그를 방문하십시오. http://javabyroopam.blogspot.com

문자열은 불변이기 때문에 나중에 문자열을 변경할 수는 없습니다 (문자열 객체를 다른 문자열 객체를 가리키는 변수 만 만들 수 있습니다).

그러나 이것이 변수를 final 매개 변수. 모든 컴파일러 점검은 매개 변수가 재 할당되지 않았다는 것입니다. 이내에 방법. 이것은 문서화 목적, 아마도 좋은 스타일에 적합하며 속도를 위해 바이트 코드를 최적화하는 데 도움이 될 수도 있습니다 (실제로는 그리 많지 않은 것 같습니다).

그러나 메소드 내에서 매개 변수를 재 할당하더라도 Java는 모든 매개 변수를 전달하는 모든 매개 변수를 수행하기 때문에 발신자는 알지 못합니다. 시퀀스 후

  a = someObject();
  process(a);

A의 필드가 바뀌었을 수도 있지만 A는 여전히 이전과 같은 객체입니다. 통과 참조 언어에서는 이것이 사실이 아닐 수도 있습니다.

@stuxnet, 나는 정반대의 주장을 할 수 있습니다. 객체를 함수로 전달하고 전달 된 객체의 속성을 변경하면 함수의 발신자가 변수의 변경된 값을 볼 수 있습니다. 이것은 통과별로 값이 아닌 통과에 의한 통과를 의미합니다.

혼란스러운 것은 포인터의 사용이 최종 사용자에게 완전히 숨겨져있는 시스템에서 통과별로 값 또는 통과에 따라 통과하는 것입니다.

Java는 확실히 가치별로 가치가 없으며, 그와 같이 전달 된 물체를 돌연변이 할 수 있으며 원본은 영향을받지 않을 것입니다.

원시를 변수에만 할당 할 수있는 프리미티브를 돌연변이 할 수는 없습니다. 따라서 프리미티브를 사용하여 참조 또는 값으로 패스를 테스트하는 것은 테스트가 아닙니다.

다른 언어로 할 수있는 Java에서 할 수없는 것은 Java에 포인터가 없기 때문에 발신자의 변수를 새로운 값으로 재 할당하는 것입니다.

메소드 입력 매개 변수의 최종 키워드는 필요하지 않습니다. Java는 객체에 대한 참조 사본을 만듭니다. 따라서 최종적으로 켜짐에 따라 객체를 최종적으로 만들지 않고 참조만으로는 의미가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top