Wie werden in Java mehrere Werte zurückgegeben?

11

Manchmal möchten Sie mehrere Werte von einer Funktion zurückgeben. Wie wird das normalerweise in Java gemacht?

Eine Möglichkeit besteht darin, ein Array wie dieses Python-Snippet zu verwenden, das eine Liste oder ein Tupel zurückgibt:

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

Eine andere Möglichkeit wäre, einen Hash / Dikt zurückzugeben, wie in diesem JavaScript-Beispiel:

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

Eine weitere Möglichkeit besteht darin, ein benutzerdefiniertes Objekt nur für diesen Zweck zu erstellen, wie in diesem Java-Beispiel:

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

Natürlich können Sie auch nur einige globale Variablen verwenden, um das zu speichern, was Sie benötigen, anstatt Dinge weiterzugeben, aber sagen wir einfach, dass dies keine Option ist.

Mike M. Lin
quelle
Haben "echte" Java-Leute wirklich die Mühe, öffentliche Getter und Setter zu verwenden, um Felder in kleinen internen Klassen wie diesen zu verbergen? Nur neugierig.
Chris Farmer
3
Ja, die meisten tun es. Da viele Frameworks den JavaBean-Standard erwarten, können Sie es bereuen, keine Getter und Setter zu haben. In jedem Fall generiert Ihre IDE sie für Sie.
Eric Wilson
3
Oder Sie können sie einfach weglassen, basierend auf dem YAGNI-Prinzip. Aber das scheint nicht so oft zu passieren, wie man es erwarten könnte.
MatrixFrog
@ FarmBoy: Ich glaube, ich verstehe für Bohnen und dergleichen, aber das OP impliziert, dass dies nur eine einmalige Klasse ist, die mehrere Werte zurückgeben soll.
Chris Farmer
@ChrisFarmer Ich denke, dass ich in diesem Kontext noch nie einen "echten" Java-Programmierer gesehen habe, der eine Klasse für diesen Zweck erstellt hat.
Eric Wilson

Antworten:

26

Wie wird das normalerweise in Java gemacht?

Schmerzlich.

Eine Möglichkeit besteht darin, ein Array wie dieses Python-Snippet zu verwenden, das eine Liste oder ein Tupel zurückgibt ...

Eine andere Möglichkeit wäre, einen Hash / Dikt zurückzugeben, wie in diesem JavaScript-Beispiel ...

Diese Techniken funktionieren in Java nicht gut. Die Werte müssten von Object herabgestuft werden.

Eine weitere Möglichkeit besteht darin, ein benutzerdefiniertes Objekt nur für diesen Zweck zu erstellen, wie in diesem Java-Beispiel ...

Dies ist am häufigsten der Fall, aber es ist mühsam, all diese kleinen Klassen zu erstellen. In C ++ wird häufig std :: pair verwendet, dies wird jedoch in Java nicht häufig durchgeführt.

Mit Lombok ist es ganz einfach, kleine benutzerdefinierte Objekte zu erstellen:

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

}}

Kevin Cline
quelle
10
"Wie wird das normalerweise in Java gemacht?" "Schmerzlich." lol als Java-Entwickler muss ich dich dafür +1
TheLQ
Die Verwendung einer kompakten unveränderlichen strukturähnlichen Klasse ist nicht so schmerzhaft ... Es ist wirklich so, als würde man eine C-Struktur schreiben ...
Guillaume
1
@ Guillaume - sicher, aber all diese kleinen Dinge summieren sich sowohl zeitlich als auch räumlich. Ich weiß nicht, warum die Java-Community keine Standard-Generika wie "Klassenpaar <T1, T2> {public T1 first; public T2 second; ...}" übernommen hat. in modernen Sprachen gibt man einfach "a, b zurück"; und dann schreibe "x, y = f ()";
Kevin Cline
1
Ich bin mir sicher, dass einige 'alte' Sprachen dies auch können :) IMHO Ich habe festgestellt, dass mehrere Rückgabewerte zu totalem Durcheinander führen können, und wenn Sie weitere Rückgabefelder hinzufügen müssen, müssen Sie nur Ihre strukturähnliche Klasse aktualisieren, ohne dies zu tun Ändern Sie Ihre Methodensignatur.
Guillaume
1
Das "Schmerzlich". hat mich hart getroffen, ja, es ist genau das, was ich als Java-Entwickler fühle, wenn ich auf ähnliche Situationen stoße.
Artjom
13

Ja, die Art und Weise ein zu schaffen struct/ tuple/ recordin Java ist durch Erstellen einer Klasse. Wenn es nur für den internen Gebrauch ist, bevorzuge ich die Verwendung einer kleinen unveränderlichen strukturähnlichen Klasse mit öffentlichen Feldern.

Beispiele:

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

Dies ist in Scala viel einfacher:

case class Unreliably(success: Boolean, value: Int)
Jonas
quelle
8
In Scala würden Sie wahrscheinlich im Allgemeinen nur eine zurückgeben Tuple2[Boolean, Int]. Obwohl Sie in diesem speziellen Beispiel eine zurückgeben würden Option[Int].
Jörg W Mittag
2
Dies beantwortet also die Frage von Chris Farmer (in den Kommentaren des Q), dass echte Java-Leute nicht unbedingt Getter und Setter für kleine interne Klassen erstellen. Sie sind eine "echte" Java-Person, oder?
Mike M. Lin
2
In anderen Nachrichten gibt es keine wahren Schotten.
Joseph Weissman
5

Für das Beispiel, das Sie gegeben haben, ist das Auslösen einer Ausnahme die Standardmethode, um damit umzugehen:

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

Wenn Sie Funktionen wie "Do One Thing" anstreben, ist die Funktion zum Zurückgeben mehrerer Werte weniger erforderlich, wenn auch gelegentlich praktisch.

Eric Wilson
quelle
4

Wir haben eine generische Paarklasse, die eine Instanz von A und eine Instanz von B speichern kann. Sie können wahrscheinlich ein Triplet oder Quadruplet auf dieselbe Weise erstellen.

public class Pair<A, B>
{
    ...
}
Raku
quelle
1
Dies führt jedoch zu WIRKLICH unlesbarem Code. Pair<String, Integer>Was bedeutet es, wenn eine Methode zurückgegeben wird? Was bedeuten diese Werte? Sie können es unmöglich wissen, ohne die Implementierung der Methode zu lesen.
Sara
1

In Java würde Ihre Funktion ein Objekt zurückgeben (oder im Falle eines Fehlers möglicherweise null). Auf diese Weise können mehrere Daten zurückgegeben werden.

Scott C Wilson
quelle
1

Es gibt keine explizite Möglichkeit, mehrere Variablen in Java zurückzugeben. Es gibt jedoch einige Ansätze:

  1. Das erste ist, den Weg des Arrays zu gehen. Dies funktioniert nur dann wirklich, wenn Sie alle Daten als denselben Datentyp haben oder sie vorübergehend in einen Typ konvertieren können.
  2. Die zweite Möglichkeit besteht darin, eine Klasse zum Übertragen mehrerer Variablentypen zu erstellen. Bei meiner Arbeit bezeichnen wir diese als DTOs oder Datenübertragungsobjekte.

quelle