자바 메소드 인수를 최종으로 만들기


92

final아래 코드의 차이점은 무엇입니까? 인수를 final.

public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){  
    return ....
}

public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
        final Timezone toTz){
    return ....
}

4
매개 변수가 재사용되거나 재 할당되면 경고하는 코드 분석기가 있습니다. (지역 변수와 동일) IMHO, 변경이 바람직하지 않은 경우 이러한 매개 변수를 포착하는 더 좋은 방법입니다.
— Peter Lawrey 2010


Java는 기본적으로 모든 입력 방법 인수를 최종적으로 만들어야한다고 생각합니다. 그런 다음 참조를 수정하려면 수동으로해야합니다. 그렇게하면 죄책감 요인이 그러한 많은 경우를 예방할 수 있습니다.
— Sid

답변:


131

공식 메소드 매개 변수는 지역 변수이므로 final로 선언 된 경우에만 내부 익명 클래스에서 액세스 할 수 있습니다.

이렇게하면 메서드 본문에서 다른 지역 최종 변수를 선언하지 않아도됩니다.

 void m(final int param) {
        new Thread(new Runnable() {
            public void run() {
                System.err.println(param);
            }
        }).start();
    }

27
+1 : 이것은 중요한 사용 사례이며 필요한 유일한 시간 입니다. (이것은 프로그래머를 돕는 편리 무엇 단지 문제 나머지 시간.)
— DONAL 휄로우

3
이것의 이유를 물어봐도 될까요?
— KodeWarrior

21
Java 8에서는 더 이상 필요하지 않습니다.
— Amit Parashar 2015


3
@AmitParashar 사실이지만 Java 8은 내부 클래스에서 변수를 사용해야 할 때마다 "final" 이라는 키워드를 사용 하지 않아도됩니다 ... 현실은 컴파일러가 최종성을 암시 적으로 만드는 것뿐입니다. 변수가 효과적으로 최종적 이어야합니다 ... 따라서 나중에 할당하려고하면 컴파일 시간 오류가 발생합니다! 자바 8 : SNEAK 100 :)
— varun

38

최종 키워드의 최종 단어에서 추출

최종 매개 변수

다음 샘플은 최종 매개 변수를 선언합니다.

public void doSomething(final int i, final int j)
{
  // cannot change the value of i or j here...
  // any change would be visible only inside the method...
}

final은 여기서 두 인덱스 i와 j가 메서드에 의해 실수로 재설정되지 않도록하는 데 사용됩니다. 매개 변수 값을 잘못 변경하는 교활한 버그로부터 보호 할 수있는 편리한 방법입니다. 일반적으로 짧은 메서드는 이러한 종류의 오류로부터 보호하는 더 좋은 방법이지만 최종 매개 변수는 코딩 스타일에 유용한 추가 기능이 될 수 있습니다.

최종 매개 변수는 메서드 서명의 일부로 간주되지 않으며 메서드 호출을 확인할 때 컴파일러에서 무시됩니다. 매개 변수는 메소드가 재정의되는 방법에 영향을주지 않고 최종 (또는 그렇지 않음)으로 선언 될 수 있습니다.


18
이 예제에서는 기본 변경 사항이 항상 메서드 내에서만 표시되므로 객체를 사용하는 것이 더 나을 수 있습니다. 그리고 개체의 경우에도 변경할 수 있습니다. 새로운 물체를 가리킬 수 없습니다. 사실 이제 생각해 보면 final은 변수 선언을 AIC로 저장하고 컴파일러가 어떤 이유로 든 수정하고 싶지 않은 매개 변수의 우발적 인 수정을 지적하는 것 외에는 아무것도 변경하지 않습니다. .
— 롭 그랜트

27

마지막은 변수에 새 값을 할당하는 것을 방지하므로 오타를 포착하는 데 도움이 될 수 있습니다. 스타일 적으로 수신 된 매개 변수를 변경하지 않고 로컬 변수에만 할당 할 수 있으므로 final이 해당 스타일을 적용하는 데 도움이됩니다.

매개 변수에 대해 final을 사용하는 것을 거의 기억하지 못한다는 것을 인정해야합니다.

public int example(final int basicRate){
    int discountRate;

    discountRate = basicRate - 10;
    // ... lots of code here 
    if ( isGoldCustomer ) {
        basicRate--;  // typo, we intended to say discountRate--, final catches this
    }
    // ... more code here

    return discountRate;
}

1
인수를 final로 선언하는 것이 유용한 방법에 대한 훌륭한 예입니다. 나는 이것에 부분적이지만 그들은 또한 3 개 이상의 매개 변수에 대해 한 입입니다.
— JoseHdez_2

14

큰 차이는 없습니다. 그것은 당신이 쓸 수 없다는 것을 의미합니다.

stamp = null;
fTz = new ...;

그러나 여전히 다음과 같이 작성할 수 있습니다.

stamp.setXXX(...);
fTz.setXXX(...);

그것은 당신을 따르는 유지 보수 프로그래머에게 당신이 명확하지 않고 혼란을 야기 할 수있는 당신의 방법 중간 어딘가에 매개 변수에 새로운 값을 할당하지 않을 것이라는 힌트입니다.


3

Java에서 매개 변수 / 변수에 사용되는 final 키워드는 참조를 final로 표시합니다. 객체를 다른 메서드로 전달하는 경우 시스템은 참조 변수의 복사본을 만들어 메서드에 전달합니다. 새 참조를 최종적으로 표시하면 재 할당되지 않도록 보호 할 수 있습니다. 때로는 좋은 코딩 관행으로 간주됩니다.


1
추가해야합니다. 매개 변수가 원시적이면 차이점이 없습니다. 또한 매개 변수가 컬렉션 (객체 목록 ...) 인 경우 final을 추가해도 수정되는 것을 막을 수 없습니다.
— Sam003

1
불변성은 항상 바람직한 특성입니다. Java에는 기본적으로 제공되지 않습니다. 변수를 최종적으로 만들면 참조 무결성이 보장됩니다.
— 시드

1
나는 동의한다. 그러나 정말로 객체의 불변성을 얻고 싶다면 깊은 복제를 시도 할 수 있습니다.
— Sam003

2

이 방법의 본문에 대해 final 키워드는 인수 참조가 실수로 재 할당되는 것을 방지하여 이러한 경우에 컴파일 오류를 제공합니다 (대부분의 IDE는 즉시 불평합니다). 어떤 사람들은 final가능할 때마다 일반적으로 사용 하면 속도가 빨라진다 고 주장 할 수 있지만 최근 JVM에서는 그렇지 않습니다.


2

내가 본 두 가지 장점은 다음과 같습니다.

1 메소드 인수를 final로 표시하면 메소드 내에서 인수 재 할당을 방지합니다.

당신의 예에서

    public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
            final Timezone toTz){
    
    // THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument

      fTz = Calendar.getInstance().getTimeZone();     
      return ..
    
    }

복잡한 메서드에서 인수를 final로 표시하면 이러한 인수를 메서드 로컬 변수로 우연히 해석하는 데 도움이되고 컴파일러로 다시 할당하면 예제에 표시된대로 이러한 경우에 플래그가 지정됩니다.

2 익명의 내부 클래스에 인수 전달

공식 메소드 매개 변수는 지역 변수이므로 final로 선언 된 경우에만 내부 익명 클래스에서 액세스 할 수 있습니다.


1

-과거 (Java 8 이전 :-))

"final"키워드의 Explit 사용은 내부 익명 클래스에 대한 메서드 변수의 접근성에 영향을 미쳤습니다.

-최신 (Java 8+) 언어에서는 다음과 같은 용도로 사용할 필요가 없습니다.

Java는 "효과적으로 최종"변수를 도입했습니다. 코드가 변수 값 변경을 의미하지 않는 경우 로컬 변수 및 메서드 매개 변수는 최종적으로 간주됩니다. 따라서 Java8 +에서 이러한 키워드를 보면 불필요하다고 가정 할 수 있습니다. "효과적으로 최종"을 도입하면 람다를 사용할 때 코드를 적게 입력 할 수 있습니다.


0

계약을 정의하고 고수하는 데 도움이되는 Java의 구성 일뿐입니다. 비슷한 토론 : http://c2.com/cgi/wiki?JavaFinalConsideredEvil

BTW-(twiki가 말했듯이), 좋은 프로그래밍 원칙을 따르고 들어오는 인수 참조를 재 할당 / 재정의하는 경우 args를 final로 표시하는 것은 일반적으로 중복됩니다.

최악의 경우 args 참조를 재정의하면 참조 만 전달되었으므로 함수에 전달 된 실제 값에 영향을주지 않습니다.


0

일반적으로 변수와 필드를 최종적으로 표시하는 것에 대해 말하고 있습니다. 메소드 인수에만 적용되는 것이 아닙니다. (마킹 방법 / 클래스 final은 완전히 다른 것입니다).

코드의 독자 / 미래 유지 관리자에게 유리합니다. 현명한 변수 이름과 함께 문제의 변수가 무엇을 나타내는 지보고 이해하는 것은 코드 독자에게 도움이되고 안심할 수 있습니다. 동일한 범위에서 변수를 볼 때마다 의미가 유지된다는 것은 독자에게 안심입니다. 동일하므로 모든 상황에서 변수가 의미하는 바를 항상 파악하기 위해 머리를 긁을 필요가 없습니다. 변수의 "재사용"을 너무 많이 남용하여 짧은 코드 스 니펫도 이해하기 어렵게 만듭니다.


-3

final 키워드는 매개 변수에 새 값을 지정하지 못하게합니다. 간단한 예를 들어 설명하겠습니다.

방법이 있다고 가정합니다.

method1 () {

Date dateOfBirth = new Date ( "1/1/2009");

method2 (dateOfBirth);

method3 (dateOfBirth); }

public mehod2 (Date dateOfBirth) {
....
....
....
}

공개 mehod2 (Date dateOfBirth) {
....
....
....
}

위의 경우 "dateOfBirth"가 method2에 새 값이 할당되면 method3에서 잘못된 출력이 발생합니다. method3에 전달되는 값은 method2에 전달되기 전의 값이 아닙니다. 따라서이 최종 키워드를 방지하기 위해 매개 변수에 사용됩니다.

또한 이것은 Java Coding Best Practices 중 하나입니다.


5
그것은 옳지 않습니다. 인수 dateOfBirth가 method2 ()에서 다른 값으로 변경 되더라도 Java는 참조가 아닌 값으로 전달되기 때문에 method2 ()에는 영향을 미치지 않습니다.
— Flo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.