web-dev-qa-db-fra.com

Renvoie plusieurs valeurs à partir d'une méthode Java: pourquoi aucun objet n-Tuple?

Pourquoi n'y a-t-il pas de solution (standard, Java), dans le cadre du langage Java lui-même), pour renvoyer plusieurs valeurs à partir d'un Java, plutôt que les développeurs doivent utiliser leurs propres moyens, tels que les cartes, les listes, les paires, etc.? Pourquoi Java ne prend-il pas en charge les objets n-Tuple?

Penser en particulier aux méthodes privées triviales qui peuvent modifier deux objets ensemble (en tandem), et dans ce cas, un objet typé en retour semble exagéré.

47
Saket

Je suppose que l'OP signifie "Pourquoi Java ne prend-il pas en charge les objets n-Tuple?". Python, Haskell, LISP, ML, etc. ont des capacités hétérogènes n-Tuple. Également souvent la capacité de retourner apparemment plusieurs objets dans une langue sont du sucre syntaxique (c'est-à-dire en python return 'a', 'b').

La raison est bien sûr la conception et la cohérence du langage. Java préfère être très explicite et n'aime pas les structures de données anonymes (bien que j'aurais aimé avoir des fermetures anonymes).

Par exemple, dans Java il n'y a aucun moyen de dire que je voudrais un rappel qui prend ces paramètres de type et renvoie ceci. Certaines personnes ressentent cela comme une énorme faiblesse, d'autres comme la cohérence et l'explicitation.

À mon humble avis, bien que ce soit ennuyeux, je lutte fréquemment contre ce problème en créant des classes statiques en ligne:

private static class Combo {
   String name;
   int weight;
}

Oui, c'est fastidieux, mais plus tard, je réutilise et refaçonne souvent ces classes, ce qui les rend de haut niveau et ajoute un comportement. En fait, l'un des avantages de cette route est qu'il est beaucoup plus facile d'ajouter de nouveaux champs où est la structure de données anonyme (comme dans FP langues), il devient beaucoup plus difficile d'ajouter un champ (vous finissent par changer une tonne de code).

Je dois noter que pour 2 tuples, certaines personnes utilisent (ou abusent) Java.util.Map.Entry car il y a un Java.util.AbstractMap.SimpleEntry in Java 6. De plus, certaines personnes utilisent maintenant Prise en charge de la paire Commons Lang3 (2-Tuple) .

Scala prend en charge n-Tuple par une sorte de triche et ayant tout un tas d'interfaces 2-16 Tuple qui sont standard dans la langue et qui sont syntaxiquement cachées au programmeur.

Pour des raisons purement pédagogiques, vous voudrez peut-être voir comment les autres les langues accomplissent cela .

MISE À JOUR: pour Java 8

Java 8 supportera/peut-être (donc mon numéro ... appelez-moi peut-être) une interface appelée Java.lang.BiValue avec une implémentation concrète que vous pouvez utiliser appelée Java.lang.BiVal. Ces classes doivent aider à prendre en charge la nouvelle fonctionnalité lambda. Mais notez que ce n'est que pour 2 tuples.

MISE À JOUR: pour 2015

Java 8 n'a pas pris en charge les tuples.

MISE À JOUR: de l'auteur 2015

Si vous souhaitez toujours la prise en charge de Tuple, il existe trois bibliothèques qui prennent bien en charge les tuples:

  • javatuples - Prend en charge JDK 5 et supérieur. Jusqu'à 10 tuples.
  • JOOλ - De l'auteur de jOOQ mais nécessite JDK 8.
  • Commons Lang - Prend désormais en charge un triple (3-Tuple) et prend en charge JDK 6 et supérieur.
51
Adam Gent

Les méthodes Java renvoient exactement zéro ou une valeur; que est la norme pour Java. Si vous avez besoin de renvoyer plusieurs valeurs, créez un objet avec les valeurs multiples et renvoyez-le.

9
DwB

Si vous souhaitez renvoyer deux objets, vous souhaitez généralement retourner un seul objet qui encapsule les deux objets à la place.

4
Psychologist

Il existe de nombreuses façons de pirater cela, une façon serait de retourner un Object[], mais alors vous avez des indices dont vous devez vous soucier, et des vérifications de pointeurs nuls, ça devient tout simplement désagréable. Une autre façon est de renvoyer un String, mais ensuite vous devez l'analyser, et ça devient désagréable.

Je pense que la vraie question est pourquoi?

Voici le hic - Si je travaillais sur un projet avec vous et que je voyais ce type de comportement, je le réécrirais pour que vous puissiez voir comment il devrait être géré. Si vous fournissez un exemple de code, je vais le réécrire pour illustrer.

Écrivez vos méthodes avec une seule responsabilité, si elles ont besoin de renvoyer plus de données qu'elles ne le peuvent, vous devez probablement utiliser un objet ou le diviser en méthodes plus petites.

3
Travis

Parce que renvoyer plusieurs valeurs à partir d'une méthode n'est pas une pratique recommandée (dans Java).

Si vous avez besoin de valeurs indépendantes d'une méthode, vous avez besoin d'une autre structure de données comme un objet contenant ces valeurs. Si vous avez besoin de plusieurs instances de la même classe (c'est-à-dire plusieurs chaînes), vous devez renvoyer soit un tableau, soit une collection en fonction de vos besoins.

Le retour de plusieurs valeurs dans d'autres langues (Go par exemple) est utilisé par exemple pour renvoyer un code d'erreur, mais Java a été conçu différemment en utilisant des exceptions.

1
OscarRyz

Un nouveau style de modèle est disponible et correspond à la nature "tout asynchrone" que vous pourriez voir dans des langages tels que JavaScript.

Beaucoup de mon code ressemble à ceci de nos jours :-)

public class Class1 {

    public interface Callback {
       void setData(String item1, String item2);
    }
    public void getThing(Callback callback) {
        callback.setData("a", "b");
    }
}

public class Class2 {

    public void doWithThing(Class1 o) {
        o.getThing(new Class1.Callback() {
            public void setData(String item1, String item2) {
                ... do something with item 1 and item 2 ...
            }
        });
    }

}

Pas de nouveaux objets à créer et pas autant de classes supplémentaires puisque l'interface est une classe interne de l'objet.

C'est ce qui rend Swift si génial. Le code peut ressembler à ceci:

o.getThing({ item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
});

Et puisque le seul argument est le bloc, même ceci:

o.getThing { item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
};

Java a besoin de travail pour rendre le code chargé de rappel beaucoup plus facile à lire.

1
Paul Hamilton