Javaメソッドから2つの値を返す方法は?


179

Javaメソッドから2つの値を返そうとしていますが、これらのエラーが発生します。これが私のコードです:

// Method code
public static int something(){
    int number1 = 1;
    int number2 = 2;

    return number1, number2;
}

// Main method code
public static void main(String[] args) {
    something();
    System.out.println(number1 + number2);
}

エラー:

Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - missing return statement
    at assignment.Main.something(Main.java:86)
    at assignment.Main.main(Main.java:53)

Javaの結果:1


1
その複製は逆に行くべきですか?ここでの答えはより良いようです。
Jリチャードスネイプ

回答:


239

2つの値を含む配列を返すか、汎用Pairクラスを使用する代わりに、返したい結果を表すクラスを作成し、そのクラスのインスタンスを返すことを検討してください。クラスにわかりやすい名前を付けます。配列を使用することに対するこのアプローチの利点はタイプセーフであり、プログラムをより簡単に理解できるようになります。

注:ジェネリックPairクラスは、ここで他のいくつかの回答で提案されているように、タイプセーフも提供しますが、結果が表すものを伝えません。

例(本当に意味のある名前を使用していない):

final class MyResult {
    private final int first;
    private final int second;

    public MyResult(int first, int second) {
        this.first = first;
        this.second = second;
    }

    public int getFirst() {
        return first;
    }

    public int getSecond() {
        return second;
    }
}

// ...

public static MyResult something() {
    int number1 = 1;
    int number2 = 2;

    return new MyResult(number1, number2);
}

public static void main(String[] args) {
    MyResult result = something();
    System.out.println(result.getFirst() + result.getSecond());
}

1
これは私の好みのルートです-おそらく、数値のペアには何らかの意味があり、戻り値の型がこれを表すとよいでしょう。
アルマンド

3
SimpleEntry <type_of_value_1、type_of_value_2>をjava.util.AbstractMap.SimpleEntryから使用し、それをgetKey()で使用してオブジェクト1を取得し、getValue()でオブジェクト2を取得する
Crystalonics

45
Javaでは複数の値を返すことができるようにすべきだと私は強く感じています。これはより高速で(作成されるオブジェクトが少なく)、少し違うことをするたびに追加のクラス(肥大化したコード)を必要としません。私はどんな欠点も見ません、おそらく誰かが私を啓発することができますか?
クリスセリーヌ2016年

これは、「Pythonで行うように、メソッドから2つの値を返す方法」である質問に対する回避策にすぎません。
Anum Sheraz

4
@AnumSheraz「Pythonのように...する方法」に対する答えは次のとおりです。Javaにはそのような言語機能がないため、必要ありません...
Jesper

73

Javaは複数値の戻りをサポートしていません。値の配列を返します。

// Function code
public static int[] something(){
    int number1 = 1;
    int number2 = 2;
    return new int[] {number1, number2};
}

// Main class code
public static void main(String[] args) {
  int result[] = something();
  System.out.println(result[0] + result[1]);
}

7
これは、ほとんどの場合、特に2つの結果値のタイプが異なる場合は、間違った方法です。
Kevin Sitze

7
@BarAkiva、それが間違っている理由は、型の安全性を失うためです。同種の型の値を返す場合は、常に配列よりもリストを優先する必要があります。特に、ジェネリック値を扱う場合は、T []よりも常に戻り値としてList <T>を使用することをお勧めします。ジェネリック型では常にListを作成できますが、配列では作成できないためです。これを行うことはできません: "new T [length];" 異種の型に対してここで示されているようにPairクラスを作成するアプローチは、異種の型のより良いオプションです。
Kevin Sitze 2017

41

Pair2つの値を返す必要があるだけの場合は、ジェネリックを実装できます。

public class Pair<U, V> {

 /**
     * The first element of this <code>Pair</code>
     */
    private U first;

    /**
     * The second element of this <code>Pair</code>
     */
    private V second;

    /**
     * Constructs a new <code>Pair</code> with the given values.
     * 
     * @param first  the first element
     * @param second the second element
     */
    public Pair(U first, V second) {

        this.first = first;
        this.second = second;
    }

//getter for first and second

そして、メソッドがそれを返すようにしPairます:

public Pair<Object, Object> getSomePair();

このメソッドの戻りはどのようになりますか?
Jwan622

ペアの線に沿った何か:pair = new Pair(thing1、thing2).... return pair;
Lars Andren

27

Javaでは1つの値しか返せないため、最も近い方法は次のようになります。

return new Pair<Integer>(number1, number2);

コードの更新バージョンは次のとおりです。

public class Scratch
{
    // Function code
    public static Pair<Integer> something() {
        int number1 = 1;
        int number2 = 2;
        return new Pair<Integer>(number1, number2);
    }

    // Main class code
    public static void main(String[] args) {
        Pair<Integer> pair = something();
        System.out.println(pair.first() + pair.second());
    }
}

class Pair<T> {
    private final T m_first;
    private final T m_second;

    public Pair(T first, T second) {
        m_first = first;
        m_second = second;
    }

    public T first() {
        return m_first;
    }

    public T second() {
        return m_second;
    }
}

8

SimpleEntryを使用した本当にシンプルで短いソリューションを次に示します。

AbstractMap.Entry<String, Float> myTwoCents=new AbstractMap.SimpleEntry<>("maximum possible performance reached" , 99.9f);

String question=myTwoCents.getKey();
Float answer=myTwoCents.getValue();

Java組み込み関数のみを使用し、型の安全性の利点が付属しています。


6

コレクションを使用して複数の戻り値を返す必要があります

あなたの場合、あなたはあなたのコードを次のように書く

public static List something(){
        List<Integer> list = new ArrayList<Integer>();
        int number1 = 1;
        int number2 = 2;
        list.add(number1);
        list.add(number2);
        return list;
    }

    // Main class code
    public static void main(String[] args) {
      something();
      List<Integer> numList = something();
    }

4
public class Mulretun
{
    public String name;;
    public String location;
    public String[] getExample()
    {
        String ar[] = new String[2];
        ar[0]="siva";
        ar[1]="dallas";
        return ar; //returning two values at once
    }
    public static void main(String[] args)
    {
        Mulretun m=new Mulretun();
        String ar[] =m.getExample();
        int i;
        for(i=0;i<ar.length;i++)
        System.out.println("return values are: " + ar[i]);      

    }
}

o/p:
return values are: siva
return values are: dallas

4

ペア/タプルタイプのオブジェクトを使用します。Apachecommons-langに依存している場合は、オブジェクトを作成する必要もありません。Pairクラスを使用するだけです。


なぜこれはもっと賛成されないのですか?
Rauni Lillemets

3

なぜ誰もよりエレガントなコールバックソリューションを考え出していないのか、私は興味があります。したがって、戻り値の型を使用する代わりに、メソッドに渡されたハンドラを引数として使用します。以下の例には、2つの対照的なアプローチがあります。2つのうちどちらがよりエレガントであるかを知っています。:-)

public class DiceExample {

    public interface Pair<T1, T2> {
        T1 getLeft();

        T2 getRight();
    }

    private Pair<Integer, Integer> rollDiceWithReturnType() {

        double dice1 = (Math.random() * 6);
        double dice2 = (Math.random() * 6);

        return new Pair<Integer, Integer>() {
            @Override
            public Integer getLeft() {
                return (int) Math.ceil(dice1);
            }

            @Override
            public Integer getRight() {
                return (int) Math.ceil(dice2);
            }
        };
    }

    @FunctionalInterface
    public interface ResultHandler {
        void handleDice(int ceil, int ceil2);
    }

    private void rollDiceWithResultHandler(ResultHandler resultHandler) {
        double dice1 = (Math.random() * 6);
        double dice2 = (Math.random() * 6);

        resultHandler.handleDice((int) Math.ceil(dice1), (int) Math.ceil(dice2));
    }

    public static void main(String[] args) {

        DiceExample object = new DiceExample();


        Pair<Integer, Integer> result = object.rollDiceWithReturnType();
        System.out.println("Dice 1: " + result.getLeft());
        System.out.println("Dice 2: " + result.getRight());

        object.rollDiceWithResultHandler((dice1, dice2) -> {
            System.out.println("Dice 1: " + dice1);
            System.out.println("Dice 2: " + dice2);
        });
    }
}

2

2つの異なる値を返すために独自のクラスを作成する必要はありません。次のようにHashMapを使用するだけです。

private HashMap<Toy, GameLevel> getToyAndLevelOfSpatial(Spatial spatial)
{
    Toy toyWithSpatial = firstValue;
    GameLevel levelToyFound = secondValue;

    HashMap<Toy,GameLevel> hm=new HashMap<>();
    hm.put(toyWithSpatial, levelToyFound);
    return hm;
}

private void findStuff()
{
    HashMap<Toy, GameLevel> hm = getToyAndLevelOfSpatial(spatial);
    Toy firstValue = hm.keySet().iterator().next();
    GameLevel secondValue = hm.get(firstValue);
}

タイプセーフのメリットもあります。


2
HashMapも必要ありません。SimpleEntryを使用するだけです!
Xerus

なぜHashMapなのか、質問してもいいですか?ここで使用するのは奇妙なデータ構造のようです。
Neil Chowdhury

@Neil Chowdhuryこれは、2つの定義可能なパラメーターを取る便利な組み込みクラスであること以外に理由はありません。Xerusが指摘したように、ここではAbstractMap.SimpleEntryがより軽量なオプションです。以下の対応する回答をご覧ください!
コードninetyninepointnine 2018

2

私の意見では、最良の方法は、コンストラクターが必要な関数である新しいクラスを作成することです。

public class pairReturn{
        //name your parameters:
        public int sth1;
        public double sth2;
        public pairReturn(int param){
            //place the code of your function, e.g.:
            sth1=param*5;
            sth2=param*10;
        }
    }

次に、関数を使用するのと同じようにコンストラクタを使用します。

pairReturn pR = new pairReturn(15);

また、pR.sth1、pR.sth2を「関数の2つの結果」として使用できます。


1

変更可能なオブジェクトをパラメーターとして送信することもできます。メソッドを使用して変更すると、関数から戻ったときに変更されます。それは不変なので、フロートのようなものでは動作しません。

public class HelloWorld{

     public static void main(String []args){
        HelloWorld world = new HelloWorld();

        world.run();
     }



    private class Dog
    {
       private String name;
       public void setName(String s)
       {
           name = s;
       }
       public String getName() { return name;}
       public Dog(String name)
       {
           setName(name);
       }
    }

    public void run()
    {
       Dog newDog = new Dog("John");
       nameThatDog(newDog);
       System.out.println(newDog.getName());
     }


     public void nameThatDog(Dog dog)
     {
         dog.setName("Rutger");
     }
}

結果は次のとおりです。ラトガー


1

オブジェクトの配列を返す

private static Object[] f () 
{ 
     double x =1.0;  
     int y= 2 ;
     return new Object[]{Double.valueOf(x),Integer.valueOf(y)};  
}

0

まず、Javaに複数の値を返すためのタプルがあるとよいでしょう。

第二に、可能な限り簡単なコーディング Pairクラスをか、配列を使用します。

ただし、ペアを返す必要がある場合、それが表す概念(フィールド名で始まり、次にクラス名)を検討してください。また、ペアが思ったよりも大きな役割を果たすかどうか、および全体的な設計に役立つかどうかを検討してください。それのための明示的な抽象化。多分それはだcode hint...
してください注:私は独断的にそれは言わないよし、ちょうど見に、助けを参照それがない場合...またはそれがない場合はありません。


-7

そして、これはJSでそれを行う方法です: return { objA, valueB }。私はそれがオフトピックであることを知っていますが、まったく新しいクラスをJavaで実装する必要があることを確認した後、このコメントを残すのを控えることはできません。JavaScript-あなたの人生を無駄にしないで、スクリプトを開始してください!

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