Javaメソッドから複数のオブジェクトを返す方法は?


172

Javaメソッドから2つのオブジェクトを返したいのですが、それを行うにはどうすればよいのでしょうか。

私は考えることができる可能性のある方法は、以下のとおりです。リターンA HashMap(2つのオブジェクトが関連しているので)または戻りArrayListObjectオブジェクトを。

より正確には、返したい2つのオブジェクトはList、(a)オブジェクトの(b)コンマ区切りの同じ名前です。

オブジェクトのリストを繰り返し処理してコンマ区切りの名前を取得したくないので、この2つのオブジェクトを1つのメソッドから返したいのです(このメソッドの同じループで実行できます)。

どういうわけか、aを返すことHashMapは、非常にエレガントな方法ではありません。


1
リストとCSVは基本的に同じデータの異なるビューですか?必要なのは、単一のList参照と一種のルックアップテーブルを持つオブジェクトです。
ジェームズP.

回答:


128

2つのオブジェクトを返す場合は、通常、代わりに2つのオブジェクトをカプセル化する単一のオブジェクトを返します。

次のNamedObjectようなオブジェクトのリストを返すことができます。

public class NamedObject<T> {
  public final String name;
  public final T object;

  public NamedObject(String name, T object) {
    this.name = name;
    this.object = object;
  }
}

その後、簡単にを返すことができますList<NamedObject<WhateverTypeYouWant>>

また、なぜではなく、名前のコンマ区切りのリストを返す必要があるのList<String>ですか?あるいはMap<String,TheObjectType>、キーをオブジェクトの名前と値にした状態でa を返します(オブジェクトに順序が指定されていNavigableMapない場合、その場合はa が必要な場合があります)。


コンマ区切りのリストを返す理由は次のとおりです。ここでリストを作成しない場合は、呼び出し側でオブジェクトをループして実行する必要があります(CS値が必要です)。おそらく、私は不必要に事前最適化しています。
Jagmal、2009年

2
この理由から、JavaにはなぜPair <T、U>クラスがないのかといつも疑問に思っていました。
David Koelle、

Jagmal:はい、コンマ区切りのリストを返す唯一の理由がこの最適化である場合は、それを忘れてください。
Joachim Sauer、

これは、返したいアイテムが同じクラスであるか、少なくとも共通の祖先がある場合にのみ機能します。つまり、WhateverTypeYouWantの代わりにObjectを使用することは、あまりうまくいきません。
デビッドハナク2009年

@David:ここでObjectを使用することはあまり効果的ではないことに同意しますが、共通の祖先なしでオブジェクトを返すこと(もちろんObjectを除く)もあまり効果的ではないことに同意します。あなたがそれを必要とするなら、私はそれがコードのにおいだとさえ言うでしょう。
Joachim Sauer、

69

2つのオブジェクトを返すことがわかっている場合は、一般的なペアを使用することもできます。

public class Pair<A,B> {
    public final A a;
    public final B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }
};

編集上記のより完全に形成された実装:

package util;

public class Pair<A,B> {

    public static <P, Q> Pair<P, Q> makePair(P p, Q q) {
        return new Pair<P, Q>(p, q);
    }

    public final A a;
    public final B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((a == null) ? 0 : a.hashCode());
        result = prime * result + ((b == null) ? 0 : b.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        @SuppressWarnings("rawtypes")
        Pair other = (Pair) obj;
        if (a == null) {
            if (other.a != null) {
                return false;
            }
        } else if (!a.equals(other.a)) {
            return false;
        }
        if (b == null) {
            if (other.b != null) {
                return false;
            }
        } else if (!b.equals(other.b)) {
            return false;
        }
        return true;
    }

    public boolean isInstance(Class<?> classA, Class<?> classB) {
        return classA.isInstance(a) && classB.isInstance(b);
    }

    @SuppressWarnings("unchecked")
    public static <P, Q> Pair<P, Q> cast(Pair<?, ?> pair, Class<P> pClass, Class<Q> qClass) {

        if (pair.isInstance(pClass, qClass)) {
            return (Pair<P, Q>) pair;
        }

        throw new ClassCastException();

    }

}

ノート、主にJavaとジェネリックの錆びについて:

  • 両方ab不変です。
  • makePair静的メソッドは、ボイラープレートのタイピングに役立ちます。Java7のダイヤモンドオペレーターは、煩わしさが少なくなります。これを本当に優れたre:genericsにするためのいくつかの作業がありますが、今は大丈夫なはずです。(PECSを参照)
  • hashcodeそしてequals日食によって生成されます。
  • castメソッドでのコンパイル時のキャストは問題ありませんが、正しくないようです。
  • のワイルドカードisInstanceが必要かどうかはわかりません。
  • これは、説明のみを目的として、コメントへの返信として書いたものです。

私は通常、このクラスに取り組んでいる各コードベースをたたきます。また、hashCode / equalsの実装、および場合によっては静的なisInstance()およびcast()メソッドも追加します。
jamesh

もちろん、このクラスをよりスマートで使いやすくする方法はたくさんあります。上記のバージョンには、ワンショット宣言で十分なものが含まれています。
David Hanak、2009年

@jamesh:ペアの詳細をここに記入してよろしいですか?「hashCode / equalsの実装、および場合によっては静的なisInstance()とcast()メソッドを提供した後の様子を知りたいのですが。ありがとうございました。
Qiang Li

@QiangLi-私は通常、ハッシュコードと等しいメソッドを生成します。インスタンスメソッドisInstanceは2つのクラスを取り、インスタンスのaおよびbがそれらのクラスのインスタンスであることを確認します。キャストはペア<?、?>を取り、ペア<A、B>に慎重にキャストします。実装はかなり簡単である必要があります(ヒント:Class.cast()、Class.isInstance())
jamesh

2
これは非常に優れたPair実装です。私が行う1つの小さな変更:メッセージをに追加しますClassCastException。さもなければ、これが何らかの理由で失敗した場合、デバッグは悪夢になります。あなたがにキャストたい場合(およびrawtypes抑止警告は不要だろうPair<?,?>あなただけの必要があるため、働く(Objectメソッドから、ab。?)私は、コードを微調整する場合は、あなたが気にしてください
ヨアヒム・ザウアー

25

呼び出すメソッドがプライベートである場合、または1つの場所から呼び出される場合は、

return new Object[]{value1, value2};

呼び出し元は次のようになります。

Object[] temp=myMethod(parameters);
Type1 value1=(Type1)temp[0];  //For code clarity: temp[0] is not descriptive
Type2 value2=(Type2)temp[1];

David Hanakによるペアの例には構文上の利点はなく、2つの値に制限されています。

return new Pair<Type1,Type2>(value1, value2);

そして、呼び出し元は次のようになります。

Pair<Type1, Type2> temp=myMethod(parameters);
Type1 value1=temp.a;  //For code clarity: temp.a is not descriptive
Type2 value2=temp.b;

7
ペアにはクラスタイプコントロールの利点があります
Hlex

5
私見、このようにしないでください-宣言は期待される戻り値についてあまりにも少なすぎます。私の知る限りでは、返されるパラメーターの数とそれらのパラメーターのタイプを指定する汎用クラスを作成する方がより広く推奨されます。Pair<T1, T2>Tuple<T1, T2, T3>Tuple<T1, T2, T3, T4>、など、特定の用途ショー数及びパラメータの種類Pair<int, String> temp = ...または何。
ToolmakerSteve 2015年

22

次のいずれかの方法を使用できます。

private static final int RETURN_COUNT = 2;
private static final int VALUE_A = 0;
private static final int VALUE_B = 1;
private static final String A = "a";
private static final String B = "b";

1)配列の使用

private static String[] methodWithArrayResult() {
    //...
    return new String[]{"valueA", "valueB"};
}

private static void usingArrayResultTest() {
    String[] result = methodWithArrayResult();
    System.out.println();
    System.out.println("A = " + result[VALUE_A]);
    System.out.println("B = " + result[VALUE_B]);
}

2)ArrayListの使用

private static List<String> methodWithListResult() {
    //...
    return Arrays.asList("valueA", "valueB");
}

private static void usingListResultTest() {
    List<String> result = methodWithListResult();
    System.out.println();
    System.out.println("A = " + result.get(VALUE_A));
    System.out.println("B = " + result.get(VALUE_B));
}

3)HashMapの使用

private static Map<String, String> methodWithMapResult() {
    Map<String, String> result = new HashMap<>(RETURN_COUNT);
    result.put(A, "valueA");
    result.put(B, "valueB");
    //...
    return result;
}

private static void usingMapResultTest() {
    Map<String, String> result = methodWithMapResult();
    System.out.println();
    System.out.println("A = " + result.get(A));
    System.out.println("B = " + result.get(B));
}

4)カスタムコンテナークラスの使用

private static class MyContainer<M,N> {
    private final M first;
    private final N second;

    public MyContainer(M first, N second) {
        this.first = first;
        this.second = second;
    }

    public M getFirst() {
        return first;
    }

    public N getSecond() {
        return second;
    }

    // + hashcode, equals, toString if need
}

private static MyContainer<String, String> methodWithContainerResult() {
    //...
    return new MyContainer("valueA", "valueB");
}

private static void usingContainerResultTest() {
    MyContainer<String, String> result = methodWithContainerResult();
    System.out.println();
    System.out.println("A = " + result.getFirst());
    System.out.println("B = " + result.getSecond());
}

5)AbstractMap.simpleEntryの使用

private static AbstractMap.SimpleEntry<String, String> methodWithAbstractMapSimpleEntryResult() {
    //...
    return new AbstractMap.SimpleEntry<>("valueA", "valueB");
}

private static void usingAbstractMapSimpleResultTest() {
    AbstractMap.SimpleEntry<String, String> result = methodWithAbstractMapSimpleEntryResult();
    System.out.println();
    System.out.println("A = " + result.getKey());
    System.out.println("B = " + result.getValue());
}

6)Apache Commonsのペアの使用

private static Pair<String, String> methodWithPairResult() {
    //...
    return new ImmutablePair<>("valueA", "valueB");
}

private static void usingPairResultTest() {
    Pair<String, String> result = methodWithPairResult();
    System.out.println();
    System.out.println("A = " + result.getKey());
    System.out.println("B = " + result.getValue());
}

16

ほとんどの場合、Javaでコーディングするとき、n-Tupleクラスを定義することになります。例えば:

public class Tuple2<T1,T2> {
  private T1 f1;
  private T2 f2;
  public Tuple2(T1 f1, T2 f2) {
    this.f1 = f1; this.f2 = f2;
  }
  public T1 getF1() {return f1;}
  public T2 getF2() {return f2;}
}

私はそれが少し見苦しいことを知っていますが、それは機能し、タプル型を一度定義するだけで済みます。タプルはJavaには本当に欠けているものです。

編集:David Hanakの例は、ゲッターの定義を回避し、オブジェクトを不変に保つため、よりエレガントです。


9

Java 5以前は、マップソリューションが理想的ではないことに少し同意します。コンパイル時に型チェックが行われないため、実行時に問題が発生する可能性があります。ただし、Java 5ではジェネリック型があります。

したがって、メソッドは次のようになります。

public Map<String, MyType> doStuff();

もちろんMyTypeは、返されるオブジェクトのタイプです。

基本的に、この場合はMapを返すことが正しい解決策であると思います。これは、まさに文字列からオブジェクトへのマッピングです。


名前のいずれかが衝突する場合、これは機能しません。リストには重複が含まれる可能性がありますが、マップには含まれません(重複キーが含まれます)。
tvanfosson、2009年

もちろん。私は質問に基づいて仮定を立てていました-おそらく過度に:)
kipz '19年

この場合、あなたの仮定は当てはまりますが、私は時期尚早の最適化の領域に踏み込んでいます(私はすべきではありません)。
Jagmal、2009年

6

あるいは、メソッドから多くのものを返したい状況では、コンテナーの代わりにコールバックメカニズムを使用することがあります。これは、生成されるオブジェクトの数を事前に指定できない状況で非常にうまく機能します。

あなたの特定の問題では、それは次のようになります:

public class ResultsConsumer implements ResultsGenerator.ResultsCallback
{
    public void handleResult( String name, Object value )
    {
        ... 
    }
}

public class ResultsGenerator
{
    public interface ResultsCallback
    {
        void handleResult( String aName, Object aValue );
    }

    public void generateResults( ResultsGenerator.ResultsCallback aCallback )
    {
        Object value = null;
        String name = null;

        ...

        aCallback.handleResult( name, value );
    }
}

あなたの非常に古い答えにコメントして申し訳ありませんが、ガベージコレクションに関してコールバックはどのように行われますか?私は確かにのメモリ管理について十分に理解していません。javaオブジェクトAコールオブジェクトがB.getResult()あり、B.getResult()A.finishResult()として呼び出した場合callback、オブジェクトBはガベージコレクションされますか、それともAが終了するまで残りますか?おそらく愚かな質問ですが、それは私が持っている根本的な混乱です!
ワイヤード00

6

Apache Commonsには、このためのタプルとトリプルがあります。

  • ImmutablePair<L,R> 2つのObject要素で構成される不変のペア。
  • ImmutableTriple<L,M,R> 3つのObject要素で構成される不変のトリプル。
  • MutablePair<L,R> 2つのObject要素で構成される可変ペア。
  • MutableTriple<L,M,R> 3つのObject要素で構成される可変トリプル。
  • Pair<L,R> 2つの要素で構成されるペア。
  • Triple<L,M,R> 3つの要素で構成されるトリプル。

ソース:https : //commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html


6

あなたの場合、コメントは良い方法かもしれませんが、Androidではを使用できますPair 。単に

return new Pair<>(yourList, yourCommaSeparatedValues);


5

一般に複数の戻り値に関する問題に関して、私は通常、単一の戻り値をラップし、パラメーターとしてメソッドに渡される小さなヘルパークラスを使用します。

public class ReturnParameter<T> {
    private T value;

    public ReturnParameter() { this.value = null; }
    public ReturnParameter(T initialValue) { this.value = initialValue; }

    public void set(T value) { this.value = value; }
    public T get() { return this.value; }
}

(プリミティブデータ型の場合、マイナーバリエーションを使用して値を直接格納します)

複数の値を返したいメソッドは、次のように宣言されます。

public void methodThatReturnsTwoValues(ReturnParameter<ClassA> nameForFirstValueToReturn, ReturnParameter<ClassB> nameForSecondValueToReturn) {
    //...
    nameForFirstValueToReturn.set("...");
    nameForSecondValueToReturn.set("...");
    //...
}

おそらく主な欠点は、呼び出し元が戻りオブジェクトを使用したい場合に備えて、呼び出し元が事前に準備する必要があることです(メソッドはnullポインターをチェックする必要があります)。

ReturnParameter<ClassA> nameForFirstValue = new ReturnParameter<ClassA>();
ReturnParameter<ClassB> nameForSecondValue = new ReturnParameter<ClassB>();
methodThatReturnsTwoValues(nameForFirstValue, nameForSecondValue);

利点(提案されている他のソリューションとの比較):

  • 個々のメソッドとその戻りの型に対して特別なクラス宣言を作成する必要はありません
  • パラメータには名前が付けられるため、メソッドシグネチャを見たときに区別しやすくなります
  • 各パラメーターの型安全性

戻り値の型のセットごとにクラス宣言を必要とせずに、各戻り値に名前と型の安全性を与えるソリューションに感謝します。
ToolmakerSteve

3

考えられるすべてのソリューションは粗末なものになります(コンテナーオブジェクト、HashMapのアイデア、「配列によって実現される複数の戻り値」など)。返されたリストからコンマ区切りのリストを再生成することをお勧めします。コードはかなりクリーンになります。


私はこれに同意しますが、そうすると、ループが2回終了します(実際には、既存のメソッドでリストの要素を1つずつ作成しています)。
ジャグマル09年

1
@Jagmal:2回ループする可能性がありますが、ほとんどの場合問題ありません(ギズモの回答を参照)。
ヨアヒムザウアー

1
ええ、本当に必要でない限り、コードを最適化しようとしないでください。ギズモはそれについて非常に正しいです。
ボンベ、

3

シンプルに保ち、複数の結果状況に対応するクラスを作成します。この例では、データベースヘルパーgetInfoからArrayListとメッセージテキストを受け入れます。

コーディングする複数の値を返すルーチンを呼び出す場所:

multResult res = mydb.getInfo(); 

ルーチンgetInfoでコーディングします。

ArrayList<String> list= new ArrayList<String>();
add values to the list...
return new multResult("the message", list);

そして、クラスmultResultを定義します:

public class multResult {
    public String message; // or create a getter if you don't like public
    public ArrayList<String> list;
    multResult(String m, ArrayList<String> l){
        message = m;
        list= l;
}

}


2

私が見ると、ここには本当に3つの選択肢があり、解決策はコンテキストによって異なります。リストを作成するメソッドで名前の構成を実装することを選択できます。これはあなたが選んだ選択ですが、私はそれが最良のものではないと思います。プロデューサーメソッドで、存在する必要のないコンシューミングメソッドにカップリングを作成しています。他の発信者は追加情報を必要としない場合があり、これらの発信者の追加情報を計算します。

または、呼び出しメソッドに名前を計算させることもできます。この情報を必要とする発信者が1人だけの場合は、そこで停止できます。追加の依存関係はなく、少し余分な計算が必要ですが、構築方法を具体的にしすぎることは避けています。これは良いトレードオフです。

最後に、リスト自体に名前の作成を任せることもできます。これは、複数の呼び出し元が計算を行う必要がある場合に使用するルートです。これは、オブジェクト自体に最も密接に関連しているクラスで名前を作成する責任があると思います。

後者の場合、私の解決策は、含まれるオブジェクトの名前のコンマ区切りの文字列を返す特殊なListクラスを作成することです。オブジェクトが追加されたり削除されたりするときに、その場で名前文字列を構築するようにクラスを十分にスマートにします。次に、このリストのインスタンスを返し、必要に応じて名前生成メソッドを呼び出します。メソッドが最初に呼び出されてそれを保存するまで名前の計算を単に遅延させること(遅延読み込み)は、ほぼ同じくらい効率的(かつ簡単)です。オブジェクトを追加/削除する場合は、計算された値を削除し、次の呼び出しで再計算させるだけです。


2

動的言語(Python)のタプルのようなことができる

public class Tuple {
private Object[] multiReturns;

private Tuple(Object... multiReturns) {
    this.multiReturns = multiReturns;
}

public static Tuple _t(Object... multiReturns){
    return new Tuple(multiReturns);
}

public <T> T at(int index, Class<T> someClass) {
    return someClass.cast(multiReturns[index]);
}
}

そしてこのように使います

public Tuple returnMultiValues(){
   return Tuple._t(new ArrayList(),new HashMap())
}


Tuple t = returnMultiValues();
ArrayList list = t.at(0,ArrayList.class);

2

私は他の回答で説明されているのと同じアプローチに従いましたが、私が持っていた要件に基づいていくつかの微調整を行い、基本的に次のクラスを作成しました(念のため、すべてがJavaです):

public class Pair<L, R> {
    final L left;
    final R right;

    public Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    public <T> T get(Class<T> param) {
        return (T) (param == this.left.getClass() ? this.left : this.right);
    }

    public static <L, R> Pair<L, R> of(L left, R right) {
        return new Pair<L, R>(left, right);
    }
}

次に、私の要件は単純でした、DBに到達するリポジトリクラスで、GetメソッドがDBからデータを取得するよりも、失敗したか成功したかを確認する必要があります。成功した場合は、返されたリストで遊ぶ必要がありました。失敗した場合は、実行を停止してエラーを通知します。

したがって、たとえば、私のメソッドは次のようになります。

public Pair<ResultMessage, List<Customer>> getCustomers() {
    List<Customer> list = new ArrayList<Customer>();
    try {
    /*
    * Do some work to get the list of Customers from the DB
    * */
    } catch (SQLException e) {
        return Pair.of(
                       new ResultMessage(e.getErrorCode(), e.getMessage()), // Left 
                       null);  // Right
    }
    return Pair.of(
                   new ResultMessage(0, "SUCCESS"), // Left 
                   list); // Right
}

ここで、ResultMessageは2つのフィールド(コード/メッセージ)を持つクラスであり、CustomerはDBから取得される一連のフィールドを持つクラスです。

次に、結果を確認するには、次のようにします。

void doSomething(){
    Pair<ResultMessage, List<Customer>> customerResult = _repository.getCustomers();
    if (customerResult.get(ResultMessage.class).getCode() == 0) {
        List<Customer> listOfCustomers = customerResult.get(List.class);
        System.out.println("do SOMETHING with the list ;) ");
    }else {
        System.out.println("Raised Error... do nothing!");
    }
}

1

C ++(STL)には、2つのオブジェクトをバンドルするためのペアクラスがあります。Java Genericsでは、いくつかの要求がありますが、ペアクラスは使用できません。ただし、自分で簡単に実装できます。

ただし、メソッドから2つ以上のオブジェクトを返す必要がある場合は、クラスにカプセル化する方がよいという他のいくつかの回答にも同意します。


1

なぜ作成しないでWhateverFunctionResult、あなたの結果を含むオブジェクト、および反復が終わった後などそれはどちらかと私には思われる、これらの結果を解析するために必要なロジックを:

  1. これらの結果オブジェクトは、密接に結び付いている/関連していて、一緒に属している、または:
  2. それらは無関係であり、その場合、関数は何をしようとしているのか(つまり、2つの異なることを行うことに関して)明確に定義されていません。

私はこの種の問題が何度も繰り返されるのを見ます。これを処理するためのデータと関連機能を含む独自のコンテナー/結果クラスを作成することを恐れないでください。単にものをHashMap類似のもので渡す場合、クライアントはこのマップを引き離して、結果を使用するたびにコンテンツを調べる必要があります。


複数の値を返す必要があるときはいつでもクラスを定義する必要があるのはPITAだからです。これは、言語にこの一般的に役立つ機能がないためです;)しかし、真剣に、提案することは非常に頻繁に行う価値があります。
ToolmakerSteve

1
public class MultipleReturnValues {

    public MultipleReturnValues() {
    }

    public static void functionWithSeveralReturnValues(final String[] returnValues) {
        returnValues[0] = "return value 1";
        returnValues[1] = "return value 2";
    }

    public static void main(String[] args) {
        String[] returnValues = new String[2];
        functionWithSeveralReturnValues(returnValues);
        System.out.println("returnValues[0] = " + returnValues[0]);
        System.out.println("returnValues[1] = " + returnValues[1]);
    }

}

1

これは正確に質問に答えているわけではありませんが、ここで示すすべてのソリューションにはいくつかの欠点があるため、コードを少しリファクタリングして、1つの値のみを返すようにすることをお勧めします。

ケース1。

メソッドの内部と外部の両方で何かが必要です。外で計算してメソッドに渡してみませんか?

の代わりに:

[thingA, thingB] = createThings(...);  // just a conceptual syntax of method returning two values, not valid in Java

試してください:

thingA = createThingA(...);
thingB = createThingB(thingA, ...);

ほとんどの場合、1つの値が他の値の前に作成され、2つの方法でそれらを分割して作成できるため、これでほとんどのニーズがカバーされます。欠点は、メソッドにcreateThingsBはと比較して追加のパラメーターがcreateThingsあり、場合によってはまったく同じパラメーターのリストを異なるメソッドに2回渡すことです。


ケース2。

これまでで最も明白なソリューションとケース1の簡略化されたバージョン。常に可能であるとは限りませんが、おそらく両方の値を互いに独立して作成できますか?

の代わりに:

[thingA, thingB] = createThings(...);  // see above

試してください:

thingA = createThingA(...);
thingB = createThingB(...);

より便利にするために、これらの2つのメソッドはいくつかの一般的なロジックを共有できます。

public ThingA createThingA(...) {
    doCommonThings(); // common logic
    // create thing A
}
public ThingB createThingB(...) {
    doCommonThings(); // common logic
    // create thing B
}

0

リストをメソッドに渡し、それを入力してから、次のように名前付きの文字列を返します。

public String buildList(List<?> list) {
    list.add(1);
    list.add(2);
    list.add(3);
    return "something,something,something,dark side";
}

次に、次のように呼び出します。

List<?> values = new ArrayList<?>();
String names = buildList(values);

-2

私は複数の返品の問題に対処するために非常に基本的なアプローチを使用しています。これは目的を果たし、複雑さを回避します。

文字列区切りと呼びますアプローチ

そして、複数の型の値を返すこともできるので効果的です、int、double、char、stringなど

このアプローチでは、一般的に発生する可能性が非常に低い文字列を使用します。これをセパレータと呼びます。このセパレーターは、関数で使用される場合、さまざまな値を区切るために使用されます

たとえば、最終的な戻り値は(たとえば)intValueセパレーターdoubleValueセパレーターです...そして、この文字列を使用して、必要なすべての情報を取得します。

次のコードはこの概念の働きを示します

使用される区切り記号は!@#で、3つの値がintVal、doubleVal、stringValとして返されます。

        public class TestMultipleReturns {

            public static String multipleVals() {

                String result = "";
                String separator = "!@#";


                int intVal = 5;
                // Code to process intVal

                double doubleVal = 3.14;
                // Code to process doubleVal

                String stringVal = "hello";
                // Code to process Int intVal

                result = intVal + separator + doubleVal + separator + stringVal + separator;
                return (result);
            }

            public static void main(String[] args) {

                String res = multipleVals();

                int intVal = Integer.parseInt(res.split("!@#")[0]);
                // Code to process intVal

                double doubleVal = Double.parseDouble(res.split("!@#")[1]);
                // Code to process doubleVal

                String stringVal = res.split("!@#")[2];

                System.out.println(intVal+"\n"+doubleVal+"\n"+stringVal);
            }
        }

出力

5
3.14
hello
BUILD SUCCESSFUL (total time: 2 seconds)

3
ゆく。巨大なコードのにおい。使用可能なオブジェクト指向機能を使用する代わりに、構文解析。IMOは、私が今まで見た中で最悪のコーディング例の1つです。2つの独立したプログラム間または他のプロセス間通信間で複数の値を渡す必要があり、それを行うための適切なメカニズム(jsonなど)にアクセスできない状況について説明している場合を除きます。
ToolmakerSteve

-4

Cでは、結果のプレースホルダーへのポインターを引数として渡すことでそれを行います。

void getShoeAndWaistSizes(int *shoeSize, int *waistSize) {
    *shoeSize = 36;
    *waistSize = 45;
}
...
int shoeSize, waistSize;
getShoeAndWaistSize(&shoeSize, &waistSize);
int i = shoeSize + waistSize;

Javaで同様のことを試してみましょう。

void getShoeAndWaistSizes(List<Integer> shoeSize, List<Integer> waistSize) {
    shoeSize.add(36);
    waistSize.add(45);
}
...
List<Integer> shoeSize = new List<>();
List<Integer> waistSize = new List<>();
getShoeAndWaistSizes(shoeSize, waistSize);
int i = shoeSize.get(0) + waistSize.get(0);

1
ただし、オブジェクト指向言語では、この回答の4年前にすでに数人が提案していることを行うことが望ましいと考えられています。関連する2つの値を1つのオブジェクト(ペア、タプル、またはカスタムクラス定義)にグループ化し、それらのリストを作成します。オブジェクト。そうすることで、複数のリストを渡す必要がなくなります。このようなペア(各リストの1つの要素)を他のメソッドに渡してさらに処理する必要がある場合、これは特に重要になります。
ToolmakerSteve

@ToolmakerSteve明確にするために:リストはそれぞれ正確に1つの要素を持つことを意図しており、ポインターを渡すための類似体を実装する手段にすぎません。これらは、いくつかの結果を収集することを意図しておらず、メソッド呼び出し後の数行以上に使用されることさえありません。
エイドリアンPanasiuk 2014年

-5

メソッドにハッシュを渡し、それを普及させる......

public void buildResponse(String data、Map response);

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.