8

タイトルから明らかなように、どのアプローチを優先すべきでしょうか?

意図は、いくつかのメソッド パラメーターを渡し、出力として何かを取得することです。別のパラメーターを渡すことができ、メソッドはそれを更新し、メソッドは何も返す必要はありません。メソッドは出力変数を更新するだけで、呼び出し元に反映されます。

この例を通して質問を組み立てようとしています。

List<String> result = new ArrayList<String>();

for (int i = 0; i < SOME_NUMBER_N; i++) {
    fun(SOME_COLLECTION.get(i), result);
}

// in some other class
public void fun(String s, List<String> result) {
    // populates result
}

List<String> result = new ArrayList<String>();

for (int i = 0; i < SOME_NUMBER_N; i++) {
    List<String> subResult = fun(SOME_COLLECTION.get(i));
    // merges subResult into result
    mergeLists(result, subResult);
}

// in some other class
public List<String> fun(String s) {
    List<String> res = new ArrayList<String>();
    // some processing to populate res
    return res;
}

1 つはリファレンスを通過し、もう 1 つは通過しないことを理解しています。

(さまざまな状況で) どちらを優先する必要がありますか? また、その理由は?

更新:変更可能なオブジェクトについてのみ検討してください。

4

6 に答える 6

17

関数から値を返すことは、通常、コードを書くためのよりクリーンな方法です。値の受け渡しと変更は、ポインターの作成と破棄の性質上、より C/C++ スタイルです。

開発者は一般に、関数が値を変更すると明示的に述べていない限り、関数を介して値を渡すことによって値が変更されることを期待していません (とにかくドキュメントをざっと読むことがよくあります)。

ただし、例外もあります。

の例を考えてみましょうCollections.sort。これは実際にリストのその場での並べ替えを行います。100 万個のアイテムのリストを想像してみてください。あなたはそれを並べ替えています。別の 100 万エントリを含む 2 つ目のリストを作成したくない場合があります (これらのエントリが元のエントリを指している場合でも)。

また、不変オブジェクトを使用することをお勧めします。不変オブジェクトを使用すると、開発のほとんどの側面 (スレッド化など) で問題が発生することがはるかに少なくなります。したがって、新しいオブジェクトを返すことで、パラメーターを変更可能にする必要はありません。

重要な部分は、メソッドの意図を明確にすることです。パラメータの変更は、Java で最も一般的な動作ではないため、可能な限り避けることをお勧めします。

于 2012-05-01T20:58:23.810 に答える
7

あなたはそれを返す必要があります。あなたが提供した2番目の例は、行く方法です。

まず第一に、それはより明確です。他の人があなたのコードを読んだときに、パラメーターが出力として変更されていることに気付かない可能性はありません。変数に名前を付けることができますが、コードの読みやすさに関しては、その方が望ましいです。

渡すのではなく返す必要がある大きな理由は、不変オブジェクトを使用することです。 あなたの例であるリストは変更可能であるため、問題なく動作します。しかし、そのように String を使用しようとすると、うまくいきません。

文字列は不変であるため、文字列をパラメーターとして渡すと、関数は次のようになります。

public void fun(String result){
    result = "new string";
}

渡した結果の値は変更されません。代わりに、ローカル スコープ変数 'result' は fun 内の新しい文字列を指すようになりましたが、呼び出しメソッドの結果は元の文字列を指したままです。

電話した場合:

String test = "test";
fun(test);
System.out.println(test);

「新しい文字列」ではなく「テスト」と出力されます。

だから間違いなく、それは返すよりも優れています。:)

于 2012-05-01T20:59:07.103 に答える
1

私たちが理解していないと思う理由は、それらが 2 つのまったく異なるタイプのアクションだからです。関数に変数を渡すことは、関数にデータを与える手段です。関数からそれを返すことは、関数からデータを渡す方法です。

これら 2 つのアクションの違いを意味する場合:

public void doStuff(int change) {
    change = change * 2;
}

public void doStuff() {
    int change = changeStorage.acquireChange();
    change = change * 2;
}

次に、2 番目の方が一般的にクリーンですが、この方法でデータを渡すことができないいくつかの理由 (セキュリティ、関数の可視性など) があります。

また、コードの再利用が容易になるだけでなく、コードのモジュール化も容易になるため、好ましいと言えます。

于 2012-05-01T20:29:34.553 に答える
1

これは、ベスト プラクティスと独自のプログラミング方法に関するものです。これが 1 つの値を返す型の関数になることがわかっている場合は、次のようになります。

関数 IsThisNumberAPrimeNumber{ }

次に、これがブール値のみを返すことがわかります。私は通常、関数をヘルパー プログラムとして使用し、大きなサブ プロシージャとしては使用しません。また、サブ\関数が何を返すと期待するかを決定するのに役立つ命名規則も適用します。例:

GetUserDetailsRecords GetUsersEmailAddress IsEmailRegistered

これら 3 つの名前を見ると、1 つ目は複数のユーザー詳細レコードのリストまたはクラスを提供し、2 つ目はメールの文字列値を提供し、3 つ目はブール値を提供する可能性が高いことがわかります。名称が変われば意味も変わるので、これも合わせて考えればいいと思います。

于 2012-05-01T20:26:17.930 に答える
0

それを返すと、コードがきれいに保たれ、メソッド/クラス間の結合が少なくなります。

于 2012-05-01T20:24:08.790 に答える