53

重複の可能性:
Java は「参照渡し」ですか?

今日、珍しい Java メソッドを見つけました。

private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
     if (null == vsName)
       vsName = "";
     else
       vsName = vsName.trim();
     String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
     //SCR10638 - Prevent export of empty rows.
     if (shortenedVoiceSetName.length() > 0)
     {
       if (!voiceSetList.contains("#" + shortenedVoiceSetName))
         voiceSetList.add("#" + shortenedVoiceSetName);
     }
}

変数、複雑なオブジェクトを渡すかどうかにかかわらず、Java の動作について読んだすべてのことによると、このコードはまったく何もしないはずです。ええと...ここで何か足りないのですか?私には見落とされた微妙な点がありますか、それともこのコードはthedailywtfに属していますか?

4

6 に答える 6

111

Rytmis が言ったように、Java は参照を値で渡します。これが意味することは、メソッドのパラメーターで変更メソッドを合法的に呼び出すことはできますが、それらを再割り当てして値が伝播することを期待することはできないということです。

例:

private void goodChangeDog(Dog dog) {
    dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
    dog = new StBernard(); // compiles, but has no effect outside the method
}

編集:この場合、これが意味することは、このメソッドの結果として変更されるvoiceSetList 可能性がありますが(新しい要素が追加される可能性があります)、への変更vsNameはメソッドの外では見えないということです。混乱を避けるために、私はよくメソッド パラメーター をマークfinalします。これにより、2 番目の例がまったくコンパイルされなくなります。

于 2009-04-27T20:36:51.593 に答える
32

Java は参照を値で渡すため、参照のコピーを取得しますが、参照されるオブジェクトは同じです。したがって、このメソッドは入力リストを変更します。

于 2009-04-27T20:32:25.067 に答える
4

参照自体は値によって渡されます。

Deitel & Deitel による Java How to Program、第 4 版から: (pg. 329)

他の言語とは異なり、Java ではプログラマーが各引数を値で渡すか参照で渡すかを選択できません。プリミティブ データ型変数は常に値渡しされます。オブジェクトはメソッドに渡されません。むしろ、オブジェクトへの参照はメソッドに渡されます。参照自体は値によって渡されます。つまり、参照のコピーがメソッドに渡されます。メソッドがオブジェクトへの参照を受け取ると、メソッドはオブジェクトを直接操作できます。

大学でJavaを学ぶときにこの本を使いました。素晴らしいリファレンス。

ここにそれを説明する良い記事があります。 http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

于 2011-11-03T14:46:13.510 に答える
2

オブジェクトである - を操作できArrayListます... オブジェクト参照を渡す場合 (値渡しであっても)、そのオブジェクトへの変更は呼び出し元に反映されます。それが質問ですか?

于 2009-04-27T20:33:16.157 に答える
1

vsName が変更されているため、混乱していると思います。ただし、このコンテキストでは、これは単なるローカル変数であり、shortedVoiceSetName とまったく同じレベルです。

于 2009-04-27T20:51:02.200 に答える
-3

コード内の正確な質問が何であるかは明確ではありません。Java は値渡しですが、配列はオブジェクトを渡さず、ポインターのみを渡すため、参照渡しです。配列は、実際のオブジェクトではなく、ポインターで構成されます。これにより、非常に高速になりますが、取り扱いが危険になります。これを解決するには、それらを複製してコピーを取得する必要があります。それでも、配列の最初の次元のみが複製されます。

詳細については、私の回答を参照してください: Java では、浅いコピーとは何ですか? (私の他の回答も参照してください)

ところで、配列はポインタにすぎないため、いくつかの利点があります。配列を同期オブジェクトとして (ab) 使用できます。

于 2012-10-20T12:34:50.547 に答える