Làm thế nào để trả về 2 giá trị từ một phương thức Java?


179

Tôi đang cố gắng trả về 2 giá trị từ một phương thức Java nhưng tôi gặp các lỗi này. Đây là mã của tôi:

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

Lỗi:

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)

Kết quả Java: 1


1
Có nên trùng lặp đi ngược lại? Câu trả lời ở đây có vẻ tốt hơn.
J Richard Snape

Câu trả lời:


239

Thay vì trả về một mảng chứa hai giá trị hoặc sử dụng một Pairlớp chung , hãy xem xét việc tạo một lớp biểu thị kết quả mà bạn muốn trả về và trả về một thể hiện của lớp đó. Đặt cho lớp một cái tên ý nghĩa. Lợi ích của phương pháp này so với việc sử dụng một mảng là an toàn kiểu và nó sẽ giúp chương trình của bạn dễ hiểu hơn nhiều.

Lưu ý: Một Pairlớp chung , như được đề xuất trong một số câu trả lời khác ở đây, cũng cung cấp cho bạn loại an toàn, nhưng không truyền đạt được kết quả đại diện cho điều gì.

Ví dụ (không sử dụng tên thực sự có ý nghĩa):

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
Đây sẽ là tuyến ưa thích của tôi - có lẽ cặp số này có một số ý nghĩa và sẽ rất tuyệt nếu kiểu trả về đại diện cho điều này.
Armand

3
Bạn có thể sử dụng SimpleEntry <type_of_value_1, type_of_value_2> từ java.util.AbaugeMap.SimpleEntry và sử dụng nó với getKey () để lấy đối tượng 1 và getValue () để lấy đối tượng 2
Crystalonics

45
Tôi cảm thấy rất mạnh mẽ rằng Java sẽ cho phép bạn trả về nhiều giá trị. Nó sẽ nhanh hơn (ít đối tượng được tạo hơn) và sẽ không yêu cầu các lớp bổ sung (mã cồng kềnh) mỗi khi bạn muốn làm điều gì đó khác đi một chút. Tôi không thấy bất kỳ nhược điểm nào, có lẽ ai đó có thể khai sáng cho tôi?
Chris Seline

Đây chỉ là một cách giải quyết cho câu hỏi được hỏi, vẫn còn "cách trả về 2 giá trị từ phương thức giống như chúng ta làm trong Python".
Anum Sheraz

4
@AnumSheraz Câu trả lời cho "cách ... giống như trong Python" là: bạn không, bởi vì Java không có tính năng ngôn ngữ như vậy ...
Jesper

73

Java không hỗ trợ trả về đa giá trị. Trả về một mảng các giá trị.

// 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
Điều này hầu như luôn luôn là điều sai lầm, đặc biệt là nếu các loại của hai giá trị kết quả là khác nhau.
Kevin Sitze

7
@BarAkiva, lý do là sai vì bạn mất loại an toàn. Nếu bạn đang trả về các giá trị của loại đồng nhất thì bạn nên luôn thích Danh sách trên một mảng. Cụ thể, nếu bạn đang xử lý các giá trị chung thì Danh sách <T> luôn được ưu tiên là giá trị trả về trên T [] vì bạn luôn có thể tạo Danh sách theo loại chung nhưng không bao giờ là mảng; bạn không thể làm điều này: "T mới [chiều dài];" Cách tiếp cận của việc tạo một lớp Cặp như được chỉ ra ở đây cho các loại khác nhau là một lựa chọn tốt hơn cho các loại không đồng nhất.
Kevin Sitze

41

Bạn có thể triển khai chung chung Pairnếu bạn chắc chắn rằng bạn chỉ cần trả về hai giá trị:

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

và sau đó có phương thức trả về rằng Pair:

public Pair<Object, Object> getSomePair();

Sự trở lại của phương pháp này sẽ như thế nào?
Jwan622

Một cái gì đó dọc theo dòng: cặp = cặp mới (thing1, thing2) .... cặp trả về;
Lars Andren

27

Bạn chỉ có thể trả về một giá trị trong Java, vì vậy cách gọn gàng nhất là như sau:

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

Đây là phiên bản cập nhật của mã của bạn:

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

Đây là giải pháp thực sự đơn giản và ngắn gọn với SimpleEntry:

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

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

Chỉ sử dụng các hàm dựng sẵn của Java và nó đi kèm với lợi ích an toàn kiểu.


6

bạn phải sử dụng các bộ sưu tập để trả về nhiều hơn một giá trị trả về

trong trường hợp của bạn, bạn viết mã của bạn là

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

Sử dụng một đối tượng loại Ghép / Tuple, bạn thậm chí không cần tạo một đối tượng nếu bạn phụ thuộc vào Apache commons-lang. Chỉ cần sử dụng lớp Cặp .


Tại sao điều này không được nâng cao hơn?
Rauni Lillemets

3

Tôi tò mò về lý do tại sao không ai nghĩ ra giải pháp gọi lại thanh lịch hơn. Vì vậy, thay vì sử dụng kiểu trả về, bạn sử dụng một trình xử lý được truyền vào phương thức làm đối số. Ví dụ dưới đây có hai cách tiếp cận tương phản. Tôi biết cái nào trong số hai là thanh lịch hơn đối với tôi. :-)

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

Bạn không cần tạo lớp riêng để trả về hai giá trị khác nhau. Chỉ cần sử dụng HashMap như thế này:

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

Bạn thậm chí có lợi ích của loại an toàn.


2
Bạn thậm chí không cần HashMap, chỉ cần sử dụng SimpleEntry!
Xerus

Tại sao một HashMap, tôi có thể hỏi? Đó dường như là một cấu trúc dữ liệu lạ để sử dụng ở đây.
Neil Chowdhury

@Neil Chowdhury Không có lý do nào khác ngoài vì đây là Lớp tích hợp thuận tiện, có hai tham số có thể xác định. Như Xerus đã chỉ ra, AbstractMap.SimpleEntry là tùy chọn nhẹ hơn ở đây. Xin vui lòng xem câu trả lời tương ứng dưới đây!
Mã ninetyninepointnine

2

Theo tôi, tốt nhất là tạo một lớp mới mà hàm tạo là hàm bạn cần, vd:

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

Sau đó, chỉ cần sử dụng hàm tạo như bạn sẽ sử dụng hàm:

pairReturn pR = new pairReturn(15);

và bạn có thể sử dụng pR.sth1, pR.sth2 làm "2 kết quả của hàm"


1

Bạn cũng có thể gửi các đối tượng có thể thay đổi dưới dạng tham số, nếu bạn sử dụng các phương thức để sửa đổi chúng thì chúng sẽ được sửa đổi khi bạn trở về từ hàm. Nó sẽ không hoạt động trên những thứ như Float, vì nó là bất biến.

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

Kết quả là:


1

Trả về một mảng các đối tượng

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

0

Đầu tiên, sẽ tốt hơn nếu Java có các bộ dữ liệu để trả về nhiều giá trị.

Thứ hai, mã đơn giản nhất có thể Pair , hoặc sử dụng một mảng.

Nhưng, nếu bạn làm cần phải trả về một cặp, xem xét những gì khái niệm nó đại diện (bắt đầu với những cái tên lĩnh vực của mình, sau đó tên lớp) - và cho dù nó đóng một vai trò lớn hơn bạn nghĩ, và nếu nó sẽ giúp thiết kế tổng thể của bạn để có một trừu tượng rõ ràng cho nó. Có lẽ đó là một code hint...
Xin lưu ý: Tôi không nói một cách giáo điều rằng nó sẽ giúp ích, nhưng chỉ để nhìn, để xem nếu nó ... hoặc nếu nó không.


-7

và đây là cách bạn làm điều đó trong JS : return { objA, valueB }. Tôi biết điều đó không chính đáng, nhưng tôi không thể không để lại bình luận này sau khi thấy một lớp hoàn toàn mới phải được triển khai như thế nào trong Java. JavaScript - ngừng lãng phí cuộc sống của bạn và bắt đầu Scripting!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.