web-dev-qa-db-ja.com

Java決して参照渡しではありませんよね?...正しいですか?

重複の可能性:
Is Java“ pass-by-reference”?

今日、変わった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に属していますか?

43
Troy Nichols

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
}

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

103
Michael Myers

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

28
Rytmis

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

From Java How to Program、4th Edition by Deitel&Deitel:(pg。329)

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

大学でJava=を学ぶときにこの本を使用しました。素晴らしい参考文献です。

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

3
the_new_mr

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

2
Marc Gravell

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

1
PhiLho