フィールドまたはクラスが final としてマークされていない不変オブジェクトがあります。私はこれを行うことができますが、これを行うメリットは本当にありますか? コンパイラが物事を理解するのに少し時間を節約できることがわかりましたが、それが「価値がある」とは思えません(将来の開発者がオブジェクトに何かをして変更可能にすることを再考させるという事実を除いて) .
4 に答える
あなたが指摘する点とは別に (将来の開発者がフィールドを変更することは非常に賢明なものであり、別の 1 つは、誰かがクラスをサブクラス化して可変にすることができるということです)、明示的にフィールドを final としてマークすると、マルチスレッド環境での可視性が保証されます。
このクラスを取ります - それは事実上不変です:
public class SomeClass {
private int i;
public SomeClass(int i) { this.i = i; }
public int getI() { return this.i; }
}
マルチスレッド環境では、スレッド T1 が を作成し、別のスレッド T2が 0 をSomeClass sc = new SomeClass(1);
読み込んで見ることができます。sc.getI()
を final にすると、これi
はもう起こりません (this
以下の引用で説明されているように、構築中に逃げさせないと仮定します)。
参照: JLS #17.5 - 強調鉱山
final フィールドを使用すると、プログラマーは同期なしでスレッドセーフな不変オブジェクトを実装することもできます。[...]
final フィールドの使用モデルは単純なものです。そのオブジェクトのコンストラクターでオブジェクトの final フィールドを設定します。オブジェクトのコンストラクターが終了する前に、別のスレッドが参照できる場所に構築中のオブジェクトへの参照を書き込まないでください。これに従えば、オブジェクトが別のスレッドから見られるとき、そのスレッドは常に、そのオブジェクトの final フィールドの正しく構築されたバージョンを認識します。
誰かが誤って変更可能にするのではなく、あなたの意図を示すのに役立ちます。
さらに、メソッドを final としてマークすると、インラインになり、パフォーマンスが向上する場合があります。
また、クラスの参照オブジェクトを としてマークするとfinal
、コンストラクターがアトミックになります。最後に、クラスをfinal
継承を停止するようにマークします。これはあなたが必要とするものですか?
フィールドを作成するということは、コードの意図final
を示すことです。
getter メソッドを作成しない限りfinal
、クラスは不変ではありません。検討:
public class MyClass {
private final int num;
public int getNum() {
return num;
}
}
public class MySubClass extends MyClass {
private int num;
public int getNum() {
return num;
}
public void setNum(int i) {
num = i;
}
}
サブクラスはフィールドを完全にオーバーライドし、変更可能にしました。セッターにアクセスするには、 toMyClass
のインスタンスをキャストするだけです。MySubClass
セッターがなくても、サブクラスはnum
別のメソッドでそのフィールドを変更できます。
フィールドがプライベートであると仮定すると、フィールドが であるかどうかは問題ではありませんfinal
: クラスを作成するかfinal
、ゲッターを作成する必要がありますfinal
。
また、好きなコード保護をすべて使用しても、リフレクションを使用すると、他のクラスがすべてを切り抜けてフィールドを変更する可能性があることに注意してください。
まず、final
フィールドはクラスとは大きく異なりfinal
ます。最終フィールドは変更できません。クラスのfinal
修飾子は、他のクラスがそのクラスから継承することを許可されていないことを意味しますが、フィールドにはまったく影響しません。
そうは言っても、フィールドが final とマークされていると、コンパイラは実際にいくつかの最適化を行うことができます。それらの影響の大きさは大きく異なります。プログラムにパフォーマンスの問題がない場合は、おそらく価値がありません。
しかし、設計の観点から、最終的なものを意図している場合に最終的なマークを付けることは有用であるため、クラスを使用している誰もが誤って何かを壊すことはありません。したがって、全体として、設計上後で変更したくないものがある場合は、それを最終的なものにしてください。