答えて
防衛的にプログラムする必要があります。たとえば、
public void addPerson(String personName) {
people.add(personName);
}
- 戻り不変オブジェクトまたはA、代わりにリストに適用する方法を公開し、外部リストを公開しないでください
- を検討するためのいくつかの選択肢があります。オブジェクトのコピー。例えば、
public List<String> getPeople { return new ArrayList<String>(people); }
は限りなぜが行くように、それは既に他の記事で説明しています。
ArrayList
の参照値が渡されます(値を変更しても元の参照は変更されません)。しかし、リスト自体には、オブジェクトに対する変更可能な参照が含まれています。 Javaは常に値渡しさ
:
- プリミティブ型の場合は、値を直接渡します。
- オブジェクトの場合、オブジェクト参照の値を渡します。
あなたのケースでは、参照オブジェクトの値を渡しています。オブジェクト参照。
getPeople()メソッドは、不変なビューまたはコピーを返す代わりにプライベートリストへの参照を返すため、ここでカプセル化に違反しています。あなたは簡単にこのメソッドを実装することによってこの問題を解決することができます:私はジョシュア・ブロックの優れた著書「効果的なJavaの(第2版)」を見てすることをお勧めします
public List<String> getPeople() {
return Collections.unmodifiableList(people);
}
、「項目39:必要なときに守備のコピーを作成します」。
不変性は魅力的ですが、防御的なコピーを作成する場合と同様に、高価になる可能性があります。標準のJavaコレクションは、不変のデータ構造として設計されたものではありません。あなたがJohanSjöbergが示唆しているように行くことができ、リストを公開しないといいですね。
しかし、このような高レベルのカプセル化を強制する必要がある理由も考慮する必要があります。クラスをパブリックAPIとして公開していますか?もしそうでなければ、あなたのクラスのクライアントをよく知っていれば、あまりにも多くのカプセル化は実用的ではありません。カプセル化/情報の隠蔽はセキュリティに関してはあまり意味がありませんが、簡潔で明白なAPIをクライアントに提示することについてはもっと重要です。
Collections.unmodifiableList(people)は全く高価ではありません - 単純なラッパーです。 –
はい、元のコレクションのビューです。オリジナルを変更するとビューに反映されます。あなたはそれがあなたが望むものであることを確かめるべきです。私はそれが守備的なコピーを作ることとは非常に異なることを意味します。 – nansen
Javaは基本的には「値渡し」ですが、実際には「基準値渡し」という意味ではありません。 Javaタイプ(JVMのクラス市民、非プリミティブ型)を扱う場合、基本的に次のような宣言は、タイプMyClass
の参照referenceToMyObject
のコピーを取得し、同じ特定のMyClass
オブジェクトを指し示すことを意味しますJVMヒープ・メモリー内のインスタンス。
public class SomeClass {
private MyClass referenceToMyClassInstance = new MyClass("instanceId-1");
public MyClass getMyClassInstance() {
return referenceToMyClassInstance;
}
}
だからあなたの例では、基本的には同じArrayList
インスタンスへの参照ポインティングのコピーを取得し、getPeople()
と呼ばれ、誰もが今、とにかく実際のインスタンスを変更することができます、彼/彼女はおそらく状態をカプセル化しなければならないものを破壊し、好き。
だから、ArrayListののコピーを返すか、オブジェクトに来るときは常に参照渡しされる変更不可能なデコレータCollections.unmodifiableList(people)
- 1. MEL duplicate参照戻り値?
- 2. のJava:によって値パスまたは参照渡し
- 3. CPP戻り参照
- 4. C++参照戻り
- 5. 関数の戻り値への参照
- 6. は値によって、参照により両方が
- 7. 値によって戻り値がconst参照に割り当てられました
- 8. NULLポインタの逆参照による参照の割り当て
- 9. 参照または値による変数? Java
- 10. 参照によるディクショナリ値
- 11. 尖った間接参照のC++および参照としての機能に渡すは、値が
- 12. Javaワイルドカード参照
- 13. TextInputは参照によって値を取得します。
- 14. パターンへの参照と逆参照された値との照合に違いはありますか?
- 15. rvalue参照でより効率的に戻っていますか?例えば
- 16. 参照用の後続戻り型
- 17. Javaでの参照
- 18. 値または参照によって返されるgolangマップ値?
- 19. Java - オブジェクト参照または識別子?
- 20. Excel - 参照内の参照
- 21. 参照によってデータメンバーを渡す
- 22. 参照によってベクトルを渡す
- 23. 値で参照渡しのPHPUnitテスト関数と戻り値
- 24. ハッシュテーブルget関数からの戻り値は参照ですか?
- 25. golangマップは値または参照によって検索されますか?
- 26. 戻りconst参照と一時オブジェクト
- 27. l値参照とr値参照におけるバインディングエラー
- 28. PHPは参照によってクラスメンバーを設定しました
- 29. Java循環参照
- 30. Java:参照とGC
のJavaでそれをラップする必要があります。あなたのコードがその事実を確認するだけです。それで、まさにあなたは何を返そうとしていますか? – Churk
@Churk [Javaは参照渡しではありません](http://stackoverflow.com/q/40480/395760)!それが参照渡しだった場合、 'getPeople()= ...'が可能であり、メンバを別のArrayListを指すように変更します。引数を渡すためには、類似の逆の例が存在し、私がリンクしている質問で十数語で示されています(数十の重複はもちろんありません)。 – delnan
@delnanのポイントを繰り返してみたい。 Javaでは、参照(基本的に)はオブジェクトへのポインタの値を渡しています* –