Wie kann man 2 Werte von einer Java-Methode zurückgeben?

179

Ich versuche, 2 Werte von einer Java-Methode zurückzugeben, erhalte jedoch diese Fehler. Hier ist mein Code:

// 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);
}

Error:

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 Ergebnis: 1

javaLearner.java
quelle
1
Sollte dieses Duplikat umgekehrt sein? Die Antwort hier scheint besser zu sein.
J Richard Snape

Antworten:

238

Anstatt ein Array zurückzugeben, das die beiden Werte enthält, oder eine generische PairKlasse zu verwenden, sollten Sie eine Klasse erstellen, die das Ergebnis darstellt, das Sie zurückgeben möchten, und eine Instanz dieser Klasse zurückgeben. Geben Sie der Klasse einen aussagekräftigen Namen. Die Vorteile dieses Ansatzes gegenüber der Verwendung eines Arrays liegen in der Typensicherheit und erleichtern das Verständnis Ihres Programms.

Hinweis: Eine generische PairKlasse, wie in einigen anderen Antworten hier vorgeschlagen, bietet Ihnen ebenfalls Typensicherheit, vermittelt jedoch nicht, was das Ergebnis darstellt.

Beispiel (das keine wirklich aussagekräftigen Namen verwendet):

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());
}
Jesper
quelle
1
Dies wäre meine bevorzugte Route - vermutlich hat das Zahlenpaar eine Bedeutung, und es wäre schön, wenn der Rückgabetyp dies darstellen würde.
Armand
3
Sie können SimpleEntry <type_of_value_1, type_of_value_2> aus java.util.AbstractMap.SimpleEntry verwenden und es mit getKey () verwenden, um Objekt 1 abzurufen, und getValue (), um Objekt 2
Crystalonics
45
Ich bin der festen Überzeugung, dass Java es Ihnen ermöglichen sollte, mehrere Werte zurückzugeben. Es wäre schneller (weniger Objekte erstellt) und würde nicht jedes Mal zusätzliche Klassen (aufgeblähter Code) erfordern, wenn Sie etwas anderes tun möchten. Ich sehe keine Nachteile, vielleicht kann mich jemand aufklären?
Chris Seline
Dies ist nur eine Umgehung der gestellten Frage, die immer noch lautet: "Wie werden 2 Werte von der Methode zurückgegeben, genau wie in Python?".
Anum Sheraz
4
@AnumSheraz Die Antwort auf "wie man ... genau wie in Python" lautet: Sie nicht, weil Java keine solche Sprachfunktion hat ...
Jesper
74

Java unterstützt keine mehrwertigen Rückgaben. Gibt ein Array von Werten zurück.

// 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]);
}
Matt
quelle
7
Dies ist fast immer falsch, insbesondere wenn die Typen der beiden Ergebniswerte unterschiedlich sind.
Kevin Sitze
7
@ BarAkiva, der Grund, warum es falsch ist, ist, dass Sie die Typensicherheit verlieren. Wenn Sie Werte eines homogenen Typs zurückgeben, sollten Sie immer eine Liste einem Array vorziehen. Insbesondere wenn Sie mit generischen Werten arbeiten, wird eine Liste <T> immer als Rückgabewert gegenüber T [] bevorzugt, da Sie immer eine Liste für einen generischen Typ erstellen können, jedoch niemals für ein Array. Sie können dies nicht tun: "new T [length];" Der hier angegebene Ansatz zum Erstellen einer Paarklasse für unterschiedliche Typen ist eine bessere Option für heterogene Typen.
Kevin Sitze
41

Sie können ein Generikum implementieren, Pairwenn Sie sicher sind, dass Sie nur zwei Werte zurückgeben müssen:

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

und lassen Sie dann die Methode Folgendes zurückgeben Pair:

public Pair<Object, Object> getSomePair();
Lars Andren
quelle
Wie würde die Rückkehr dieser Methode aussehen?
Jwan622
Etwas in der Art von: pair = new Pair (thing1, thing2) .... return pair;
Lars Andren
27

Sie können in Java nur einen Wert zurückgeben. Der einfachste Weg ist also folgender:

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

Hier ist eine aktualisierte Version Ihres Codes:

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;
    }
}
richj
quelle
8

Hier ist die wirklich einfache und kurze Lösung mit SimpleEntry:

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

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

Verwendet nur integrierte Java-Funktionen und bietet den Vorteil der Typensicherheit.

Code ninetyninepointnine
quelle
6

Sie müssen Sammlungen verwenden, um mehr als einen Rückgabewert zurückzugeben

In Ihrem Fall schreiben Sie Ihren Code als

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();
    }
GuruKulki
quelle
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
Siva
quelle
4

Verwenden Sie ein Objekt vom Typ Pair / Tuple. Sie müssen nicht einmal eines erstellen, wenn Sie von Apache commons-lang abhängig sind. Verwenden Sie einfach die Pair- Klasse.

UserF40
quelle
Warum ist das nicht mehr positiv bewertet?
Rauni Lillemets
3

Ich bin gespannt, warum sich niemand die elegantere Rückruflösung ausgedacht hat. Anstatt einen Rückgabetyp zu verwenden, verwenden Sie einen an die Methode übergebenen Handler als Argument. Das folgende Beispiel zeigt die beiden gegensätzlichen Ansätze. Ich weiß, welcher der beiden für mich eleganter ist. :-)

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);
        });
    }
}
Steve O 1969
quelle
2

Sie müssen keine eigene Klasse erstellen, um zwei verschiedene Werte zurückzugeben. Verwenden Sie einfach eine HashMap wie folgt:

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);
}

Sie haben sogar den Vorteil der Typensicherheit.

Code ninetyninepointnine
quelle
2
Sie brauchen nicht einmal eine HashMap, verwenden Sie einfach einen SimpleEntry!
Xerus
Warum eine HashMap, darf ich fragen? Das scheint eine seltsame Datenstruktur zu sein.
Neil Chowdhury
@Neil Chowdhury Kein anderer Grund als der, dass es sich um eine praktische integrierte Klasse handelt, die zwei definierbare Parameter verwendet. Wie Xerus hervorhob, ist AbstractMap.SimpleEntry hier die leichtere Option. Bitte beachten Sie die entsprechende Antwort unten!
Code ninetyninepointnine
2

Meiner Meinung nach ist es am besten, eine neue Klasse zu erstellen, deren Konstruktor die Funktion ist, die Sie benötigen, z.

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;
        }
    }

Verwenden Sie dann einfach den Konstruktor wie die Funktion:

pairReturn pR = new pairReturn(15);

und Sie können pR.sth1, pR.sth2 als "2 Ergebnisse der Funktion" verwenden.

Jacob
quelle
1

Sie können auch veränderbare Objekte als Parameter senden. Wenn Sie Methoden verwenden, um sie zu ändern, werden sie geändert, wenn Sie von der Funktion zurückkehren. Bei Sachen wie Float funktioniert es nicht, da es unveränderlich ist.

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");
     }
}

Das Ergebnis ist: Rutger

Andreas
quelle
1

Geben Sie ein Array von Objekten zurück

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

Erstens wäre es besser, wenn Java Tupel für die Rückgabe mehrerer Werte hätte.

Zweitens codieren Sie die einfachste PairKlasse oder verwenden Sie ein Array.

Wenn Sie jedoch ein Paar zurückgeben müssen, überlegen Sie, welches Konzept es darstellt (beginnend mit den Feldnamen, dann dem Klassennamen) - und ob es eine größere Rolle spielt als Sie dachten und ob es Ihrem Gesamtdesign helfen würde, ein Paar zu haben explizite Abstraktion dafür. Vielleicht ist es ein code hint...
Bitte beachten Sie : Ich bin nicht dogmatisch sagen , es wird helfen, aber nur um zu sehen, zu sehen , ob es funktioniert ... oder wenn dies nicht der Fall.

Hyperpallium
quelle
-7

und so machen Sie es in JS : return { objA, valueB }. Ich weiß, dass es offtopisch ist, aber ich kann mich nicht enthalten, diesen Kommentar zu hinterlassen, nachdem ich gesehen habe, wie eine ganz neue Klasse in Java implementiert werden muss. JavaScript - verschwenden Sie kein Leben mehr und beginnen Sie mit dem Scripting!

zavr
quelle