Bagaimana cara mengembalikan 2 nilai dari metode Java?

179

Saya mencoba mengembalikan 2 nilai dari metode Java tapi saya mendapatkan kesalahan ini. Ini kode saya:

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

Kesalahan:

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)

Hasil Jawa: 1

javaLearner.java
sumber
1
Haruskah duplikat itu berputar sebaliknya? Jawabannya di sini sepertinya lebih baik.
J Richard Snape

Jawaban:

239

Alih-alih mengembalikan array yang berisi dua nilai atau menggunakan Pairkelas generik , pertimbangkan membuat kelas yang mewakili hasil yang ingin Anda kembalikan, dan kembalikan instance kelas itu. Beri kelas nama yang bermakna. Manfaat dari pendekatan ini dibandingkan menggunakan array adalah keamanan tipe dan itu akan membuat program Anda lebih mudah dimengerti.

Catatan: Kelas generik Pair, seperti yang diusulkan dalam beberapa jawaban lain di sini, juga memberi Anda keamanan mengetik, tetapi tidak memberikan hasil yang diwakilinya.

Contoh (yang tidak menggunakan nama yang benar-benar bermakna):

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
sumber
1
Ini akan menjadi rute pilihan saya - mungkin pasangan angka memiliki beberapa makna, dan alangkah baiknya jika tipe pengembalian mewakili ini.
Armand
3
Anda dapat menggunakan SimpleEntry <type_of_value_1, type_of_value_2> dari java.util.AbstractMap.SimpleEntry dan menggunakannya dengan getKey () untuk mendapatkan objek 1 dan getValue () untuk mendapatkan objek 2
Crystalonics
45
Saya merasa sangat kuat bahwa Java harus memungkinkan Anda mengembalikan beberapa nilai. Itu akan lebih cepat (lebih sedikit objek yang dibuat) dan tidak akan memerlukan kelas tambahan (kode kembung) setiap kali Anda ingin melakukan sesuatu yang sedikit berbeda. Saya tidak melihat kelemahan, mungkin seseorang dapat mencerahkan saya?
Chris Seline
Ini hanya solusi untuk pertanyaan yang diajukan, yang masih berdiri "bagaimana mengembalikan 2 nilai dari metode seperti yang kita lakukan dengan Python".
Anum Sheraz
4
@AnumSheraz Jawaban untuk "bagaimana ... persis seperti di Python" adalah: Anda tidak, karena Java tidak memiliki fitur bahasa seperti itu ...
Jesper
73

Java tidak mendukung pengembalian multi-nilai. Kembalikan array nilai.

// 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]);
}
Mat
sumber
7
Ini hampir selalu hal yang salah untuk dilakukan, terutama jika jenis dari kedua nilai hasil berbeda.
Kevin Sitze
7
@BarAkiva, alasannya salah adalah karena Anda kehilangan keamanan jenis. Jika Anda mengembalikan nilai tipe yang homogen maka Anda harus selalu lebih memilih Daftar daripada array. Khususnya, jika Anda berurusan dengan nilai generik maka Daftar <T> selalu lebih disukai sebagai nilai balik di atas T [] karena Anda selalu dapat membuat Daftar pada tipe generik tetapi tidak pernah array; Anda tidak dapat melakukan ini: "T baru [panjang];" Pendekatan menciptakan kelas Pair seperti yang ditunjukkan di sini untuk tipe yang berbeda adalah pilihan yang lebih baik untuk tipe yang heterogen.
Kevin Sitze
41

Anda bisa menerapkan generik Pairjika Anda yakin bahwa Anda hanya perlu mengembalikan dua nilai:

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

dan kemudian minta kembali metode itu Pair:

public Pair<Object, Object> getSomePair();
Lars Andren
sumber
Seperti apa kembalinya metode ini?
Jwan622
Sesuatu di sepanjang baris: pair = Pair baru (thing1, thing2) .... return pair;
Lars Andren
27

Anda hanya dapat mengembalikan satu nilai di Java, jadi cara yang paling rapi adalah seperti ini:

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

Ini versi terbaru dari kode Anda:

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
sumber
8

Inilah solusi yang sangat sederhana dan singkat dengan SimpleEntry:

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

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

Hanya menggunakan Java built-in functions dan ia datang dengan manfaat jenis keselamatan.

Kode ninetyninepointnine
sumber
6

Anda harus menggunakan koleksi untuk mengembalikan lebih dari satu nilai pengembalian

dalam kasus Anda, Anda menulis kode Anda sebagai

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
sumber
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
sumber
4

Gunakan objek jenis Pair / Tuple, Anda bahkan tidak perlu membuatnya jika Anda bergantung pada Apache commons-lang. Cukup gunakan kelas Pair .

UserF40
sumber
Mengapa ini tidak lebih dipilih?
Rauni Lillemets
3

Saya ingin tahu mengapa tidak ada yang datang dengan solusi panggilan balik yang lebih elegan. Jadi, alih-alih menggunakan tipe pengembalian Anda menggunakan handler yang diteruskan ke metode sebagai argumen. Contoh di bawah ini memiliki dua pendekatan yang berbeda. Saya tahu yang mana dari keduanya yang lebih anggun bagi saya. :-)

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

Anda tidak perlu membuat kelas Anda sendiri untuk mengembalikan dua nilai yang berbeda. Cukup gunakan HashMap seperti ini:

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

Anda bahkan mendapatkan manfaat dari keamanan tipe.

Kode ninetyninepointnine
sumber
2
Anda bahkan tidak memerlukan HashMap, cukup gunakan SimpleEntry!
Xerus
Mengapa HashMap, boleh saya tanyakan? Itu tampak seperti struktur data yang aneh untuk digunakan di sini.
Neil Chowdhury
@Neil Chowdhury Tidak ada alasan lain selain karena itu adalah Kelas bawaan yang memiliki dua parameter yang dapat ditentukan. Seperti yang ditunjukkan Xerus, AbstractMap.SimpleEntry adalah pilihan yang lebih ringan di sini. Silakan lihat jawaban yang sesuai di bawah ini!
Kode ninetyninepointnine
2

Menurut pendapat saya yang terbaik adalah membuat kelas baru yang konstruktor adalah fungsi yang Anda butuhkan, misalnya:

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

Kemudian cukup gunakan konstruktor karena Anda akan menggunakan fungsi:

pairReturn pR = new pairReturn(15);

dan Anda dapat menggunakan pR.sth1, pR.sth2 sebagai "2 hasil dari fungsi"

Yakub
sumber
1

Anda juga dapat mengirim objek yang bisa berubah sebagai parameter, jika Anda menggunakan metode untuk memodifikasinya, mereka akan dimodifikasi ketika Anda kembali dari fungsi. Itu tidak akan bekerja pada hal-hal seperti Float, karena tidak dapat diubah.

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

Hasilnya adalah: Rutger

Andreas
sumber
1

Kembalikan Array Objek

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

Pertama, akan lebih baik jika Java memiliki tuple untuk mengembalikan beberapa nilai.

Kedua, kode sesederhana mungkin Pair kelas , atau gunakan array.

Tapi, jika Anda lakukan perlu untuk kembali sepasang, mempertimbangkan apa konsep yang diwakilinya (dimulai dengan nama field, maka nama kelas) - dan apakah itu memainkan peran yang lebih besar daripada yang Anda pikir, dan jika itu akan membantu desain Anda secara keseluruhan memiliki abstraksi eksplisit untuk itu. Mungkin itu code hint...
Tolong Catatan: Saya tidak dogmatis mengatakan itu akan membantu, tetapi hanya untuk melihat, untuk melihat apakah itu ... atau jika tidak.

hyperpallium
sumber
-7

dan ini adalah bagaimana Anda melakukannya dalam JS: return { objA, valueB }. Saya tahu ini offtopic, tapi saya tidak bisa meninggalkan komentar ini setelah melihat bagaimana seluruh kelas baru harus diimplementasikan di Jawa. JavaScript - berhenti menyia-nyiakan hidup Anda dan mulai Scripting!

zavr
sumber