Làm thế nào nhiều giá trị được trả về trong Java?


11

Đôi khi bạn muốn trả về nhiều giá trị từ một hàm. Làm thế nào điều này thường được thực hiện trong Java?

Một tùy chọn là sử dụng một mảng, như đoạn mã Python này trả về một danh sách hoặc tuple:

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

Một tùy chọn khác là trả về hàm băm / dict, như ví dụ JavaScript này:

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

Một điều nữa sẽ là tạo một đối tượng tùy chỉnh chỉ cho mục đích này, như ví dụ Java này:

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

Tất nhiên bạn cũng có thể chỉ sử dụng một số biến toàn cục để lưu trữ những gì bạn cần thay vì chuyển mọi thứ xung quanh, nhưng hãy nói rằng đó không phải là một lựa chọn.


Những người java "thực sự" có thực sự gặp rắc rối khi sử dụng các getters và setters công cộng để ẩn các trường trên các lớp nội bộ nhỏ như vậy không? Chỉ tò mò thôi.
Nông dân Chris

3
Vâng, hầu hết làm. Vì nhiều khung công tác mong đợi tiêu chuẩn JavaBean, bạn có thể hối tiếc vì không có getters và setters. Trong mọi trường hợp, IDE của bạn sẽ tạo chúng cho bạn.
Eric Wilson

3
Hoặc bạn có thể bỏ chúng ra, dựa trên nguyên tắc YAGNI. Nhưng điều đó dường như không xảy ra thường xuyên như người ta có thể mong đợi.
MatrixFrog

@FarmBoy: Tôi đoán tôi hiểu về đậu và như vậy, nhưng OP ngụ ý rằng đây chỉ là lớp một lần được thiết kế để trả về nhiều giá trị.
Nông dân Chris

@ChrisFarmer Tôi đoán rằng với bối cảnh đó, tôi chưa bao giờ thấy một lập trình viên Java 'thực sự' tạo ra một lớp cho mục đích này.
Eric Wilson

Câu trả lời:


26

Làm thế nào điều này thường được thực hiện trong Java?

Đau đớn.

Một tùy chọn là sử dụng một mảng, như đoạn mã Python này trả về danh sách hoặc tuple ...

Một tùy chọn khác là trả về hàm băm / dict, như ví dụ JavaScript này ...

Các kỹ thuật này không hoạt động tốt trong Java; các giá trị sẽ phải được downcast từ Object.

Một điều nữa là tạo một đối tượng tùy chỉnh chỉ cho mục đích này, như ví dụ Java này ...

Điều này là phổ biến nhất, nhưng thật tẻ nhạt khi tạo ra tất cả các lớp nhỏ đó. Trong C ++, người ta thường sử dụng std :: cặp nhưng điều này không được thực hiện phổ biến trong Java.

Với Lombok , thật dễ dàng để tạo ra các đối tượng tùy chỉnh nhỏ:

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

}


10
"Làm thế nào điều này thường được thực hiện trong Java?" "Đau đớn." lol là một nhà phát triển Java Tôi phải +1 bạn cho điều đó
TheLQ

Sử dụng một lớp giống như cấu trúc bất biến nhỏ gọn không quá đau đớn ... Nó thực sự giống như viết một cấu trúc C ...
Guillaume

1
@Guillaume - chắc chắn, nhưng tất cả những điều nhỏ nhặt đó cộng lại cả về thời gian và không gian. Tôi không biết tại sao cộng đồng Java không chấp nhận một tập hợp chung chung tiêu chuẩn như "Cặp lớp <T1, T2> {công khai T1 trước; công khai T2 thứ hai; ...}"; trong các ngôn ngữ hiện đại, bạn chỉ cần "trả về a, b"; và sau đó viết "x, y = f ()";
kevin cline

1
Tôi chắc chắn rằng một số ngôn ngữ 'cổ đại' cũng có thể làm được điều đó :) IMHO Tôi thấy nhiều giá trị trả về có thể dẫn đến sự lộn xộn và nếu bạn cần thêm các trường trả về khác, bạn chỉ cần cập nhật lớp cấu trúc của mình mà không cần thay đổi chữ ký phương thức của bạn.
Guillaume

1
Đó là "Đau đớn." làm tôi khó khăn, vâng, đó chính xác là những gì tôi cảm thấy là nhà phát triển Java khi tôi gặp các tình huống tương tự.
artjom

13

Đúng, cách tạo struct/ tuple/ recordtrong Java là bằng cách tạo một lớp. Nếu nó chỉ dành cho sử dụng nội bộ, tôi thích sử dụng một lớp nhỏ giống như cấu trúc bất biến với các trường công khai.

Ví dụ:

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

Điều này dễ thực hiện hơn ở Scala:

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

8
Trên thực tế, ở Scala, bạn thường chỉ cần quay lại a Tuple2[Boolean, Int]. Mặc dù trong ví dụ cụ thể này , bạn sẽ trả lại một Option[Int].
Jörg W Mittag

2
Vì vậy, điều này trả lời câu hỏi của Chris Farmer (theo ý kiến ​​của Q) rằng những người Java thực sự không nhất thiết phải tạo ra các biểu đồ và setters cho các lớp bên trong nhỏ. Bạn là một người Java "thực sự", phải không?
Mike M. Lin

2
Trong những tin tức khác, không có người Scotland thực sự.
Joseph Weissman

5

Đối với ví dụ bạn đã đưa ra, ném ngoại lệ sẽ là cách tiêu chuẩn nhất để xử lý nó:

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

Hơn nữa, nếu bạn cố gắng có các chức năng "Làm một điều" thì tính năng trả lại nhiều giá trị là ít cần thiết, mặc dù đôi khi thuận tiện.


4

Chúng tôi có một lớp chung Cặp có thể lưu trữ một thể hiện của A và một thể hiện của B. Bạn có thể có thể tạo một Triplet hoặc Quadruplet theo cách tương tự.

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

1
điều này làm cho một số mã thực sự không thể đọc được mặc dù. Nếu một phương thức trả về Pair<String, Integer>, điều đó có nghĩa là gì? những giá trị này đại diện cho cái gì? bạn có thể biết mà không cần đọc thực hiện phương pháp.
sara

1

Trong Java, hàm của bạn sẽ trả về một đối tượng (hoặc có thể là null trong trường hợp không thành công). Bằng cách này, nhiều phần dữ liệu có thể được trả lại.


1

Không có cách rõ ràng để trả về nhiều biến trong Java, tuy nhiên có một vài cách tiếp cận:

  1. Đầu tiên là đi theo con đường của mảng. Điều này chỉ thực sự hoạt động nếu bạn có mọi thứ như cùng một loại dữ liệu hoặc có thể tạm thời chuyển đổi chúng thành một loại.
  2. Cách thứ hai là tạo một lớp cho mục đích chuyển nhiều loại biến. Trong công việc của tôi, chúng tôi gọi chúng là DTO hoặc Đối tượng truyền dữ liệu.
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.