¿Cómo devolver 2 valores de un método Java?

179

Estoy tratando de devolver 2 valores de un método Java pero obtengo estos errores. Aquí está mi código:

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

Resultado Java: 1

javaLearner.java
fuente
1
¿Debería ese duplicado ir al revés? La respuesta aquí parece mejor.
J Richard Snape

Respuestas:

240

En lugar de devolver una matriz que contenga los dos valores o usar una Pairclase genérica , considere crear una clase que represente el resultado que desea devolver y devuelva una instancia de esa clase. Dale a la clase un nombre significativo. Los beneficios de este enfoque sobre el uso de una matriz son la seguridad de tipo y hará que su programa sea mucho más fácil de entender.

Nota: Una Pairclase genérica , como se propone en algunas de las otras respuestas aquí, también le da seguridad de tipo, pero no transmite lo que representa el resultado.

Ejemplo (que no usa nombres realmente significativos):

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
fuente
1
Esta sería mi ruta preferida, presumiblemente el par de números tiene algún significado, y sería bueno si el tipo de retorno representara esto.
Armand
3
Puede usar SimpleEntry <type_of_value_1, type_of_value_2> de java.util.AbstractMap.SimpleEntry y usarlo con getKey () para obtener el objeto 1 y getValue () para obtener el objeto 2
Crystalonics
45
Creo firmemente que Java debería permitirle devolver múltiples valores. Sería más rápido (menos objetos creados) y no requeriría clases adicionales (código hinchado) cada vez que quiera hacer algo un poco diferente. No veo inconvenientes, ¿tal vez alguien pueda iluminarme?
Chris Seline
Esto es solo una solución alternativa para la pregunta formulada, que todavía significa "cómo devolver 2 valores del método al igual que lo hacemos en Python".
Anum Sheraz
44
@AnumSheraz La respuesta a "cómo ... al igual que en Python" es: no, porque Java no tiene esa función de lenguaje ...
Jesper
73

Java no admite devoluciones de valores múltiples. Devuelve una matriz de valores.

// 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]);
}
Mate
fuente
77
Esto es casi siempre algo incorrecto, especialmente si los tipos de los dos valores de resultados son diferentes.
Kevin Sitze
77
@BarAkiva, la razón por la que está mal es porque pierdes la seguridad del tipo. Si devuelve valores de un tipo homogéneo, siempre debe preferir una Lista sobre una matriz. En particular, si se trata de valores genéricos, siempre se prefiere una Lista <T> como valor de retorno sobre T [] porque siempre se puede construir una Lista en un tipo genérico pero nunca una matriz; no puedes hacer esto: "new T [length];" El enfoque de crear una clase Pair como se indica aquí para tipos dispares es una mejor opción para tipos heterogéneos.
Kevin Sitze
41

Puede implementar un genérico Pairsi está seguro de que solo necesita devolver dos valores:

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

y luego haga que el método devuelva que Pair:

public Pair<Object, Object> getSomePair();
Lars Andren
fuente
¿Cómo sería el regreso de este método?
Jwan622
Algo similar a: pair = new Pair (thing1, thing2) .... return pair;
Lars Andren
27

Solo puede devolver un valor en Java, por lo que la mejor manera es la siguiente:

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

Aquí hay una versión actualizada de su código:

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
fuente
8

Aquí está la solución realmente simple y corta con SimpleEntry:

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

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

Solo utiliza funciones integradas en Java y viene con el beneficio de tipo seguro.

Código noventa y nueve puntos
fuente
6

tienes que usar colecciones para devolver más de un valor de retorno

en tu caso escribes tu código como

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
fuente
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
fuente
4

Use un objeto de tipo Par / Tupla, ni siquiera necesita crear uno si depende de Apache commons-lang. Solo usa la clase Pair .

UsuarioF40
fuente
¿Por qué no es esto más votado?
Rauni Lillemets
3

Tengo curiosidad por saber por qué a nadie se le ocurrió la solución de devolución de llamada más elegante. Entonces, en lugar de usar un tipo de retorno, usa un controlador pasado al método como argumento. El siguiente ejemplo tiene los dos enfoques contrastantes. Sé cuál de los dos es más elegante para mí. :-)

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
fuente
2

No necesita crear su propia clase para devolver dos valores diferentes. Solo usa un HashMap como este:

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

Incluso tiene el beneficio de la seguridad tipográfica.

Código noventa y nueve puntos
fuente
2
Ni siquiera necesita un HashMap, ¡solo use un SimpleEntry!
Xerus
¿Por qué un HashMap, puedo preguntar? Parece una estructura de datos extraña para usar aquí.
Neil Chowdhury
@Neil Chowdhury No hay otra razón que no sea porque es una Clase convenientemente integrada que toma dos parámetros definibles. Como Xerus señaló, AbstractMap.SimpleEntry es la opción más ligera aquí. Por favor, consulte la respuesta correspondiente a continuación!
Código noventa y nueve puntos el
2

En mi opinión, lo mejor es crear una nueva clase cuyo constructor sea la función que necesita, por ejemplo:

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

Luego simplemente use el constructor como usaría la función:

pairReturn pR = new pairReturn(15);

y puede usar pR.sth1, pR.sth2 como "2 resultados de la función"

Jacob
fuente
1

También puede enviar objetos mutables como parámetros, si utiliza métodos para modificarlos, se modificarán cuando regrese de la función. No funcionará en cosas como Float, ya que es inmutable.

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

El resultado es: Rutger

Andreas
fuente
1

Devolver una matriz de objetos

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

Primero, sería mejor si Java tuviera tuplas para devolver múltiples valores.

Segundo, codifique la Pairclase más simple posible , o use una matriz.

Pero, si lo hace la necesidad de volver un par, considere lo que el concepto que representa (empezando por sus nombres de campo, a continuación, nombre de la clase) - y si desempeña un papel más importante de lo que pensaba, y si sería ayudar a su diseño general para tener una abstracción explícita para ello. Tal vez es un code hint...
Por favor Nota: No estoy diciendo que dogmáticamente se ayudar, pero sólo para mirar, a ver si lo hace o no ... si lo hace.

hiperpallium
fuente
-7

y así es como lo haces en JS: return { objA, valueB }. Sé que no es un tema, pero no puedo abstenerme de dejar este comentario después de ver cómo se debe implementar una clase completamente nueva en Java. JavaScript: ¡deja de malgastar tu vida y comienza a crear secuencias de comandos!

zavr
fuente