web-dev-qa-db-ja.com

インターフェースメソッドの最後の引数-ポイントは何ですか?

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には、クラスVSインターフェイスの反対のfinal定義があります。

同様に、あるクラスメソッドが別のクラスメソッドを拡張する場合、finalの有無にかかわらず、abstractの制限は適用されません。

finalにはクラスメソッド本体内に実用的な値がありますが、インターフェイスメソッドのパラメーターにfinalを指定するポイントはありますか?

182
mindas

それには何の意味もないようです。 Java Language Specification 4.12.4 によると:

変数finalを宣言することは、その値が変わらず、プログラミングエラーの回避に役立つという有用なドキュメントとして役立ちます。

ただし、メソッドパラメーターのfinal修飾子は、オーバーライドされたメソッドの 署名の一致の規則 には記載されておらず、呼び出し元には影響せず、実装の本体内でのみ有効です。 。また、コメントでロビンが述べたように、メソッドパラメーターのfinal修飾子は、生成されたバイトコードには影響しません。 (これはfinalの他の用途には当てはまりません。)

96
Ted Hopp

一部のIDEは、サブクラスに実装メソッドを挿入するときに、抽象/インターフェイスメソッドのシグネチャをコピーします。

コンパイラーに違いをもたらすとは思わない。

編集:これは過去に真実だったと思うが、現在のIDEはこれをこれ以上しないと思う。

23
Peter Lawrey

メソッドパラメータの最終的な注釈は、常に呼び出し側ではなくメソッド実装にのみ関連します。したがって、インターフェイスメソッドシグネチャでそれらを使用する本当の理由はありません。すべてのメソッドシグネチャで、最終メソッドパラメータを必要とする同じ一貫したコーディング標準に従う必要がある場合を除きます。そうすることができて嬉しいです。

17
jmg

更新:以下の元の回答は質問を完全に理解せずに書かれたため、質問に直接対処しません:)とはいえ、finalキーワードの一般的な使用法を理解したい人には参考になるはずです。

質問に関しては、下から自分のコメントを引用したいと思います。

自分の実装でfinalであるかどうかを自由に決定できるようにするために、引数の最終性を実装する必要はありません。

しかし、はい、インターフェースでfinalを宣言できるが、実装ではnon-finalにすることができます。次のいずれかの場合、より意味があります。

a。finalキーワードは、インターフェイス(抽象)メソッドの引数には使用できません(ただし、実装で使用できます)。または
b。インターフェイスでfinalとして引数を宣言すると、実装でfinalとして宣言されます(ただし、非ファイナルでは強制されません)。


メソッドシグネチャがfinalパラメーターを持つことができる2つの理由を考えることができます:Beansおよび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キーワードにより、新しいlocalクッキングポットを作成しようとしてコンパイルエラーが表示されることにより、誤って作成されないようにしました。これにより、addChickenメソッドが取得した元の調理鍋に鶏肉スープが確実に追加されます。これを、カリフラワーを失ったaddVegetablesと比較してください。カリフラワーは、元の鍋ではなく、新しいlocal調理鍋に追加されたためです。

Beans:これはオブジェクトと同じ概念です(上記のとおり)。 Beanは基本的にJavaのObjectsです。ただし、Bean(JavaBeans)は、関連するデータの定義済みコレクションを格納して渡す便利な方法として、さまざまなアプリケーションで使用されます。 addVegetablesが新しい調理鍋StringBuilderを作成してカリフラワーと一緒に捨てることで調理プロセスを台無しにできるように、調理鍋でも同じことができますJavaBean

6
ADTC

最終であるかどうかは実装の詳細であるため、それは余分な詳細である可能性があります。

(インターフェースのメソッド/メンバーをパブリックとして宣言するようなものです。)

2
Peter