6
votes

Passer des types primitifs comme Out Param en Java

Je dois retourner / mettre à jour un booléen tout en retournant une liste de choses d'une méthode. Java ne peut pas retourner les tuples et je ne voulais pas faire une classe distincte pour cela, alors figuré, je passerais le bool comme un param. C'est ce que notre client C ++ fait, passe Bool par référence. Cela fonctionnerait pour une classe normale puisque Java a une sorte de réussite pour des objets (voir est Java "Pass-By-Référence" ou "Pass-By-Value"? Pour une bonne discussion de cela). Mais les classes "wrapper" comme booléen stockent leur valeur primitive comme immutable, il ne peut donc pas être mis à jour de cette manière.

Utiliser un tableau booléen (avec une entrée) semble Hokey mais est peut-être la chose la plus simple qui fonctionne. Alternativement, pourrait renvoyer le booléen et transmettre la liste créée en arrière comme un paramètre de sortie plutôt que comme le retour [mais le client Java s'écarte de la C ++, et il est préférable de garder la plupart des mêmes approches en C #. ]


2 commentaires

En fait, Java peut retourner les tuples. Vous pouvez simplement mettre vos valeurs de retour dans une liste Java.Util.Utiliser ou java.Util.map et retourner cela.


FYI Voir les commentaires dans les réponses ci-dessous sur les tuples Java et la messilité de la liste de retour.


6 Réponses :


14
votes

Non, Java ne doit pas avoir transbord-by-ref pour des objets; Il a "transmission de la valeur par valeur" qui n'est pas la même chose.

Vous ne pouvez certainement rien transmettre en tant que paramètre "Out" ou par référence en Java - bien que vous puissiez en C #.

Pourriez-vous encapsuler la "liste Boolean Plus" dans un autre type? Sont-ils réellement liés? L'utilisation d'une matrice booléenne est définitivement assez laide. Vous pourriez-vous écrire un MUTABLEBOOLEAN Type d'emballage - mais à nouveau, c'est assez moche. Normalement, je dirais que le retour de deux choses suggère que la méthode devrait être fractionnée, mais quand l'un d'entre eux est un booléen, il peut être assez raisonnable - comme int.tryparse etc de C #.


7 commentaires

@Jon - Java passe des objets par référence et primitives par valeur. C'est sur le SCJP, je ne suis pas sûr de ce que vous entendez par "transmettre la référence par valeur". Si vous passez un objet sous forme de paramètre, modifiez l'objet et quittez l'objet, l'objet est modifié. Aucun "copie" de l'objet actuel n'existe.


Merci. Oui, je sais que la terminologie de Java est désordonnée, c'est pourquoi j'ai dit que "la sorte de Java a passé PAS-BY-REF pour des objets (voir la question 40480" est-ce que Java passe par référence? "Pour une bonne discussion de cela)."


@Mech Software - Non - ce n'est pas sur l'examen SCJP - parce que c'est faux. Bobcat.webappcabaret.net/javachina/faq/07.htm#pas_q5


@Mech: Quand ai-je dit que l'objet est copié? La référence est copiée. La référence est transmise par la valeur. Vous n'avez jamais réellement adopté un objet - vous passez une référence. Et @Cincinnati Joe - il n'a pas besoin d'être désordonné du tout. "Passer une référence par valeur" n'est pas désordonnée ou inexacte.


Les appeler des "références" était un mauvais déménagement imho. Ils auraient pu les appeler "pointeurs", "ID d'objet", "poignées" ou un million d'autres choses qui ne voulaient pas dire quelque chose de complètement différent en C ++.


@FINNW: "Pointeur" suggérerait qu'elle signifiait une adresse physique en mémoire, ce qui ne doit certainement pas à. "Poignée" serait un peu mieux, bien qu'il ait une signification légèrement différente sous Windows. "ID d'objet" pourrait ne pas être trop mauvais. Vraiment "référence" n'est pas trop mauvaise une fois que vous l'avez, et c'est assez simple de l'obtenir.


@FINNW: "Référence" est un terme générique pour des éléments tels que les pointeurs ( en.wikipedia.org / wiki / référence_% 28computer_science% 29 ). C'est donc un terme parfaitement raisonnable. Je ne pense pas que ce que C ++ appelle des références est nécessairement une utilisation très standard du terme, mais comme beaucoup de gens viennent de C ++, ils sont bloqués dans cette signification de "référence".



8
votes

Comme vous le dites, la classe Wrapper Boolen est immuable, vous ne pouvez donc pas l'utiliser pour recevoir votre variable de sortie.

Transmettre une nouvelle liste pour recevoir le résultat de la liste et renvoyer le booléen sonnerait le plus naturel pour moi, mais Vous avez une bonne raison; Garder l'interface à peu près la même chose sur plusieurs implémentations.

Vous pouvez résoudre ce problème en créant votre propre booléen mutable et en faisant passer une référence à celle-ci, quelque chose comme: xxx

et utilisez-le comme: xxx


1 commentaires

Oui, merci de faire la sorte que ceci (Jon l'avait également mentionné dans sa réponse). Je pense que c'est ce que nous allons avec depuis que cela correspond principalement à notre version C ++.



1
votes

Qu'est-ce que j'ai fait pour renvoyer plusieurs valeurs consiste à modifier le type de retour pour renvoyer une matrice d'objet. Le [0] pourrait être le bool et [1] pourrait être la liste.

L'inconvénient est que l'appelant doit savoir de jeter les objets retournés de manière appropriée de la matrice d'objet et que le compilateur ne peut pas vous vérifier.

edit: ici est une réponse pour renvoyer une paire de valeurs de Java.


2 commentaires

J'aime l'idée de paire - un collègue a noté que Google Collections a une paire, mais il semble que ce n'est pas dans leur version 1.0.


Selon ces collections Google pas ont une classe de paire encore: code.google.com/p/guava-libraires/issues/detail?id=203



4
votes

Je dois retourner / mettre à jour un booléen tout en retournant une liste de choses d'une méthode. Java ne peut pas retourner les tuples et je ne voulais pas faire une classe distincte pour cette

J'ai rencontré le même problème et la meilleure solution IMHO est généralement:

oublie juste vos soucis et faire une classe distincte.

J'avais l'habitude d'hésiter à ce sujet, mais les classes sont destinées à encapsuler des valeurs, alors allez-y et faites-le.

chances sont, une fois que votre fonction renvoie une instance d'une classe personnalisée, vous constaterez qu'il existe des fonctionnalités supplémentaires qui conviennent bien à cette classe ou à d'autres méthodes pouvant utiliser la classe comme une valeur de paramètre ou de retour, et bientôt le la classe sera assez utile: -).

Si vous vraiment Je ne veux pas faire cela, vous pouvez toujours tout cacher dans une liste Java.Util.Utiliser ou un java.Util.map et retourner cela. Mais c'est vraiment moche :-( Je l'ai fait aussi bien et venez le regretter. Cela peut sembler simple au début, mais comme le code évolue et pousse, la lisibilité souffre (était-ce qu'une liste d'entier, puis double, double, ou vice versa?). Les classes sont beaucoup plus utiles.

Remarque: Si vous sentez une classe normale de niveau de haut niveau, vous pouvez utiliser un classe imbriquée , qui est agréable pour les classes de "usage local" seulement.


2 commentaires

Je suis arrivé à mes notes de la récente conférence du développeur de CoDemash et j'ai rappelé que cette situation s'est produite dans une courte présentation par Dick Wall de la Posse Java. Il parlait de Scala et a déclaré qu'il soutient des tuples pour des types de retour (il a mentionné le désir controversé de les ajouter à Java: Stackoverflow.com/questions/457775/DOES-JAVA-NEED-TUPES ). Il a dit qu'en Java si vous définissez une nouvelle classe "STRIT" pour retourner plusieurs choses que vous auriez à la mettre en œuvre pleinement avec des méthodes d'équivalence et de code HASHCODE et de tester les frais généraux pour une telle chose simple.


@Cincinnati Joe: Point intéressant, merci. Quant à "mettre en œuvre complètement avec des égaux, etc.": Je ne suis qu'un peu en désaccord. Il est parfaitement acceptable de ne pas mettre en œuvre (remplacer) ceux-ci. Il vous suffit de vous rappeler que vous ne devez pas utiliser aveuglément égal () / hashcode () sur une classe sans vérifier qu'ils l'appliquent correctement. Mais c'est une boîte différente de vers ...



2
votes

Vous ne pouvez utiliser aucun des types primitifs comme paramètre "OUT" en Java. Cela ne va pas arriver à tout moment.

Vous ne pouvez également utiliser aucune des versions d'objet, telles que Boolean, Entier, Float, Double, etc., comme des paramètres «sortis» tels qu'ils sont immuables. Ce que vous pouvez faire est d'écrire votre propre classe ou d'utiliser quelque chose comme Mutableboolcan in Commons-Lang ( http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/mutable/mutableboolcan .html ). P>

Par exemple: P>

public void setTrue(MutableBoolean b) {
    b.setValue(Boolean.TRUE);
}


0 commentaires

-1
votes

As RSP et beaucoup d'autres ont mentionné, il est immuable. Cependant, il y a une variation booléenne appelée atomicboolean qui a été introduit dans le cadre de la JAVA.UTIL.CONCURENT.ATOMIC Paquet de Java 1.5. Si vous ne voulez pas créer de cours pour manipuler de tels problèmes triviaux, Atomicboolean est la voie à suivre. Vérifiez-le. Exécutez le code suivant pour voir par vous-même. XXX


1 commentaires

-1 Parce que vous aurez une surcharge, petite commee, pour le mécanisme de verrouillage, les paramètres atomiques mettent en œuvre. Ils devraient être utilisés pour surmonter les problèmes simultanés. Les paramètres mutables sont une meilleure suite pour ce cas.