Come restituire 2 valori da un metodo Java?


179

Sto cercando di restituire 2 valori da un metodo Java ma ottengo questi errori. Ecco il mio codice:

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

Errore:

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)

Risultato Java: 1


1
Quel duplicato dovrebbe andare al contrario? La risposta qui sembra migliore.
J Richard Snape,

Risposte:


239

Invece di restituire un array che contiene i due valori o utilizzare una Pairclasse generica , prendere in considerazione la creazione di una classe che rappresenti il ​​risultato che si desidera restituire e restituire un'istanza di quella classe. Dai alla classe un nome significativo. I vantaggi di questo approccio rispetto all'utilizzo di un array sono la sicurezza dei tipi e semplificheranno la comprensione del programma.

Nota: una Pairclasse generica , come proposto in alcune delle altre risposte qui, ti dà anche la sicurezza del tipo, ma non trasmette ciò che rappresenta il risultato.

Esempio (che non usa nomi veramente significativi):

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
Questo sarebbe il mio percorso preferito - presumibilmente la coppia di numeri ha qualche significato, e sarebbe bello se il tipo restituito rappresentasse questo.
Armand,

3
È possibile utilizzare SimpleEntry <type_of_value_1, type_of_value_2> da java.util.AbstractMap.SimpleEntry e utilizzarlo con getKey () per ottenere l'oggetto 1 e getValue () per ottenere l'oggetto 2
Crystalonics

45
Sono fermamente convinto che Java dovrebbe consentire di restituire più valori. Sarebbe più veloce (meno oggetti creati) e non richiederebbe classi extra (codice gonfio) ogni volta che vuoi fare qualcosa di leggermente diverso. Non vedo alcun aspetto negativo, forse qualcuno può illuminarmi?
Chris Seline,

Questo è solo un modo per aggirare la domanda posta, che sta ancora "come restituire 2 valori dal metodo proprio come facciamo in Python".
Anum Sheraz,

4
@AnumSheraz La risposta a "come ... proprio come in Python" è: no, perché Java non ha una tale funzione linguistica ...
Jesper,

73

Java non supporta i rendimenti multi-valore. Restituisce una matrice di valori.

// 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
Questa è quasi sempre la cosa sbagliata da fare, specialmente se i tipi dei due valori del risultato sono diversi.
Kevin Sitze,

7
@BarAkiva, il motivo per cui è sbagliato è perché perdi la sicurezza del tipo. Se si restituiscono valori di tipo omogeneo, è consigliabile preferire sempre un elenco a un array. In particolare, se hai a che fare con valori generici, allora un Elenco <T> è sempre preferito come valore di ritorno su T [] perché puoi sempre costruire un Elenco su un tipo generico ma mai un array; non puoi farlo: "new T [length];" L'approccio alla creazione di una classe Pair come indicato qui per tipi diversi è un'opzione migliore per i tipi eterogenei.
Kevin Sitze,

41

È possibile implementare un generico Pairse si è certi di dover solo restituire due valori:

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 quindi il metodo restituisce che Pair:

public Pair<Object, Object> getSomePair();

Come sarebbe il ritorno di questo metodo?
Jwan622

Qualcosa sulla falsariga di: pair = new Pair (thing1, thing2) .... return pair;
Lars Andren,

27

Puoi restituire un solo valore in Java, quindi il modo più accurato è questo:

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

Ecco una versione aggiornata del tuo codice:

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

Ecco la soluzione davvero semplice e breve con SimpleEntry:

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

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

Utilizza solo le funzioni integrate Java e viene fornito con il vantaggio safty di tipo.


6

devi utilizzare le raccolte per restituire più di un valore di ritorno

nel tuo caso scrivi il tuo codice come

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

Utilizzare un oggetto di tipo Pair / Tuple, non è nemmeno necessario crearne uno se si dipende da Apache commons-lang. Usa solo la classe Pair .


Perché questo non è più votato?
Rauni Lillemets,

3

Sono curioso di sapere perché nessuno abbia escogitato la soluzione di callback più elegante. Pertanto, anziché utilizzare un tipo restituito, si utilizza un gestore passato al metodo come argomento. L'esempio seguente ha i due approcci contrastanti. So quale dei due è più elegante per me. :-)

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

Non è necessario creare la propria classe per restituire due valori diversi. Basta usare una HashMap come questa:

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

Hai anche il vantaggio della sicurezza del tipo.


2
Non hai nemmeno bisogno di una HashMap, basta usare un SimpleEntry!
Xerus,

Perché una HashMap, posso chiedere? Sembra una strana struttura di dati da usare qui.
Neil Chowdhury,

@Neil Chowdhury Nessun altro motivo se non perché è una classe integrata che accetta due parametri definibili. Come ha sottolineato Xerus, AbstractMap.SimpleEntry è l'opzione più leggera qui. Si prega di consultare la risposta corrispondente di seguito!
Codice ninetyninepointnine,

2

Secondo me il migliore è creare una nuova classe quale costruttore sia la funzione di cui hai bisogno, ad es .:

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

Quindi utilizza semplicemente il costruttore come utilizzeresti la funzione:

pairReturn pR = new pairReturn(15);

e puoi usare pR.sth1, pR.sth2 come "2 risultati della funzione"


1

È inoltre possibile inviare oggetti mutabili come parametri, se si utilizzano metodi per modificarli, questi verranno modificati al ritorno dalla funzione. Non funzionerà su cose come Float, poiché è immutabile.

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

Il risultato è: Rutger


1

Restituisce una matrice di oggetti

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

0

Innanzitutto, sarebbe meglio se Java avesse tuple per restituire più valori.

In secondo luogo, codifica il più semplice possibile Pair classe o utilizzare un array.

Ma, se si fa necessità di tornare un paio, in considerazione ciò che il concetto che rappresenta (a partire con i suoi nomi di campo, quindi il nome della classe) - e se gioca un ruolo più importante di quanto si pensava, e se sarebbe aiutare il vostro disegno complessivo per avere un astrazione esplicita per questo. Forse è un code hint...
Si prega di notare: non sto dicendo che dogmaticamente vi aiuterà, ma solo per guardare, per vedere se lo fa ... o se non è così.


-7

e questo è come lo fate in JS: return { objA, valueB }. So che è offtopico, ma non posso astenermi dal lasciare questo commento dopo aver visto come una nuova classe deve essere implementata in Java. JavaScript: smetti di sprecare la tua vita e inizia a scrivere!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.