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


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.