3

メソッドから複数の値を返すために 1 要素の配列を使用していることに気付くことがあります (実際にはよくあることです)。このようなもの:

public static int foo(int param1, int param2[], String param3[])
{
    // method body
    ....
    // set return values
    param2[0] = <some value>;
    param3[0] = <some value>;

    return <some value>;
}

これは悪い習慣ですか?(私の友人の何人かが、2 秒間何をしているのかわからなかったと言ったからのようです!) しかし、そもそも私がこれを使用した理由は、これがpass-by-referenceC++ で知られているものに最も近いように見えたからです。そして、練習は に落胆しなかったC++ので...

しかし、これが本当に間違った方法である場合、これをきれいに書き直す方法はありますか?

ありがとう

4

7 に答える 7

6

返すデータを含むオブジェクトを作成します。

次に、そのオブジェクトのインスタンスを返すことができます。

class FooData {
    private int someInt;
    private int anotherInt;
    private String someString;

    public FooData(int a, int b, String c) {
        someInt = a;
        anotherInt = b;
        someString = c;
    }
}

public FooData foo() {
    // do stuff
    FooData fd = new FooData(blah, blahh, blahhh);
    return fd;
}
于 2013-02-11T20:21:56.253 に答える
5

このような目的で配列を使用することは悪い習慣であるという一般的な意見に同意しますが、いくつか追加したいと思います。そもそも「参照渡し」が本当に必要なものだと確信していますか?多くの人があなたのコードは悪いスタイルだと言っていますが、それが私見である理由をお話ししましょう。「参照渡し」は、ほとんどの場合、「副作用によるプログラミング」の同義語であり、常に避けたいものです。これにより、コードのデバッグと理解がはるかに困難になります。マルチスレッド環境では、この態度の悪影響が実際に大きな打撃を与える可能性があります。Javaでスケーラブルでスレッドセーフなコードを作成するには、オブジェクトを可能な限り「読み取り専用」にする必要があります。つまり、オブジェクトの作成と初期化を同時に行い、アプリケーション全体でこの変更不可能な状態で使用するのが理想的です。 。状態への論理的な変更は、ほとんどの場合、新しい状態の「作成」と見なすことができます。つまり、状態に初期化されてから必要になる新しいインスタンスの作成です。最新のスクリプト言語の多くは、この方法でしか作業できず、理解しやすくなっています。C ++とは対照的に、Javaは短命のオブジェクトの割り当てと解放においてはるかに効率的であるため、他の人が提案したことには実際には何の問題もありません。目的のためだけに、関数の結果を保持する特別なクラスのインスタンスを作成する結果を返します。ループでそれを行ったとしても、JVMはそれを効率的に処理するのに十分賢いでしょう。Javaは、必要な場合にのみOSから非常に大きなチャンクでメモリを割り当て、C / C ++などの言語に伴うオーバーヘッドなしに、オブジェクトの作成と解放を内部的に処理します。「」

編集:このフォーラムまたはネットで「副作用」、「関数型プログラミング」、「不変性」という用語を検索することをお勧めします。これはおそらくあなたの質問に新しい視点を開くでしょう。

于 2013-02-11T21:12:10.367 に答える
4

メソッドへのパラメーターである 1 要素の配列を使用して値を「返す」ことは悪い習慣だと思います。

これは、このトピックに関する別の SO の質問です。要するに、可読性が非常に悪いです。

簡単な回避策があります。戻りたいすべての値を、この目的のために特別に定義したクラスにラップし、そのクラスのインスタンスを返します。

return new ValueHolder(someValue1, someValue2, someValue3);
于 2013-02-11T20:22:19.083 に答える
3

それはあまり慣用的なJavaではありません。通常、ソフトウェア設計にはより良いアプローチがあります。

「1要素配列」で実際に行っているのは、可変オブジェクトを作成し(intのようなプリミティブと同様にStringは不変であるため)、それを参照渡しすることです。この変更可能なオブジェクトを変更することは、メソッドの「副作用」と呼ばれます。一般に、可変性 ( Effective Java Item 15 ) を最小限に抑え、メソッドに副作用がないようにする必要があります。ここにはいくつかのアプローチがあります。

1. メソッドを、すべて同じパラメータを取る 2 つ (または 3 つ) のメソッドに分割します。

public static int foo1(int param1)
{
    // method body
    ....
    return <some value>;
}

同様に、あなたは持っているかもしれません

public static int foo2(int param1) { ... }

public static String foo3(int param1) { ... }.

2. 複合オブジェクトを返します。

public Container {
    private final int originalReturn;
    private final int param2;
    private final String param3;

    public Container(int originalReturn, int param2, String param3) {
        this.originalReturn = originalReturn;
        this.param2 = param2;
        this.param3 = param3;
    }

    // getters
}

public static Container foo(int param1, int param2[], String param3[])
{
    // method body
    ....
    // set return values
    return new Container(<some value>, <some value>, <some value>);
}
于 2013-02-11T20:46:25.757 に答える
2

値が関連していない場合、これは確かに悪い習慣です。これは通常、その関数を 2 つに分割して、それぞれが値の 1 つを返すことを示しています。

編集:

メソッドで計算された 2 つの値を配列で返していると仮定しています。そうではありませんか?

例えば

public int[] getStatistics(int[] nums)
{
    //code

    int[] returns = new int[2];
    returns[0] = mean;
    returns[1] = mode;

    return returns;
}

getMean()上記の関数は、とに分割できますgetMode()

于 2013-02-11T20:20:44.953 に答える
1

参照によって変数を渡すと、関数はその値を「合法的に」変更できます。Java でこれが可能な場合とそうでない場合の混乱を解消するには、この記事を参照してください...

于 2013-02-11T20:24:21.187 に答える
1

これは、名前と住所など、値が異なるタイプおよび異なるエンティティである場合、悪い習慣です。アドレスのリストなど、同じデータ タイプの配列を作成しても問題ありません。

于 2013-02-11T20:55:51.590 に答える