Comment renvoyer 2 valeurs à partir d'une méthode Java?

179

J'essaie de renvoyer 2 valeurs d'une méthode Java mais j'obtiens ces erreurs. Voici mon 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);
}

Erreur:

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)

Résultat Java: 1

javaLearner.java
la source
1
Ce duplicata devrait-il aller dans l'autre sens? La réponse ici semble meilleure.
J Richard Snape

Réponses:

240

Au lieu de renvoyer un tableau contenant les deux valeurs ou d'utiliser une Pairclasse générique , envisagez de créer une classe qui représente le résultat que vous souhaitez renvoyer et renvoyez une instance de cette classe. Donnez à la classe un nom significatif. Les avantages de cette approche par rapport à l'utilisation d'un tableau sont la sécurité de type et rendra votre programme beaucoup plus facile à comprendre.

Remarque: Une Pairclasse générique , comme proposé dans certaines des autres réponses ici, vous donne également la sécurité de type, mais ne transmet pas ce que le résultat représente.

Exemple (qui n'utilise pas de noms vraiment significatifs):

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
la source
1
Ce serait mon itinéraire préféré - vraisemblablement la paire de nombres a une certaine signification, et ce serait bien si le type de retour représentait cela.
Armand
3
Vous pouvez utiliser SimpleEntry <type_of_value_1, type_of_value_2> de java.util.AbstractMap.SimpleEntry et l'utiliser avec getKey () pour obtenir l'objet 1 et getValue () pour obtenir l'objet 2
Crystalonics
45
Je suis convaincu que Java devrait vous permettre de renvoyer plusieurs valeurs. Ce serait plus rapide (moins d'objets créés) et ne nécessiterait pas de classes supplémentaires (code gonflé) chaque fois que vous voulez faire quelque chose d'un peu différent. Je ne vois aucun inconvénient, peut-être que quelqu'un peut m'éclairer?
Chris Seline
Ceci est juste une solution de contournement pour la question posée, qui est toujours "comment renvoyer 2 valeurs de méthode comme nous le faisons en Python".
Anum Sheraz du
4
@AnumSheraz La réponse à "comment faire ... comme en Python" est: ce n'est pas le cas, parce que Java n'a pas une telle fonctionnalité de langage ...
Jesper
73

Java ne prend pas en charge les retours à valeurs multiples. Renvoie un tableau de valeurs.

// 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]);
}
Mat
la source
7
Ce n'est presque toujours pas la bonne chose à faire, surtout si les types des deux valeurs de résultat sont différents.
Kevin Sitze
7
@BarAkiva, la raison pour laquelle c'est faux est que vous perdez la sécurité de type. Si vous renvoyez des valeurs d'un type homogène, vous devriez toujours préférer une liste à un tableau. En particulier, si vous avez affaire à des valeurs génériques, alors un List <T> est toujours préféré comme valeur de retour à T [] car vous pouvez toujours construire un List sur un type générique mais jamais un tableau; vous ne pouvez pas faire ceci: "new T [length];" L'approche de création d'une classe Pair comme indiqué ici pour les types disparates est une meilleure option pour les types hétérogènes.
Kevin Sitze
41

Vous pouvez implémenter un générique Pairsi vous êtes sûr que vous n'avez qu'à renvoyer deux valeurs:

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

puis demandez à la méthode de renvoyer que Pair:

public Pair<Object, Object> getSomePair();
Lars Andren
la source
À quoi ressemblerait le retour de cette méthode?
Jwan622
Quelque chose du genre: pair = new Pair (thing1, thing2) .... return pair;
Lars Andren
27

Vous ne pouvez renvoyer qu'une seule valeur en Java, donc le moyen le plus simple est comme ceci:

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

Voici une version mise à jour de votre code:

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
la source
8

Voici la solution vraiment simple et courte avec SimpleEntry:

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

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

Utilise uniquement les fonctions intégrées de Java et il est livré avec l'avantage de la sécurité de type.

Code quatre-vingt-dix-neuf point neuf
la source
6

vous devez utiliser des collections pour renvoyer plus d'une valeur de retour

dans votre cas, vous écrivez votre code comme

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
la source
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
la source
4

Utilisez un objet de type Pair / Tuple, vous n'avez même pas besoin d'en créer un si vous dépendez d'Apache commons-lang. Utilisez simplement la classe Pair .

UtilisateurF40
la source
Pourquoi n'est-ce pas plus voté?
Rauni Lillemets le
3

Je suis curieux de savoir pourquoi personne n'a proposé la solution de rappel la plus élégante. Ainsi, au lieu d'utiliser un type de retour, vous utilisez un gestionnaire passé dans la méthode en tant qu'argument. L'exemple ci-dessous présente les deux approches contrastées. Je sais lequel des deux est le plus élégant pour moi. :-)

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
la source
2

Vous n'avez pas besoin de créer votre propre classe pour renvoyer deux valeurs différentes. Utilisez simplement un HashMap comme celui-ci:

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

Vous bénéficiez même de la sécurité de type.

Code quatre-vingt-dix-neuf point neuf
la source
2
Vous n'avez même pas besoin d'un HashMap, utilisez simplement un SimpleEntry!
Xerus
Pourquoi un HashMap, puis-je demander? Cela semble être une structure de données étrange à utiliser ici.
Neil Chowdhury
@Neil Chowdhury Aucune autre raison que parce qu'il s'agit d'une classe intégrée de manière pratique prenant deux paramètres définissables. Comme l'a souligné Xerus, AbstractMap.SimpleEntry est l'option la plus légère ici. Veuillez voir la réponse correspondante ci-dessous!
Code ninetyninepointnine
2

À mon avis, le mieux est de créer une nouvelle classe dont le constructeur est la fonction dont vous avez besoin, par exemple:

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

Ensuite, utilisez simplement le constructeur comme vous utiliseriez la fonction:

pairReturn pR = new pairReturn(15);

et vous pouvez utiliser pR.sth1, pR.sth2 comme "2 résultats de la fonction"

Jacob
la source
1

Vous pouvez également envoyer des objets mutables en tant que paramètres, si vous utilisez des méthodes pour les modifier, ils seront modifiés lorsque vous reviendrez de la fonction. Cela ne fonctionnera pas sur des choses comme Float, car il est immuable.

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

Le résultat est: Rutger

Andreas
la source
1

Renvoyer un tableau d'objets

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

Premièrement, il serait préférable que Java ait des tuples pour renvoyer plusieurs valeurs.

Deuxièmement, codez la Pairclasse la plus simple possible ou utilisez un tableau.

Mais, si vous avez besoin de retourner une paire, pensez à ce concept , il représente ( en commençant par ses noms de champs, puis le nom de la classe) - et si elle joue un rôle plus important que vous pensiez, et si cela aiderait votre conception globale d'avoir un abstraction explicite pour cela. Peut - être un code hint...
S'il vous plaît Note: Je ne suis pas dogmatiquement en disant qu'il va aider, mais juste pour regarder, pour voir si elle fait ... ou si elle ne fonctionne pas.

hyperpallium
la source
-7

et voici comment vous le faites dans JS: return { objA, valueB }. Je sais que c'est hors sujet, mais je ne peux pas m'abstenir de laisser ce commentaire après avoir vu comment une toute nouvelle classe doit être implémentée en Java. JavaScript - arrêtez de perdre votre vie et commencez à créer des scripts!

zavr
la source