인터페이스 메소드의 최종 인수-요점은 무엇입니까?


189

Java에서는 final인터페이스 메소드에서 인수 를 정의 하고 구현 클래스에서 인수 를 정의 하지 않는 것이 합법적입니다 .

public interface Foo {
    public void foo(int bar, final int baz);
}

public class FooImpl implements Foo {

    @Override
    public void foo(final int bar, int baz) {
        ...
    }
}

위의 예에서 barbaz반대의 보유 final인터페이스 VS 클래스의 정의.

같은 방식으로 final한 클래스 메소드가 다른 클래스 메소드를 다른 클래스 메소드로 확장 할 때 제한이 적용 abstract되지 않습니다.

반면 final클래스 방법 본체 내부의 실제 값을 가지고, 특정 포인트가 어떤 final인터페이스 방법 매개 변수는?


final어쨌든 네이티브 유형은 복사되기 때문에 아무것도하지 않습니다.
Paul Tomblin

11
토론의 요점으로 방금 시도해 보았으며 두 가지 interface정의 final가 인수 의 속성 에서만 다를 경우 결과 .class파일은 바이트 단위로 동일합니다 (물론 javap -v동일한 출력을 생성합니다). 그건 final그렇고, 속성 만 다른 두 클래스에 대해서도 마찬가지입니다 !
Joachim Sauer

2
@Paul : 참조 타입과 똑같은 일을한다 : 인수 자체가 수정되는 것을 막는다 (구현에서 사용되는 경우).
Joachim Sauer

메소드 서명에서 일반인과 관련성이 큽니다.
Robin

2
@Deepak : 이해가되지 않더라도 모든 종류의 질문에 대한 실례를 요구하는 것을 보았습니다. 추상적 인 사고를 배워야한다고 생각 합니다. 앞에 실행 코드 가 없어도 문제에 대해 생각해보십시오 . 장기적으로 도움이 될 것입니다.
Joachim Sauer

답변:


104

요점이없는 것 같습니다. Java 언어 사양 4.12.4 에 따르면 :

변수 final을 선언하면 값이 변경되지 않으며 프로그래밍 오류를 피할 수 있다는 유용한 문서로 사용할 수 있습니다.

그러나 final메서드 매개 변수 의 수정자는 재정의 된 메서드의 서명을 일치 시키는 규칙에 언급되어 있지 않으며 구현 본문 내에서만 호출자에게 영향을 미치지 않습니다. 또한 주석에서 Robin이 언급 한 것처럼 final메소드 매개 변수 의 수정자는 생성 된 바이트 코드에 영향을 미치지 않습니다. (이것은 다른 용도로는 적용되지 않습니다 final.)


메소드 매개 변수도 변수로 규정됩니까? 분명히 실제로 있지만 사양 컨텍스트에 있습니까?
mindas

11
실제 .class 파일에 표시되지 않으므로 서명을 일치시키는 데 사용할 수 없습니다. 컴파일러 전용입니다.
Robin

@ mindas-JLS는 7 가지 변수 가 있다고 말합니다 . 메소드 매개 변수는 목록에서 네 번째입니다.
Ted Hopp

3
그러나 final수정자는 구현 클래스에 적용되지 않으므로 문서는 쓸모 가 없습니다. 당신의 인터페이스 서명은 단순히 거짓말 일 수 있습니다.
Stefan Haberl

Java 8 언어 사양에 따르면 8 가지 변수 가 있다고 합니다 (7 개에서 람다 매개 변수 추가 ). 메소드 매개 변수는 여전히 목록에서 네 번째입니다 (적어도 일부는 안정적으로 보입니다. :-)).
Ted Hopp

25

일부 IDE는 서브 클래스에 구현 메소드를 삽입 할 때 추상 / 인터페이스 메소드의 서명을 복사합니다.

컴파일러와 차이가 있다고 생각하지 않습니다.

편집 : 과거에는 이것이 사실이라고 생각하지만 현재 IDE가 더 이상 이것을하지 않는다고 생각합니다.


2
이 기능을 구현할 때 IDE가 많지 않다고 생각하지만 (
mindas

2
나는 static transient분야 의 범주에 있다고 생각 합니다. ;)
Peter Lawrey

1
그리고 추상 클래스의 공개 생성자.
Peter Lawrey

1
IntelliJ가이 작업을 수행합니다. 내 버전은 IntelliJ IDEA 2016.1.3 빌드 # IU-145.1617입니다.
Dormouse

1
@Dormouse, Android Studio (3.1.4 Build # AI-173.4907809)가하지 않기 때문에 흥미 롭습니다 :(
The Godfather

18

메소드 매개 변수의 최종 주석은 항상 호출자에게 절대로 메소드 구현과 관련이 없습니다. 따라서 인터페이스 메소드 시그니처에 사용할 이유가 없습니다. 모든 메서드 시그니처에서 최종 메서드 매개 변수가 필요한 동일한 일관된 코딩 표준을 따르지 않는 한. 그러면 그렇게 할 수있어서 좋습니다.


6

업데이트 : 아래의 원래 답변은 질문을 완전히 이해하지 않고 작성되었으므로 질문을 직접 해결하지는 못하지만 키워드 :)의 일반적인 사용법을 이해하려는 사람들에게는 유익해야합니다 final.

질문에 대해서는 아래에서 내 의견을 인용하고 싶습니다.

나는 당신이 자신의 구현에서 최종적인 것인지 아닌지를 자유롭게 결정할 수 있도록 논쟁의 최종성을 구현해서는 안된다고 생각합니다 .

그러나 그렇습니다 final. 인터페이스에서 선언 할 수는 있지만 구현에서 최종적이지 않은 것은 다소 이상하게 들립니다 . 다음 중 하나에 해당하면 더 의미가있을 것입니다.

ㅏ. final인터페이스 (추상) 메소드 인수에 키워드가 허용되지 않았지만 (구현에 사용할 수 있음)
b. final인터페이스에서 와 같이 인수를 선언하면 final구현 에서 인수를 선언 해야하지만 (최종이 아닌 경우에는 적용되지 않음)


메소드 서명이 final매개 변수 를 가질 수있는 두 가지 이유를 생각할 수 있습니다 : Beans and Objects ( 실제로 그들은 같은 이유이지만 약간 다른 컨텍스트입니다. )

사물:

public static void main(String[] args) {
    StringBuilder cookingPot = new StringBuilder("Water ");
    addVegetables(cookingPot);
    addChicken(cookingPot);
    System.out.println(cookingPot.toString());
    // ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth 
    //      We forgot to add cauliflower. It went into the wrong pot.
}

private static void addVegetables(StringBuilder cookingPot) {
    cookingPot.append("Carrot ");
    cookingPot.append("Broccoli ");
    cookingPot = new StringBuilder(cookingPot.toString());
    //   ^--- Assignment allowed...
    cookingPot.append("Cauliflower ");
}

private static void addChicken(final StringBuilder cookingPot) {
    cookingPot.append("Chicken ");
    //cookingPot = new StringBuilder(cookingPot.toString());
    //     ^---- COMPILATION ERROR! It is final.
    cookingPot.append("ChickenBroth ");
}

final키워드는 우리가 실수로 새 생성되지 않습니다 보장 현지 우리가 그렇게 할 시도 할 때 컴파일 오류를 보여줌으로써 요리 냄비를. 이를 통해 닭 국물이 addChicken방법이 얻은 원래 요리 냄비에 추가됩니다 . addVegetables콜리 플라워를 잃어버린 곳 과 원래의 냄비 대신 새로운 지역 요리 냄비에 추가했기 때문에 이것을 비교하십시오 .

Beans : 객체와 동일한 개념입니다 (위 그림 참조) . 콩은 본질적 Object으로 Java에 있습니다. 그러나 Bean (JavaBeans)은 정의 된 관련 데이터 콜렉션을 저장하고 전달하는 편리한 방법으로 다양한 애플리케이션에서 사용됩니다. addVegetables새로운 요리 냄비를 만들어 StringBuilder콜리 플라워로 버려 요리 과정을 망칠 수있는 것처럼 요리 냄비 JavaBean으로도 같은 작업을 수행 할 수 있습니다 .


확인. 인터페이스에 대한 구현이 최종 인수를 취하도록 강요하지 않기 때문에 실제로 질문에 대한 정답은 아니지만, 이유에 대한 훌륭한 설명이므로 여전히 도움이됩니다. 메소드 매개 변수를 최종으로 설정하는 것이 좋습니다.
Phil

나는 당신이 자신의 구현에서 최종적인 것인지 아닌지를 자유롭게 결정할 수 있도록 논쟁의 최종성을 구현하도록 강요받지 않았다고 생각합니다 . 그러나 그렇습니다 final. 인터페이스에서 선언 할 수는 있지만 구현에서 최종적이지 않은 것은 다소 이상하게 들립니다 . 어느 경우가 더 의미가 만든 것 (a)는 final 키워드가 인터페이스 (추상) 메소드 인수에 허용되지 않은 (그러나 당신이 구현에서 사용할 수 있습니다), 또는 (b)는 같은 인수 선언 final을 강제 인터페이스가 선언 될 final구현 (최종 결승에는 적용되지 않습니다).
ADTC

"정말 질문에 대한 정답 은 아닙니다. " 당신 말이 맞아, 내가 무슨 생각을했는지 모르겠다. :)
ADTC

2

나는 그것이 세부 사항인지 아닌지에 대한 세부 사항 일 수 있다고 생각합니다. 구현 세부 사항입니다.

(공개로 인터페이스에서 메소드 / 멤버를 선언하는 것과 같습니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.