Как вернуть 2 значения из метода Java?

179

Я пытаюсь вернуть 2 значения из метода Java, но я получаю эти ошибки. Вот мой код:

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

Ошибка:

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 Результат: 1

javaLearner.java
источник
1
Должен ли этот дубликат идти наоборот? Ответ здесь кажется лучше.
J Ричард Снейп

Ответы:

240

Вместо того, чтобы возвращать массив, содержащий два значения, или использовать универсальный Pairкласс, рассмотрите возможность создания класса, представляющего результат, который вы хотите вернуть, и возврата экземпляра этого класса. Дайте классу значимое имя. Преимущества этого подхода по сравнению с использованием массива - безопасность типов, и это сделает вашу программу намного проще для понимания.

Примечание. Универсальный Pairкласс, как предлагается в некоторых других ответах, здесь также обеспечивает безопасность типов, но не передает то, что представляет результат.

Пример (в котором не используются действительно значимые имена):

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
источник
1
Это был бы мой предпочтительный маршрут - предположительно пара чисел имеет какое-то значение, и было бы неплохо, если бы возвращаемый тип представлял это.
Арманд
3
Вы можете использовать SimpleEntry <type_of_value_1, type_of_value_2> из java.util.AbstractMap.SimpleEntry и использовать его с getKey (), чтобы получить объект 1, и getValue (), чтобы получить объект 2
Crystalonics,
45
Я очень сильно чувствую, что Java должна позволять вам возвращать несколько значений. Это было бы быстрее (создавалось меньше объектов) и не требовало бы дополнительных классов (раздутый код) каждый раз, когда вы хотите сделать что-то немного другое. Я не вижу никаких недостатков, возможно, кто-то может просветить меня?
Крис Селин
Это просто обходной вопрос для заданного вопроса, который все еще стоит «как вернуть 2 значения из метода, как мы делаем в Python».
Анум Шераз
4
@AnumSheraz Ответ на вопрос «как… как в Python» таков: нет, потому что в Java нет такой языковой функции ...
Jesper
73

Java не поддерживает возврат нескольких значений. Вернуть массив значений.

// 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
источник
7
Это почти всегда неправильно, особенно если типы двух значений результата различны.
Кевин Ситце
7
@ BarAkiva, причина в том, что это неправильно, потому что вы теряете безопасность типов. Если вы возвращаете значения однородного типа, то вам всегда следует отдавать предпочтение списку, а не массиву. В частности, если вы имеете дело с универсальными значениями, то List <T> всегда предпочтительнее в качестве возвращаемого значения, чем T [], потому что вы всегда можете создать List по универсальному типу, но никогда не массиву; Вы не можете сделать это: "new T [length];" Подход к созданию класса Pair, как указано здесь для разнородных типов, является лучшим вариантом для разнородных типов.
Кевин Ситце
41

Вы можете реализовать универсальный, Pairесли вы уверены, что вам просто нужно вернуть два значения:

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

и затем метод возвращает Pair:

public Pair<Object, Object> getSomePair();
Ларс Андрен
источник
Как будет выглядеть возвращение этого метода?
Jwan622
Что-то вроде: пара = новая пара (вещь1, вещь2) .... вернуть пару;
Ларс Андрен
27

Вы можете вернуть только одно значение в Java, поэтому самый лучший способ выглядит так:

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

Вот обновленная версия вашего кода:

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
источник
8

Вот действительно простое и краткое решение с SimpleEntry:

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

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

Используются только встроенные функции Java, и это дает преимущество типа safty.

Код нинетининпоэтинина
источник
6

Вы должны использовать коллекции, чтобы вернуть более одного возвращаемого значения

в вашем случае вы пишете свой код как

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
источник
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

Используйте объект типа Pair / Tuple, вам даже не нужно создавать объект, если вы зависите от Apache commons-lang. Просто используйте класс Pair .

UserF40
источник
Почему это не более проголосовало?
Рауни Лиллемец
3

Мне любопытно, почему никто не придумал более элегантное решение для обратного вызова. Поэтому вместо использования возвращаемого типа вы используете обработчик, переданный в метод в качестве аргумента. Пример ниже имеет два противоположных подхода. Я знаю, какой из этих двух вариантов более элегантен для меня. :-)

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);
        });
    }
}
Стив О 1969
источник
2

Вам не нужно создавать свой собственный класс для возврата двух разных значений. Просто используйте HashMap, как это:

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

У вас даже есть преимущество безопасности типов.

Код нинетининпоэтинина
источник
2
Вам даже не нужен HashMap, просто используйте SimpleEntry!
Xerus
Почему HashMap, могу я спросить? Это кажется странной структурой данных для использования здесь.
Нил Чоудхури
@Neil Chowdhury Нет другой причины, кроме как потому, что это удобно встроенный класс, принимающий два определяемых параметра. Как указал Xerus, AbstractMap.SimpleEntry является более легким вариантом здесь. Пожалуйста, смотрите соответствующий ответ ниже!
Код ninetyninepointnine
2

На мой взгляд, лучше всего создать новый класс, конструктор которого является необходимой вам функцией, например:

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

Затем просто используйте конструктор, как если бы вы использовали функцию:

pairReturn pR = new pairReturn(15);

и вы можете использовать pR.sth1, pR.sth2 как «2 результата функции»

Иаков
источник
1

Вы также можете отправлять изменяемые объекты в качестве параметров, если вы используете методы для их изменения, они будут изменены, когда вы вернетесь из функции. Он не будет работать с такими вещами, как Float, так как он неизменен.

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

Результат: Рутгер

Andreas
источник
1

Вернуть массив объектов

private static Object[] f () 
{ 
     double x =1.0;  
     int y= 2 ;
     return new Object[]{Double.valueOf(x),Integer.valueOf(y)};  
}
MC
источник
0

Во-первых, было бы лучше, если бы в Java были кортежи для возврата нескольких значений.

Во-вторых, используйте самый простой код Pair класс или используйте массив.

Но, если вы делаете потребность вернуть пару, рассмотрим , что концепция представляет (начиная с его имена полей, то имя класса) - и играет ли большую роль , чем вы думали, и если это поможет ваш общий дизайн , чтобы иметь явная абстракция для него. Может быть, это code hint...
Пожалуйста, обратите внимание: я не догматично говорю, что это поможет, а просто смотрю, чтобы увидеть, если это ... или если нет.

hyperpallium
источник
-7

и это, как вы это делаете в JS: return { objA, valueB }. Я знаю, что это оффтоп, но я не могу оставить этот комментарий, увидев, как в Java должен быть реализован целый новый класс. JavaScript - перестань тратить свою жизнь и начни писать сценарии!

Zavr
источник