2012-03-31 17 views
2

は、このコードを検討します。Javaの戻り参照値(または参照によって)

なぜですか?これはカプセル化に違反しませんか?価値によってそれを返す方法?

+0

のJavaでそれをラップする必要があります。あなたのコードがその事実を確認するだけです。それで、まさにあなたは何を返そうとしていますか? – Churk

+2

@Churk [Javaは参照渡しではありません](http://stackoverflow.com/q/40480/395760)!それが参照渡しだった場合、 'getPeople()= ...'が可能であり、メンバを別のArrayListを指すように変更します。引数を渡すためには、類似の逆の例が存在し、私がリンクしている質問で十数語で示されています(数十の重複はもちろんありません)。 – delnan

+0

@delnanのポイントを繰り返してみたい。 Javaでは、参照(基本的に)はオブジェクトへのポインタの値を渡しています* –

答えて

9

防衛的にプログラムする必要があります。たとえば、

public void addPerson(String personName) { 
    people.add(personName); 
} 
  • 戻り不変オブジェクトまたはA、代わりにリストに適用する方法を公開し、外部リストを公開しないでください

    • を検討するためのいくつかの選択肢があります。オブジェクトのコピー。例えば、
    public List<String> getPeople { 
        return new ArrayList<String>(people); 
    } 
    

    は限りなぜが行くように、それは既に他の記事で説明しています。 ArrayListの参照値が渡されます(値を変更しても元の参照は変更されません)。しかし、リスト自体には、オブジェクトに対する変更可能な参照が含まれています。 Javaは常に値渡しさ

3

  1. プリミティブ型の場合は、値を直接渡します。
  2. オブジェクトの場合、オブジェクト参照の値を渡します。

あなたのケースでは、参照オブジェクトの値を渡しています。オブジェクト参照。

1

getPeople()メソッドは、不変なビューまたはコピーを返す代わりにプライベートリストへの参照を返すため、ここでカプセル化に違反しています。あなたは簡単にこのメソッドを実装することによってこの問題を解決することができます:私はジョシュア・ブロックの優れた著書「効果的なJavaの(第2版)」を見てすることをお勧めします

public List<String> getPeople() { 
    return Collections.unmodifiableList(people); 
} 

、「項目39:必要なときに守備のコピーを作成します」。

1

不変性は魅力的ですが、防御的なコピーを作成する場合と同様に、高価になる可能性があります。標準のJavaコレクションは、不変のデータ構造として設計されたものではありません。あなたがJohanSjöbergが示唆しているように行くことができ、リストを公開しないといいですね。

しかし、このような高レベルのカプセル化を強制する必要がある理由も考慮する必要があります。クラスをパブリックAPIとして公開していますか?もしそうでなければ、あなたのクラスのクライアントをよく知っていれば、あまりにも多くのカプセル化は実用的ではありません。カプセル化/情報の隠蔽はセキュリティに関してはあまり意味がありませんが、簡潔で明白なAPIをクライアントに提示することについてはもっと重要です。

+0

Collections.unmodifiableList(people)は全く高価ではありません - 単純なラッパーです。 –

+0

はい、元のコレクションのビューです。オリジナルを変更するとビューに反映されます。あなたはそれがあなたが望むものであることを確かめるべきです。私はそれが守備的なコピーを作ることとは非常に異なることを意味します。 – nansen

0

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)

関連する問題