Comment passer un type de données primitif par référence?

Comment puis-je passer un type primitif par référence dans java? Par exemple, comment puis-je faire passer un int à une méthode modifiable?

Il n’y a pas moyen de passer une primitive directement par référence en Java.

Une solution de contournement consiste à transmettre une référence à une instance d’une classe wrapper, qui contient alors la primitive en tant que champ membre. Une telle classe de wrapper pourrait être extrêmement simple à écrire pour vous-même:

 public class IntRef { public int value; } 

Mais qu’en est-il de certaines classes de wrapper pré-construites, de sorte que nous n’avons pas à écrire les nôtres? D’ACCORD:

Les classes Apache commons-lang Mutable *:
Avantages : Bonnes performances pour un seul thread. Complétude.
Inconvénients : introduit une dépendance de bibliothèque tierce. Aucun contrôle de concurrence intégré.
Classes représentatives : MutableBoolean , MutableByte , MutableDouble , MutableFloat , MutableInt , MutableLong , MutableObject , MutableShort .

Les classes java.util.concurrent.atomic Atomic *:
Avantages : fait partie de l’API Java (1.5+) standard. Contrôles de concurrence intégrés.
Inconvénients : faible impact sur les performances lorsqu’il est utilisé dans un paramètre à un seul thread. Support direct manquant pour certains types de données, par exemple, il n’y a pas d’AtomicShort.
Classes représentatives : AtomicBoolean , AtomicInteger , AtomicLong et AtomicReference .
Note : Comme l’utilisateur ColinD le montre dans sa réponse , AtomicReference peut être utilisé pour approcher certaines des classes manquantes, par exemple AtomicShort.

Longueur 1 tableau primitif
La réponse d’OscarRyz montre l’utilisation d’un tableau de longueur 1 pour “envelopper” une valeur primitive.
Avantages : rapide à écrire. Performant Aucune bibliothèque tierce nécessaire.
Inconvénients : Un peu sale. Aucun contrôle de concurrence intégré. Résultat dans un code qui ne s’auto-identifie pas (clairement): le tableau se trouve-t-il dans la signature de la méthode pour que je puisse transmettre plusieurs valeurs? Ou est-ce ici comme échafaudage pour une émulation de référence?

Regarde aussi
Les réponses à la question StackOverflow “Le champ booléen Mutable en Java “.

Mon avis
En Java, vous devez vous efforcer d’utiliser les approches ci-dessus avec modération ou pas du tout. En C, il est courant d’utiliser la valeur de retour d’une fonction pour relayer un code d’état (SUCCESS / FAILURE), tandis que la sortie réelle d’une fonction est relayée via un ou plusieurs parameters de sortie. En Java, il est préférable d’utiliser les exceptions au lieu des codes de retour. Cela libère les valeurs de retour de méthode à utiliser pour transmettre la sortie de la méthode réelle – un modèle de conception que la plupart des programmeurs Java considèrent comme plus naturel que les parameters de sortie.

Rien dans Java n’est passé par référence. Tout est passé par valeur.

Edit: les primitives et les types d’object sont transmis par valeur. Vous ne pouvez jamais modifier la valeur / référence passée et attendre que la valeur / référence d’origine change. Exemple:

 Ssortingng a; int b; doSomething(a, b); ... public void doSomething(Ssortingng myA, int myB) { // whatever I do to "myA" and "myB" here will never ever ever change // the "a" and "b" } 

La seule façon de contourner cet obstacle, qu’il s’agisse d’une primitive ou d’une référence, consiste à passer un object conteneur ou à utiliser la valeur de retour.

Avec un titulaire:

 private class MySsortingngHolder { Ssortingng a; MySsortingngHolder(Ssortingng a) { this.a = a; } } MySsortingngHolder holdA = new MySsortingngHolder("something"); public void doSomething(MySsortingngHolder holder) { // alter holder.a here and it changes. } 

Avec valeur de retour

 int b = 42; b = doSomething(b); public int doSomething(int b) { return b + 1; } 

Passez AtomicInteger un AtomicInteger , AtomicBoolean , etc. Il n’y en a pas pour chaque type de primitive, mais vous pouvez utiliser, par exemple, une AtomicReference si nécessaire.

À noter: il ne devrait y avoir que très rarement besoin de faire quelque chose comme ça en Java. Quand vous voulez le faire, je vous recommande de repenser ce que vous essayez de faire et de voir si vous ne pouvez pas le faire autrement (en utilisant une méthode qui retourne un int , disons … quelle est la meilleure chose à faire) faire est variera d’une situation à l’autre).

Ce n’est pas possible en Java, vous pouvez aussi l’envelopper dans un tableau à un seul élément.

 void demo() { int [] a = { 0 }; increment ( a ) } void increment( int [] v ) { v[0]++; } 

Mais il y a toujours de meilleures options.

Vous ne pouvez pas Mais vous pouvez retourner un entier qui est une valeur modifiée

 int i = 0; i = doSomething(i); 

Si vous en transmettez plusieurs, vous souhaiterez peut-être créer un object de transfert de données (une classe contenant spécifiquement un ensemble de variables pouvant être transmises aux classes).

Passer un object qui a cette valeur en tant que champ.

Ce n’est pas possible en Java

Une option consiste à utiliser des classes comme java.lang.Integer, alors vous ne passez pas de primitive du tout.

Par contre, vous pouvez simplement utiliser du code comme:

 int a = 5; a = func(a); 

et avoir func retourner la valeur modifiée.