วิธีการคืนค่า 2 จากวิธีการจาวา?


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
ที่ซ้ำกันควรไปในทางอื่น ๆ ? คำตอบที่นี่ดูเหมือนจะดีกว่า
J Richard Snape

คำตอบ:


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

1
นี่จะเป็นเส้นทางที่ฉันต้องการ - สมมุติว่าคู่ของตัวเลขมีความหมายบางอย่างและมันจะดีถ้าประเภทผลตอบแทนเป็นตัวแทนของสิ่งนี้
อาร์มันด์

3
คุณสามารถใช้ SimpleEntry <type_of_value_1, type_of_value_2> จาก java.util.AbstractMap.SimpleEntry และใช้กับ getKey () เพื่อรับ object 1 และ getValue () เพื่อรับ object 2
Crystalonics

45
ฉันรู้สึกอย่างยิ่งว่า Java ควรอนุญาตให้คุณคืนค่าหลาย ๆ ค่า มันจะเร็วขึ้น (สร้างวัตถุน้อยลง) และไม่ต้องการคลาสพิเศษ (โค้ดป่อง) ทุกครั้งที่คุณต้องการทำบางสิ่งที่แตกต่าง ฉันไม่เห็นข้อเสียใด ๆ บางทีใครบางคนสามารถสอนฉันได้?
Chris Seline

นี่เป็นเพียงการแก้ปัญหาสำหรับคำถามที่ถามซึ่งยังคงเป็น "วิธีการคืนค่า 2 ค่าจากวิธีเหมือนกับที่เราทำใน Python"
Anum Sheraz

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
นี่เป็นสิ่งที่ผิดโดยเฉพาะอย่างยิ่งโดยเฉพาะอย่างยิ่งหากประเภทของค่าผลลัพธ์ทั้งสองนั้นแตกต่างกัน
Kevin Sitze

7
@ BarAkiva เหตุผลที่ผิดเพราะคุณหลวมความปลอดภัยประเภท หากคุณคืนค่าประเภทที่เป็นเนื้อเดียวกันคุณควรเลือก List มากกว่าอาร์เรย์ โดยเฉพาะอย่างยิ่งหากคุณกำลังจัดการกับค่าทั่วไปดังนั้นรายการ <T> จึงเป็นที่ต้องการของผลตอบแทนมากกว่า T [] เพราะคุณสามารถสร้างรายการบนประเภททั่วไป แต่ไม่เคยมีอาร์เรย์ คุณไม่สามารถทำได้: "new T [length];" วิธีการสร้างคลาส Pair ตามที่ระบุไว้ที่นี่สำหรับประเภทที่แตกต่างกันเป็นตัวเลือกที่ดีกว่าสำหรับประเภทที่ต่างกัน
Kevin Sitze

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

บางสิ่งบางอย่างตามสายของ: pair = new Pair (thing1, thing2) .... ส่งคืนคู่;
Lars Andren

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 ที่มีในตัวเท่านั้นและมาพร้อมกับประโยชน์ความปลอดภัยประเภท


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

ใช้ออบเจ็กต์แบบคู่ / Tuple คุณไม่จำเป็นต้องสร้างมันหากคุณใช้ Apache Commons-lang เพียงใช้คลาสPair


เหตุใดจึงไม่อัปโหลดมากกว่านี้
Rauni Lillemets

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

@ Neil Chowdhury ไม่มีเหตุผลอื่นนอกจากเพราะมันเป็นคลาสที่ติดตั้งในตัวเพื่อรับพารามิเตอร์ที่กำหนดได้สองแบบ 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 results of the function"


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

ผลลัพธ์คือ: Rutger


1

ส่งกลับอาร์เรย์ของวัตถุ

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

0

อันดับแรกจะเป็นการดีกว่าถ้า Java มี tuples สำหรับส่งคืนค่าหลายค่า

ประการที่สองโค้ดที่ง่ายที่สุด Pairคลาสที่หรือใช้อาเรย์

แต่ถ้าคุณทำจำเป็นที่จะต้องกลับมาคู่ให้พิจารณาสิ่งที่เป็นแนวคิดมันหมายถึง (เริ่มต้นด้วยชื่อเขตของมันแล้วชื่อชั้น) - และไม่ว่าจะมีบทบาทที่มีขนาดใหญ่กว่าที่คุณคิดและถ้ามันจะช่วยให้การออกแบบโดยรวมของคุณที่จะมีการ นามธรรมที่ชัดเจนสำหรับมัน อาจจะเป็นcode hint...
โปรดทราบ: ฉันไม่ได้พูดอย่างดื้อรั้นว่าจะช่วยได้ แต่แค่มองดูเพื่อดูว่ามันทำ ... หรือไม่


-7

และนี่คือวิธีที่คุณทำมันใน return { objA, valueB }JS: ฉันรู้ว่ามันเป็นความผิดพลาด แต่ฉันไม่สามารถละเว้นความคิดเห็นนี้หลังจากเห็นว่าคลาสใหม่ทั้งหมดจะต้องถูกนำไปใช้ใน Java JavaScript - หยุดการสูญเสียชีวิตของคุณและเริ่มการเขียนสคริปต์!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.