W jaki sposób zwracanych jest wiele wartości w Javie?

11

Czasami chcesz zwrócić wiele wartości z funkcji. Jak to zwykle się robi w Javie?

Jedną z opcji jest użycie tablicy, takiej jak ten fragment kodu w języku Python, który zwraca listę lub krotkę:

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

Inną opcją byłoby zwrócenie skrótu / dict, na przykład w tym przykładzie JavaScript:

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

Jeszcze jednym byłoby utworzenie niestandardowego obiektu tylko w tym celu, na przykład w tym przykładzie Java:

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

Oczywiście możesz także użyć niektórych zmiennych globalnych do przechowywania tego, czego potrzebujesz, zamiast przekazywać rzeczy, ale powiedzmy, że nie jest to opcja.

Mike M. Lin
źródło
Czy „prawdziwi” ludzie języka Java naprawdę mają problem z używaniem publicznych programów pobierających i ustawiających, aby ukrywać pola w takich małych klasach wewnętrznych? Po prostu ciekawy.
Chris Farmer,
3
Tak, większość tak. Ponieważ wiele platform oczekuje standardu JavaBean, możesz żałować, że nie masz programów pobierających i ustawiających. W każdym razie Twoje IDE wygeneruje je dla Ciebie.
Eric Wilson,
3
Lub możesz po prostu je pominąć, w oparciu o zasadę YAGNI. Ale to nie zdarza się tak często, jak można się spodziewać.
MatrixFrog,
@FarmBoy: Chyba rozumiem dla fasoli i tym podobnych, ale OP sugeruje, że jest to tylko jednorazowa klasa zaprojektowana do zwracania wielu wartości.
Chris Farmer,
@ChrisFarmer Chyba w tym kontekście nigdy nie widziałem, aby „prawdziwy” programista Java tworzył klasę do tego celu.
Eric Wilson,

Odpowiedzi:

26

Jak to zwykle się robi w Javie?

Dokuczliwie.

Jedną z opcji jest użycie tablicy, takiej jak ten fragment kodu w języku Python, który zwraca listę lub krotkę ...

Inną opcją byłoby zwrócenie skrótu / dict, jak w tym przykładzie JavaScript ...

Te techniki nie działają dobrze w Javie; wartości musiałyby zostać sprowadzone z Object.

Jeszcze jednym byłoby utworzenie niestandardowego obiektu tylko do tego celu, takiego jak ten przykład Java ...

Jest to najczęstsze, ale tworzenie wszystkich tych małych klas jest żmudne. W C ++ często używa się std :: pair, ale nie jest to często robione w Javie.

Dzięki Lombok tworzenie dość niestandardowych obiektów jest dość łatwe:

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

}

Kevin Cline
źródło
10
„Jak zwykle robi się to w Javie?” "Dokuczliwie." lol jako programista Java Muszę dać ci za to +1
TheLQ
Korzystanie kompaktowy niezmienna struct-jak klasa nie jest tak bolesne ... To jest naprawdę jak pisanie C struct ...
Guillaume
1
@Guillaume - jasne, ale wszystkie te małe rzeczy składają się zarówno na czas, jak i przestrzeń. Nie wiem, dlaczego społeczność Java nie przyjęła standardowego zestawu ogólnych, takich jak „klasa pary <T1, T2> {publiczny T1 pierwszy; publiczny T2 drugi; ...}”; we współczesnych językach po prostu „return a, b”; a następnie napisz „x, y = f ()”;
kevin cline
1
Jestem pewien, że niektóre „starożytne” języki też są w stanie to zrobić :) IMHO Znalazłem wiele zwracanych wartości, które mogą doprowadzić do całkowitego bałaganu, a jeśli potrzebujesz dodać kolejne pola zwracane, musisz po prostu zaktualizować swoją strukturę jak klasę bez zmień podpis metody
Guillaume
1
To „boleśnie”. uderzyło mnie mocno, tak właśnie czuję się jako programista Java, gdy spotykam podobne sytuacje.
artjom
13

Tak, sposobem na stworzenie struct/ tuple/ recordw Javie jest utworzenie klasy. Jeśli jest to tylko do użytku wewnętrznego, wolę użyć małej niezmiennej klasy strukturalnej z polami publicznymi.

Przykłady:

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

W Scali jest to o wiele łatwiejsze:

case class Unreliably(success: Boolean, value: Int)
Jonas
źródło
8
W rzeczywistości w Scali prawdopodobnie po prostu zwrócisz Tuple2[Boolean, Int]. Chociaż w tym konkretnym przykładzie zwrócisz wartość Option[Int].
Jörg W Mittag
2
Odpowiada to na pytanie Chrisa Farmera (w komentarzach Q), że prawdziwi ludzie Javy niekoniecznie tworzą programy pobierające i ustawiające dla małych klas wewnętrznych. Jesteś „prawdziwą” osobą Java, prawda?
Mike M. Lin
2
W innych wiadomościach nie ma prawdziwych Szkotów.
Joseph Weissman
5

W podanym przykładzie zgłoszenie wyjątku byłoby najbardziej standardowym sposobem jego obsługi:

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

Ponadto, jeśli dążysz do posiadania funkcji „Wykonaj jedną rzecz”, funkcja zwracania wielu wartości jest mniej potrzebna, choć czasami wygodna.

Eric Wilson
źródło
4

Mamy klasę ogólną Pair, która może przechowywać jedną instancję A i jedną instancję B. Prawdopodobnie możesz stworzyć Triplet lub Quadruplet w ten sam sposób.

public class Pair<A, B>
{
    ...
}
Raku
źródło
1
powoduje to, że NAPRAWDĘ nieczytelny kod. jeśli metoda zwróci Pair<String, Integer>, co to oznacza? co oznaczają te wartości? nie możesz tego wiedzieć bez przeczytania implementacji metody.
sara,
1

W Javie twoja funkcja zwróciłaby obiekt (lub być może zerowy w przypadku awarii). W ten sposób można zwrócić wiele danych.

Scott C. Wilson
źródło
1

Nie ma wyraźnego sposobu na zwrócenie wielu zmiennych w Javie, jednak istnieje kilka podejść:

  1. Pierwszym z nich jest przejście przez tablicę. To naprawdę działa, jeśli masz wszystko jako ten sam typ danych lub możesz tymczasowo przekonwertować je na jeden typ.
  2. Drugi sposób polega na utworzeniu klasy w celu przesyłania wielu typów zmiennych. W mojej pracy nazywamy je DTO lub Obiektami Transferu Danych.

źródło