Як повернути 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


1
Чи повинен цей дублікат навпаки? Відповідь тут здається кращою.
Дж. Річард Снейп

Відповіді:


239

Замість повернення масиву, який містить два значення або використання загального 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());
}

1
Це був би мій кращий маршрут - імовірно, пара чисел має певне значення, і було б добре, якби тип повернення представляв це.
Арман

3
Ви можете використовувати SimpleEntry <type_of_value_1, type_of_value_2> від java.util.Ab абстрактMap.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]);
}

7
Це майже завжди неправильно робити, особливо якщо типи двох значень результатів різні.
Кевін Сітце

7
@BarAkiva, причина неправильна в тому, що ви втрачаєте безпеку типу. Якщо ви повертаєте значення однорідного типу, то завжди слід віддавати перевагу списку над масивом. Зокрема, якщо ви маєте справу з загальними значеннями, тоді список <T> завжди є переважним як повернене значення над T [], оскільки ви завжди можете побудувати список на загальному типі, але ніколи не масив; ви не можете цього зробити: "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;
    }
}

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

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, вам навіть не потрібно створювати його, якщо u залежить від Apache commons-lang. Просто використовуйте клас Pair .


Чому це не прихильне?
Рауні Ліллемець,

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

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. Будь ласка, дивіться відповідну відповідь нижче!
Код дев'янотинеінтонін

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

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


1

Повернути масив об'єктів

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

0

По-перше, було б краще, якби у Java були кортежі для повернення кількох значень.

По-друге, кодуйте найпростіший можливий Pairклас або використовуйте масив.

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


-7

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.