Come vengono restituiti più valori in Java?


11

A volte si desidera restituire più valori da una funzione. Come si fa normalmente in Java?

Un'opzione è usare un array, come questo frammento di Python che restituisce un elenco o una tupla:

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

Un'altra opzione sarebbe quella di restituire un hash / dict, come questo esempio JavaScript:

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

Un altro sarebbe quello di creare un oggetto personalizzato solo per questo scopo, come questo esempio Java:

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

Ovviamente puoi anche usare solo alcune variabili globali per archiviare ciò di cui hai bisogno invece di far passare le cose, ma diciamo solo che non è un'opzione.


Le persone "vere" di java affrontano davvero il problema di usare getter e setter pubblici per nascondere campi in classi interne così piccole? Solo curioso.
Chris Farmer,

3
Sì, molti lo fanno. Poiché molti framework prevedono lo standard JavaBean, puoi pentirti di non avere getter e setter. In ogni caso, il tuo IDE li genererà per te.
Eric Wilson,

3
Oppure puoi semplicemente lasciarli fuori, in base al principio YAGNI. Ma ciò non sembra accadere tutte le volte che ci si potrebbe aspettare.
MatrixFrog,

@FarmBoy: immagino di capire per i bean e simili, ma l'OP implica che questa è solo una classe una tantum progettata per restituire più valori.
Chris Farmer,

@ChrisFarmer Immagino che in quel contesto, non ho mai visto un programmatore Java "reale" creare una classe per questo scopo.
Eric Wilson,

Risposte:


26

Come si fa normalmente in Java?

Dolorosamente.

Un'opzione è usare un array, come questo frammento di Python che restituisce un elenco o tupla ...

Un'altra opzione sarebbe quella di restituire un hash / dict, come questo esempio JavaScript ...

Queste tecniche non funzionano bene in Java; i valori dovrebbero essere downcast da Object.

Un altro sarebbe quello di creare un oggetto personalizzato solo per questo scopo, come questo esempio Java ...

Questo è molto comune, ma è noioso creare tutte quelle piccole classi. In C ++ è comune usare std :: pair, ma ciò non è comunemente fatto in Java.

Con Lombok è abbastanza facile creare piccoli oggetti personalizzati:

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

}


10
"Come si fa normalmente in Java?" "Dolorosamente." lol come sviluppatore Java devo farti +1 per questo
TheLQ,

Usare una classe simile a una struttura immutabile compatta non è così doloroso ... È davvero come scrivere una struttura C ...
Guillaume,

1
@Guillaume - certo, ma tutte quelle piccole cose si sommano sia nel tempo che nello spazio. Non so perché la comunità Java non abbia adottato un set standard di generici come "class Pair <T1, T2> {prima T1 pubblico; secondo T2 pubblico; ...}"; nelle lingue moderne "restituisci a, b"; e poi scrivi "x, y = f ()";
Kevin Cline,

1
Sono sicuro che anche un linguaggio "antico" è in grado di farlo :) IMHO Ho trovato che più valori di ritorno possono portare a un casino totale e se hai bisogno di aggiungere un altro campo di ritorno, devi solo aggiornare la tua struttura come classe senza cambia la firma del tuo metodo.
Guillaume,

1
Quel "doloroso". mi ha colpito molto, sì, è esattamente quello che sento come sviluppatore Java quando incontro situazioni simili.
artjom,

13

Sì, il modo per creare un struct/ tuple/ recordin Java è creando una classe. Se è solo per uso interno, preferisco usare una classe immutabile simile a una struttura con campi pubblici.

Esempi:

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

Questo è molto più facile da fare in Scala:

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

8
In realtà, a Scala, probabilmente in genere restituiresti a Tuple2[Boolean, Int]. Sebbene in questo esempio specifico , restituiresti un Option[Int].
Jörg W Mittag,

2
Quindi questo risponde alla domanda di Chris Farmer (nei commenti di Q) che i veri Java non creano necessariamente getter e setter per piccole classi interne. Sei una persona "reale" di Java, vero?
Mike M. Lin,

2
In altre notizie, non ci sono veri scozzesi.
Joseph Weissman,

5

Per l'esempio che hai fornito, lanciare un'eccezione sarebbe il modo più standard per gestirlo:

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

Inoltre, se ti sforzi di avere funzioni che "Do One Thing", la funzionalità di restituzione di più valori è meno necessaria, anche se a volte conveniente.


4

Abbiamo una classe generica Pair che può memorizzare un'istanza di A e un'istanza di B. Probabilmente puoi creare una Triplet o Quadruplet allo stesso modo.

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

1
questo rende però un po 'di codice VERAMENTE illeggibile. se un metodo ritorna Pair<String, Integer>, cosa significa? cosa rappresentano questi valori? non puoi assolutamente sapere senza leggere l'implementazione del metodo.
Sara

1

In Java, la tua funzione restituirebbe un oggetto (o forse null in caso di errore). In questo modo, è possibile restituire più dati.


1

Non esiste un modo esplicito per restituire più variabili in Java, tuttavia esistono alcuni approcci:

  1. Il primo è seguire la strada dell'array. Funziona davvero solo se hai tutto dello stesso tipo di dati o puoi convertirli temporaneamente in un tipo.
  2. Il secondo modo è creare una classe allo scopo di trasferire più tipi di variabili. Nel mio lavoro ci riferiamo a questi come DTO o Data Transfer Objects.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.