わかりやすくするために、クラスを final にすると、サブクラス化されなくなります。これは、クラスをさらに洗練する必要がない場合に適しています。
クラス レベルの変数を final としてマークするということは、一度だけ割り当てられることを意味します。プリミティブと文字列のような不変オブジェクトの場合、これには変数が不変になるという副作用があります (デフォルトで)。
ただし、Date のような変更可能なオブジェクトの場合、変数は常に同じインスタンスを参照しますが、そのインスタンスにアクセスできる他のユーザーは、その状態を変更することができます。たとえば、メソッドがあった場合
public Date getCreatedDate(){
return this.created; // class variable declared as private final Date created...;
}
その後、任意の呼び出し元が作成されたインスタンスにアクセスし、その状態を変更できます。真に不変の値のみを返すか、クローンを返す方がよいでしょう。
public Date getCreatedDate(){
return this.created.clone();
}
編集
「値を変更する唯一の方法が新しいインスタンスを作成することであることを確認するために、不変データ モデル クラスを final としてマークしました。」
私が理解している問題は、クラス A がクラス B に依存していることです。クラス A をテストしたいのですが、クラス B を最終としてマークしたため、クラス B をモックできません。クラス B を final としてマークして、不変にしました (内部状態が変更されないようにします)。クラスを final とマークすると、サブクラス化できなくなるため、これは正しくありません。インスタンスの内部状態を変更する機能とは関係ありません。
final を使用しても、望ましい効果はありません。フィールドを最終としてマークすることはオプションではなく、上記の理由でクラスを不変にすることはありません。データを保護する唯一の方法は、データのクライアントが、データの内部状態を構成するオブジェクトにアクセスできないようにすることです。
あなたが唯一の開発者ではないと仮定すると、意図しない更新からデータのユーザーを保護する必要があります。getter から確実にクローンを返すことは、1 つの方法です。チーム メンバーがサブクラスを作成してデータを変更するのは、プログラミングが悪いだけであり、意図的ではなく、ポリシーとコードのレビューによって管理できます。
未知の開発者による外部干渉からコードを保護したい場合 (たとえば、同じ名前空間を使用してコードを挿入するコードを作成する場合)、パッケージ シーリングなどの他のアプローチを利用できます。