ArrayListのConst Referenceを返します
-
27-09-2019 - |
質問
私は本当にJavaの機能を賞賛しており、次の問題のためにそれを使ってあきらめたくありません。
私は継承されるかもしれないクラスを持っています、そしてその内部は private ArrayList arr;
したがって、セッター機能は大丈夫ですが、ゲッター関数 return arr;
私が望んでおらず、プライベートではないその配列全体を編集できる人なら誰でも意味をなさない変数への参照を返します!
C ++では、私はちょうどそうします return const arr;
また、変数への一定の参照を返します。
変数をクローン化したり手動でコピーしたりしないように変数を必要とします。コピーを逃れる方法はありますか?
詩 (final ArrayList<Integer> arr;)
アレイが常にサイズまたは要素の値を変更するというオプションではありません。
私がC ++に戻ったり、すべてを公開したりすると脅していることの修正が見つからなかった場合、あなたは私のソフトウェアを取得しないでください:D
編集:もう1つの重要な質問:私は良くないことを求めていますか(ソフトウェアエンジニアリングワイズ)私は、Javaの作成者がconstリファレンスを持っていないと考えた場合(読み取り専用参照)、他の人で処理できるものを求めなければなりません仕方。または、私のプログラムのデザインが間違っています。私はとても混乱しています。
解決
リターン値をで包みます java.util.collections.unmodifiablelist. 。データのコピーを作成するのではなく、元のリストをラップし、読み取り専用の操作を基礎とするリストに代表します。リストを変更する操作は、実行時に拒否されます UnsupportedOperationException
.
あなたの
return arrayList;
なります
return Collections.unmodifiableList(arrayList);
残念ながら、読み取り専用の制約はコンパイラによって実施されません。ただし、実行時に実施されます。
あなたはあなたにも利用できます: unmodifiableset, unmodifiablemap, unmodifiablecollection, unmodifiablesortedset, 、 と unmodifiablesortedMap. 。これらが十分でない場合でも、この一般的なデザインアプローチからインスピレーションを得て、独自のカスタムリード専用ラッパークラスを作成できます。
他のヒント
:)いくつかのオプションがあります:
ゲッターを公開しないで、呼び出すことが許可されている方法のみを提供しないでください。
public void addToList(Object arg) { this.arr.add(arg);}
不変のオブジェクトを返す:
public List getArr() { return Collections.unmodifiableList(this.arr); }
使用することもできます Google Guava不変です コレクション. 。この場合、保存します ImmutablELIST あなたの分野で。
もちろん、クラスがこのリストを内部的に変更する必要がある場合は、ImmutablEListを使用して そうかもしれない 新しいImmutableListインスタンスを作成し、毎回フィールドに再割り当てする必要があるため、悪い考えであることが判明します...
しかし、オブジェクトの構築後にリストが変更されないことがわかっている場合、それは完璧です。
不変の例(オブジェクトの構築後にリストは変更されません)
@Immutable
public final class Foo {
@Nonnull
private final ImmutableList<String> list;
public Foo(@Nonnull List<String> list) {
// you could also compute the appropriate list here
// before assigning it to the field
this.list = ImmutableList.copyOf(list);
}
public ImmutableList<String> getList() {
return list;
}
}
可変例(リストは、セッターを使用してのみ変更できます)
public class Foo {
@Nonnull
private ImmutableList<String> list = ImmutableList.of();
public ImmutableList<String> getList() {
return list;
}
public void setList(@Nonnull List<String> list) {
this.list = ImmutableList.copyOf(list);
}
}
備考
- メソッドに可能な限り最も一般的なタイプを返すようにすることがよくあることを知っています(
List
この場合)、しかし、私はゲッターの返品タイプをImmutableList
, 、それはドキュメントとして機能するため(Javadocでの返されたリストの不変性を文書化する必要はありません)、およびAPI契約として。 「私 保証 このリストは不変であるために、それを心配したり防御的にコピーする必要はありません。」そしてそれは非常に簡潔です。 ImmutableList.copyOf()
それは自動的にnullリストを拒否するので素晴らしいです(投げることによってNullPointerException
)。また、ヌル要素を拒否します。また、ソースリストがすでにオブジェクトのインスタンス化を回避するのを避けている場合、ソースリストをコピーしません。- 2番目の例では、フィールドを初期化して空のオムサブリストに使用して
ImmutableList.of()
, 、null値の代わりに空のコレクションを返すのは良い習慣だからですnullオブジェクトパターン)。これにより、不必要なオブジェクトのインスタンスが作成されると思うかもしれませんが、ImmutableList.of()
実際にシングルトンを返します。
Unmodifiablelistメソッドに代わるものがあります。このプライベート配列のコピーを返すだけです。例えば、
return your_private_array.clone();
まあ、これにはパフォーマンスのペナルティがあるかもしれません。ただし、変更されていないインターフェイスがあります(まだ配列を返します)。
Unmodifiablelist 間違いなく答えです。