Comment les valeurs multiples sont-elles retournées en Java?

11

Parfois, vous souhaitez renvoyer plusieurs valeurs d'une fonction. Comment cela se fait-il normalement en Java?

Une option consiste à utiliser un tableau, comme cet extrait de code Python qui renvoie une liste ou un tuple:

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

Une autre option serait de renvoyer un hachage / dict, comme cet exemple JavaScript:

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

Un autre serait de créer un objet personnalisé juste à cet effet, comme cet exemple Java:

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

Bien sûr, vous pouvez également utiliser des variables globales pour stocker ce dont vous avez besoin au lieu de passer des choses, mais disons simplement que ce n'est pas une option.

Mike M. Lin
la source
Est-ce que les "vrais" gens de Java ont vraiment du mal à utiliser des getters et setters publics pour cacher des champs sur de petites classes internes comme ça? Juste curieux.
Chris Farmer
3
Oui, la plupart le font. Étant donné que de nombreux frameworks attendent la norme JavaBean, vous pouvez regretter de ne pas avoir de getters et setters. Dans tous les cas, votre IDE les générera pour vous.
Eric Wilson
3
Ou vous pouvez simplement les laisser de côté, sur la base du principe YAGNI. Mais cela ne semble pas se produire aussi souvent qu'on pourrait s'y attendre.
MatrixFrog
@FarmBoy: Je suppose que je comprends pour les beans et autres, mais l'OP implique que ce n'est qu'une classe unique conçue pour renvoyer plusieurs valeurs.
Chris Farmer
@ChrisFarmer Je suppose qu'avec ce contexte, je n'ai jamais vu un "vrai" programmeur Java créer une classe à cet effet.
Eric Wilson

Réponses:

26

Comment cela se fait-il normalement en Java?

Douloureusement.

Une option consiste à utiliser un tableau, comme cet extrait de code Python qui renvoie une liste ou un tuple ...

Une autre option serait de renvoyer un hachage / dict, comme cet exemple JavaScript ...

Ces techniques ne fonctionnent pas bien en Java; les valeurs devraient être converties à partir d'Object.

Un autre serait de créer un objet personnalisé juste à cet effet, comme cet exemple Java ...

C'est le plus courant, mais il est fastidieux de créer toutes ces petites classes. En C ++, il est courant d'utiliser std :: pair mais cela n'est généralement pas fait en Java.

Avec Lombok, il est assez facile de créer de petits objets personnalisés:

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

}

Kevin Cline
la source
10
"Comment cela se fait-il normalement en Java?" "Péniblement." lol en tant que développeur Java, je dois vous
attribuer
Utiliser une classe compacte immuable semblable à une structure n'est pas si douloureux ... C'est vraiment comme écrire une structure C ...
Guillaume
1
@Guillaume - bien sûr, mais toutes ces petites choses s'additionnent à la fois dans le temps et dans l'espace. Je ne sais pas pourquoi la communauté Java n'a pas adopté un ensemble standard de génériques comme "classe Pair <T1, T2> {public T1 premier; public T2 second; ...}"; dans les langues modernes, vous "retournez a, b"; puis écrivez "x, y = f ()";
kevin cline le
1
Je suis sûr que certains langages `` anciens '' sont capables de le faire aussi :) À mon humble avis, j'ai trouvé que plusieurs valeurs de retour peuvent conduire à un désordre total, et si vous devez ajouter d'autres champs de retour, il vous suffit de mettre à jour votre structure comme classe sans changer la signature de votre méthode.
Guillaume
1
C'est "douloureusement". m'a frappé fort, oui c'est exactement ce que je ressens en tant que développeur Java quand je rencontre des situations similaires.
artjom
13

Oui, la façon de créer un struct/ tuple/ recorden Java consiste à créer une classe. Si c'est uniquement pour un usage interne, je préfère utiliser une petite classe immuable de type struct avec des champs publics.

Exemples:

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

C'est beaucoup plus facile à faire à Scala:

case class Unreliably(success: Boolean, value: Int)
Jonas
la source
8
En fait, à Scala, vous retourneriez probablement généralement un Tuple2[Boolean, Int]. Bien que dans cet exemple spécifique , vous retourniez un Option[Int].
Jörg W Mittag
2
Cela répond donc à la question de Chris Farmer (dans les commentaires de Q) selon laquelle les vrais Java ne créent pas nécessairement des getters et setters pour les petites classes internes. Vous êtes une "vraie" personne Java, non?
Mike M. Lin
2
Dans d'autres nouvelles, il n'y a pas de vrais Ecossais.
Joseph Weissman
5

Pour l'exemple que vous avez donné, lever une exception serait la manière la plus standard de la gérer:

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

De plus, si vous vous efforcez d'avoir des fonctions "Do One Thing", la fonction de retour de plusieurs valeurs est moins nécessaire, bien que parfois pratique.

Eric Wilson
la source
4

Nous avons une classe générique Pair qui peut stocker une instance de A et une instance de B. Vous pouvez probablement créer un triplet ou quadruplet de la même manière.

public class Pair<A, B>
{
    ...
}
Raku
la source
1
cela fait cependant du code VRAIMENT illisible. si une méthode revient Pair<String, Integer>, qu'est-ce que cela signifie? que représentent ces valeurs? vous ne pouvez pas savoir sans avoir lu l'implémentation de la méthode.
sara
1

En Java, votre fonction retournerait un objet (ou peut-être null en cas d'échec). De cette façon, plusieurs éléments de données peuvent être retournés.

Scott C Wilson
la source
1

Il n'y a aucun moyen explicite de renvoyer plusieurs variables en Java, mais il existe quelques approches:

  1. La première consiste à suivre le chemin du tableau. Cela ne fonctionne vraiment que si vous avez tout le même type de données ou si vous pouvez les convertir temporairement en un seul type.
  2. La deuxième façon consiste à créer une classe dans le but de transférer plusieurs types de variables. Dans mon travail, nous les appelons DTO ou Data Transfer Objects.

la source