หลายค่าส่งคืนใน Java อย่างไร


11

บางครั้งคุณต้องการคืนค่าหลายค่าจากฟังก์ชัน ปกติแล้ววิธีนี้จะทำใน Java?

ทางเลือกหนึ่งคือใช้อาร์เรย์เช่นข้อมูลโค้ด Python ที่ส่งคืนรายการหรือทูเปิล:

value, success = read_unreliably()
if success:
    print value

ตัวเลือกอื่นคือการคืนค่าแฮช / dict เช่นตัวอย่าง JavaScript:

var result = readUnreliably()
if (result.success) {
    alert(value);
}

อีกหนึ่งการสร้างวัตถุที่กำหนดเองเพียงเพื่อวัตถุประสงค์นี้เช่นตัวอย่าง Java นี้:

ReadUnreliablyResult result = readUnreliably()
if (result.getSuccess()) {
    System.out.println(result.getValue());
}

แน่นอนคุณสามารถใช้ตัวแปรส่วนกลางบางอย่างเพื่อเก็บสิ่งที่คุณต้องการแทนที่จะส่งผ่านสิ่งต่าง ๆ แต่สมมติว่านั่นไม่ใช่ตัวเลือก


คน java "ของจริง" ต้องเผชิญกับปัญหาในการใช้ public getters และ setters เพื่อซ่อนเขตข้อมูลในคลาสภายในขนาดเล็กเช่นนั้นหรือไม่? แค่สงสัย.
Chris Farmer

3
ใช่ส่วนใหญ่ทำ เนื่องจากเฟรมเวิร์กจำนวนมากต้องการมาตรฐาน JavaBean คุณสามารถเสียใจที่ไม่มี getters และ setters ไม่ว่าในกรณีใด IDE ของคุณจะสร้างขึ้นมาเพื่อคุณ
Eric Wilson

3
หรือคุณสามารถปล่อยพวกเขาออกไปตามหลักการของ YAGNI แต่ดูเหมือนจะไม่เกิดขึ้นบ่อยเท่าที่ควร
MatrixFrog

@FarmBoy: ฉันคิดว่าฉันเข้าใจถั่วและเช่นนั้น แต่ OP หมายถึงว่านี่เป็นเพียงคลาสปิดที่ออกแบบมาเพื่อคืนค่าหลายค่า
Chris Farmer

@ChrisFarmer ฉันเดาว่าด้วยบริบทนั้นฉันไม่เคยเห็นโปรแกรมเมอร์ Java 'ของจริง' สร้างคลาสสำหรับวัตถุประสงค์นี้
Eric Wilson

คำตอบ:


26

ปกติแล้ววิธีนี้จะทำใน Java?

อย่างเจ็บปวด

ทางเลือกหนึ่งคือการใช้อาร์เรย์เช่นข้อมูลโค้ด Python ที่ส่งคืนรายการหรือทูเปิล ...

อีกตัวเลือกหนึ่งคือการส่งคืนแฮช / ดิกเช่นตัวอย่าง JavaScript นี้ ...

เทคนิคเหล่านี้ทำงานได้ไม่ดีใน Java; ค่าจะต้องมีการลดลงจากวัตถุ

อีกหนึ่งการสร้างวัตถุที่กำหนดเองเพียงเพื่อจุดประสงค์นี้เช่นตัวอย่าง Java นี้ ...

นี่เป็นเรื่องธรรมดาที่สุด แต่ก็น่าเบื่อที่จะสร้างชั้นเรียนเล็ก ๆ เหล่านั้นทั้งหมด ใน C ++ มันเป็นเรื่องธรรมดาที่จะใช้ std :: pair แต่สิ่งนี้ไม่ได้ทำกันโดยทั่วไปใน Java

ด้วยลอมบอกมันค่อนข้างง่ายที่จะสร้างวัตถุเล็ก ๆ น้อย ๆ ที่กำหนดเอง:

@RequiredArgsConstructor
public class X {
  private final boolean status;
  private final byte[] data;

}


10
"นี่เป็นวิธีปกติใน Java" "เจ็บปวด". lol ในฐานะนักพัฒนา Java ฉันต้อง +1 ให้คุณ
TheLQ

การใช้คลาสที่มีโครงสร้างแบบไม่เปลี่ยนรูปขนาดกะทัดรัดนั้นไม่เจ็บปวด ... มันเหมือนกับการเขียนโครงสร้าง C ...
Guillaume

1
@Gillaillaume - แน่นอน แต่สิ่งเล็ก ๆ น้อย ๆ เหล่านั้นเพิ่มขึ้นทั้งในเวลาและสถานที่ ฉันไม่รู้ว่าทำไมชุมชน Java ไม่ได้นำชุดมาตรฐานทั่วไปเช่น "class Pair <T1, T2> {public T1 first; public T2 second; ... }"; ในภาษาสมัยใหม่คุณเพียงแค่ "return a, b"; แล้วเขียน "x, y = f ()";
วินไคลน์

1
ฉันแน่ใจว่าภาษา 'โบราณ' บางอย่างก็สามารถทำได้เช่นกัน :) IMHO ฉันพบว่าค่าส่งคืนหลายรายการสามารถนำไปสู่ความยุ่งเหยิงโดยรวมและถ้าคุณต้องการเพิ่มเขตข้อมูลส่งคืนอื่นคุณเพียงแค่อัปเดต struct ของคุณเหมือนคลาส เปลี่ยนลายเซ็นวิธีการของคุณ
Guillaume

1
นั่น "เจ็บปวด" หลงฉันอย่างหนักใช่มันเป็นสิ่งที่ฉันรู้สึกว่าเป็นนักพัฒนา Java เมื่อฉันพบสถานการณ์ที่คล้ายกัน
artjom

13

ใช่วิธีในการสร้างstruct/ tuple/ recordใน Java คือการสร้างคลาส ถ้าเป็นการใช้ภายในเท่านั้นฉันชอบที่จะใช้คลาสที่มีลักษณะคล้ายโครงสร้างที่ไม่เปลี่ยนรูปกับเขตข้อมูลสาธารณะ

ตัวอย่าง:

public class Unreliably {
    public final boolean success;
    public final int value;
    public Unreliably(boolean success, int value) {
        this.success = success; this.value = value;
    }
}

การทำสิ่งนี้ทำได้ง่ายกว่าใน Scala:

case class Unreliably(success: Boolean, value: Int)

8
ที่จริงใน Scala Tuple2[Boolean, Int]คุณอาจต้องการโดยทั่วไปก็กลับ ถึงแม้ว่าในนี้เฉพาะOption[Int]ตัวอย่างเช่นคุณต้องการกลับ
Jörg W Mittag

2
ดังนั้นนี่จึงเป็นคำตอบสำหรับคำถามของ Chris Farmer (ในความคิดเห็นของ Q) ว่าคน Java จริงไม่จำเป็นต้องสร้าง getters และ setters สำหรับคลาสภายในเล็กน้อย คุณเป็นคน Java "ของจริง" ใช่ไหม?
Mike M. Lin

2
ในข่าวอื่น ๆ ไม่มีสกอตที่แท้จริง
Joseph Weissman

5

สำหรับตัวอย่างที่คุณให้ไว้การโยนข้อยกเว้นจะเป็นวิธีมาตรฐานที่สุดในการจัดการ:

try {
    result = readUnreliably();
    System.out.println(result);
} (catch IOException e) {
    System.out.println("Could not read file");
}

ยิ่งไปกว่านั้นหากคุณมุ่งมั่นที่จะมีฟังก์ชั่นที่ "ทำสิ่งเดียว" คุณสมบัติของการคืนค่าหลายค่านั้นไม่จำเป็น แต่สะดวกในบางครั้ง


4

เรามีคลาสทั่วไปแบบคู่ที่สามารถเก็บอินสแตนซ์หนึ่งของ A และอินสแตนซ์หนึ่งของ B คุณอาจสร้าง Triplet หรือ Quadruplet ในลักษณะเดียวกัน

public class Pair<A, B>
{
    ...
}

1
มันทำให้รหัสที่อ่านไม่ได้จริงๆ ถ้าเมธอดส่งคืนPair<String, Integer>หมายความว่าอย่างไร ค่าเหล่านี้แสดงถึงอะไร? คุณไม่สามารถรู้ได้หากไม่ได้อ่านวิธีการใช้งาน
ร่า

1

ใน Java ฟังก์ชั่นของคุณจะส่งคืนวัตถุ (หรืออาจเป็นโมฆะในกรณีที่เกิดความล้มเหลว) ด้วยวิธีนี้สามารถส่งคืนข้อมูลได้หลายชิ้น


1

ไม่มีวิธีที่ชัดเจนในการส่งคืนตัวแปรหลายตัวใน Java อย่างไรก็ตามมีวิธีการสองสามวิธี:

  1. สิ่งแรกคือไปตามทางของอาเรย์ วิธีนี้ใช้งานได้จริงถ้าคุณมีทุกอย่างที่เป็นชนิดข้อมูลเดียวกันหรือสามารถแปลงเป็นประเภทเดียวได้ชั่วคราว
  2. วิธีที่สองคือการสร้างคลาสเพื่อการถ่ายโอนตัวแปรหลายชนิด ที่ทำงานของฉันเราอ้างถึงสิ่งเหล่านี้เป็น DTOs หรือ Data Transfer Objects
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.