Como retornar 2 valores de um método Java?

179

Estou tentando retornar 2 valores de um método Java, mas recebo esses erros. Aqui está o meu 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);
}

Erro:

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
fonte
1
Essa duplicata deve seguir o contrário? A resposta aqui parece melhor.
J Richard Snape

Respostas:

239

Em vez de retornar uma matriz que contém os dois valores ou usar uma Pairclasse genérica , considere criar uma classe que represente o resultado que você deseja retornar e retorne uma instância dessa classe. Dê à classe um nome significativo. Os benefícios dessa abordagem sobre o uso de uma matriz são a segurança de tipo e isso facilitará a compreensão do seu programa.

Nota: Uma Pairclasse genérica , conforme proposto em algumas das outras respostas aqui, também fornece segurança de digitação, mas não transmite o que o resultado representa.

Exemplo (que não usa nomes 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
fonte
1
Essa seria minha rota preferida - presumivelmente o par de números tem algum significado e seria bom se o tipo de retorno representasse isso.
Armand
3
Você pode usar SimpleEntry <type_of_value_1, type_of_value_2> from java.util.AbstractMap.SimpleEntry e usá-lo com getKey () para obter objeto 1 e getValue () para obter o objeto 2
Crystalonics
45
Sinto fortemente que o Java deve permitir que você retorne vários valores. Seria mais rápido (menos objetos criados) e não exigiria classes extras (código inchado) toda vez que você quiser fazer algo um pouco diferente. Não vejo desvantagens, talvez alguém possa me esclarecer?
precisa
Esta é apenas uma solução alternativa para a pergunta feita, que ainda significa "como retornar 2 valores do método, como fazemos no Python".
Anum Sheraz
4
@AnumSheraz A resposta à pergunta "como ... como em Python" é: você não faz, porque Java não tem tal recurso de linguagem ...
Jesper
73

Java não suporta retornos com vários valores. Retorne uma 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]);
}
Matt
fonte
7
Isso quase sempre é a coisa errada a se fazer, especialmente se os tipos dos dois valores de resultado forem diferentes.
Kevin Sitze
7
@BarAkiva, o motivo está errado é porque você perde a segurança do tipo. Se você estiver retornando valores de um tipo homogêneo, deverá sempre preferir uma Lista a uma matriz. Em particular, se você estiver lidando com valores genéricos, uma Lista <T> sempre será preferida como um valor de retorno sobre T [], porque você sempre poderá construir uma Lista em um tipo genérico, mas nunca em uma matriz; você não pode fazer isso: "new T [length];" A abordagem de criar uma classe Pair, conforme indicado aqui para tipos diferentes, é uma opção melhor para tipos heterogêneos.
Kevin Sitze
41

Você pode implementar um genérico Pairse tiver certeza de que precisa retornar apenas dois 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

e depois faça com que o método retorne Pair:

public Pair<Object, Object> getSomePair();
Lars Andren
fonte
Como seria o retorno desse método?
Jwan622
Algo parecido com: pair = new Pair (coisa1, coisa2) .... retornar par;
Lars Andren
27

Você pode retornar apenas um valor em Java, portanto, a maneira mais limpa é a seguinte:

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

Aqui está uma versão atualizada do seu 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
fonte
8

Aqui está a solução realmente simples e curta com o SimpleEntry:

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

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

Utiliza apenas funções internas do Java e vem com o tipo de segurança safty.

Código noventa e nove
fonte
6

você precisa usar coleções para retornar mais de um valor de retorno

no seu caso, você escreve seu 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
fonte
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
fonte
4

Use um objeto do tipo Pair / Tuple, você nem precisará criar um se você depender do Apache commons-lang. Basta usar a classe Pair .

UserF40
fonte
Por que isso não é mais votado?
Rauni Lillemets
3

Estou curioso para saber por que ninguém criou a solução de retorno de chamada mais elegante. Portanto, em vez de usar um tipo de retorno, você usa um manipulador passado no método como argumento. O exemplo abaixo tem as duas abordagens contrastantes. Eu sei qual dos dois é mais elegante para mim. :-)

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

Você não precisa criar sua própria classe para retornar dois valores diferentes. Basta usar um 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);
}

Você ainda tem o benefício de segurança de tipo.

Código noventa e nove
fonte
2
Você nem precisa de um HashMap, basta usar um SimpleEntry!
Xerus 10/10
Por que um HashMap, posso perguntar? Parece uma estrutura de dados estranha para usar aqui.
Neil Chowdhury
@Neil Chowdhury Não há outro motivo senão porque é uma classe convenientemente incorporada que aceita dois parâmetros definíveis. Como Xerus apontou, AbstractMap.SimpleEntry é a opção mais leve aqui. Por favor, veja a resposta correspondente abaixo!
Code ninetyninepointnine
2

Na minha opinião, o melhor é criar uma nova classe cujo construtor é a função que você precisa, por exemplo:

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

Em seguida, basta usar o construtor como você usaria a função:

pairReturn pR = new pairReturn(15);

e você pode usar pR.sth1, pR.sth2 como "2 resultados da função"

Jacob
fonte
1

Você também pode enviar objetos mutáveis ​​como parâmetros, se você usar métodos para modificá-los, eles serão modificados quando você retornar da função. Não funcionará em coisas como Float, pois é imutável.

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

O resultado é: Rutger

Andreas
fonte
1

Retornar uma matriz de objetos

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

Primeiro, seria melhor se o Java tivesse tuplas para retornar vários valores.

Segundo, codifique a Pairclasse mais simples possível ou use uma matriz.

Mas, se você fazer necessidade de voltar um par, considere o conceito que ela representa (começando com seus nomes de campos, em seguida, nome da classe) - e se desempenha um papel maior do que se pensava, e se ele iria ajudar a sua concepção global para ter uma abstração explícita para ele. Talvez seja um code hint...
Por favor, note: Eu não estou dizendo que dogmaticamente vai ajudar, mas apenas para olhar, para ver se ele faz ... ou se isso não acontecer.

hiperpálio
fonte
-7

e isso é como você fazê-lo em JS: return { objA, valueB }. Eu sei que é offtopic, mas não posso me abster de deixar esse comentário depois de ver como toda uma nova classe deve ser implementada em Java. JavaScript - pare de desperdiçar sua vida e comece a criar scripts!

zavr
fonte