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) {
...
}
}
上記の例では、bar
とbaz
には、クラスVSインターフェイスの反対のfinal
定義があります。
同様に、あるクラスメソッドが別のクラスメソッドを拡張する場合、final
の有無にかかわらず、abstract
の制限は適用されません。
final
にはクラスメソッド本体内に実用的な値がありますが、インターフェイスメソッドのパラメーターにfinal
を指定するポイントはありますか?
それには何の意味もないようです。 Java Language Specification 4.12.4 によると:
変数finalを宣言することは、その値が変わらず、プログラミングエラーの回避に役立つという有用なドキュメントとして役立ちます。
ただし、メソッドパラメーターのfinal
修飾子は、オーバーライドされたメソッドの 署名の一致の規則 には記載されておらず、呼び出し元には影響せず、実装の本体内でのみ有効です。 。また、コメントでロビンが述べたように、メソッドパラメーターのfinal
修飾子は、生成されたバイトコードには影響しません。 (これはfinal
の他の用途には当てはまりません。)
一部のIDEは、サブクラスに実装メソッドを挿入するときに、抽象/インターフェイスメソッドのシグネチャをコピーします。
コンパイラーに違いをもたらすとは思わない。
編集:これは過去に真実だったと思うが、現在のIDEはこれをこれ以上しないと思う。
メソッドパラメータの最終的な注釈は、常に呼び出し側ではなくメソッド実装にのみ関連します。したがって、インターフェイスメソッドシグネチャでそれらを使用する本当の理由はありません。すべてのメソッドシグネチャで、最終メソッドパラメータを必要とする同じ一貫したコーディング標準に従う必要がある場合を除きます。そうすることができて嬉しいです。
更新:以下の元の回答は質問を完全に理解せずに書かれたため、質問に直接対処しません:)
とはいえ、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のObject
sです。ただし、Bean(JavaBeans)は、関連するデータの定義済みコレクションを格納して渡す便利な方法として、さまざまなアプリケーションで使用されます。 addVegetables
が新しい調理鍋StringBuilder
を作成してカリフラワーと一緒に捨てることで調理プロセスを台無しにできるように、調理鍋でも同じことができますJavaBean。
最終であるかどうかは実装の詳細であるため、それは余分な詳細である可能性があります。
(インターフェースのメソッド/メンバーをパブリックとして宣言するようなものです。)