Come fare l’equivalente del passaggio per riferimento per le primitive in Java

Questo codice Java:

public class XYZ { public static void main(){ int toyNumber = 5; XYZ temp = new XYZ(); temp.play(toyNumber); System.out.println("Toy number in main " + toyNumber); } void play(int toyNumber){ System.out.println("Toy number in play " + toyNumber); toyNumber++; System.out.println("Toy number in play after increement " + toyNumber); } } 

produrrà questo:

 
 Numero del giocattolo in gioco 5  
 Numero del giocattolo in gioco dopo l'integrazione 6  
 Numero del giocattolo nel principale 5  

In C ++ posso passare la variabile toyNumber come passaggio per riferimento per evitare lo shadowing, ovvero creare una copia della stessa variabile come di seguito:

 void main(){ int toyNumber = 5; play(toyNumber); cout << "Toy number in main " << toyNumber << endl; } void play(int &toyNumber){ cout << "Toy number in play " << toyNumber << endl; toyNumber++; cout << "Toy number in play after increement " << toyNumber << endl; } 

e l’output in C ++ sarà questo:

 Numero del giocattolo in gioco 5  
 Numero del giocattolo in gioco dopo l'integrazione 6  
 Numero del giocattolo nel principale 6  

La mia domanda è: qual è il codice equivalente in Java per ottenere lo stesso output del codice C ++, dato che Java è passato per valore anziché passare per riferimento ?

Hai diverse scelte. Quello che ha più senso dipende da cosa stai cercando di fare.

Scelta 1: crea toyNumber come variabile membro pubblico in una class

 class MyToy { public int toyNumber; } 

quindi passa un riferimento a un MyToy al tuo metodo.

 void play(MyToy toy){ System.out.println("Toy number in play " + toy.toyNumber); toy.toyNumber++; System.out.println("Toy number in play after increement " + toy.toyNumber); } 

Scelta 2: restituisce il valore invece di passare per riferimento

 int play(int toyNumber){ System.out.println("Toy number in play " + toyNumber); toyNumber++; System.out.println("Toy number in play after increement " + toyNumber); return toyNumber } 

Questa scelta richiederebbe una piccola modifica al callsite in main in modo che venga letto, toyNumber = temp.play(toyNumber); .

Scelta 3: rendila una class o una variabile statica

Se le due funzioni sono metodi sulla stessa class o istanza di class, è ansible convertire toyNumber in una variabile membro della class.

Scelta 4: crea una singola matrice di elementi di tipo int e passa quella

Questo è considerato un hack, ma a volte viene utilizzato per restituire valori da invocazioni di classi inline.

 void play(int [] toyNumber){ System.out.println("Toy number in play " + toyNumber[0]); toyNumber[0]++; System.out.println("Toy number in play after increement " + toyNumber[0]); } 

Java non è chiamata per riferimento , è solo chiamata per valore

Ma tutte le variabili del tipo di object sono in realtà dei puntatori.

Quindi se usi un object mutevole vedrai il comportamento che vuoi

 public class XYZ { public static void main(String[] arg) { StringBuilder toyNumber = new StringBuilder("5"); play(toyNumber); System.out.println("Toy number in main " + toyNumber); } private static void play(StringBuilder toyNumber) { System.out.println("Toy number in play " + toyNumber); toyNumber.append(" + 1"); System.out.println("Toy number in play after increement " + toyNumber); } } 

Uscita di questo codice:

 run: Toy number in play 5 Toy number in play after increement 5 + 1 Toy number in main 5 + 1 BUILD SUCCESSFUL (total time: 0 seconds) 

Puoi vedere questo comportamento anche nelle librerie standard. Ad esempio Collections.sort (); Collections.shuffle (); Questi metodi non restituiscono una nuova lista ma modifica il suo object argomento.

  List mutableList = new ArrayList(); mutableList.add(1); mutableList.add(2); mutableList.add(3); mutableList.add(4); mutableList.add(5); System.out.println(mutableList); Collections.shuffle(mutableList); System.out.println(mutableList); Collections.sort(mutableList); System.out.println(mutableList); 

Uscita di questo codice:

 run: [1, 2, 3, 4, 5] [3, 4, 1, 5, 2] [1, 2, 3, 4, 5] BUILD SUCCESSFUL (total time: 0 seconds) 

Fare un

 class PassMeByRef { public int theValue; } 

quindi passare un riferimento a un’istanza di esso. Si noti che è meglio evitare un metodo che muta lo stato attraverso i suoi argomenti, specialmente nel codice parallelo.

Non è ansible passare primitive per riferimento in Java. Tutte le variabili del tipo di object sono in realtà dei puntatori, naturalmente, ma li chiamiamo “riferimenti” e vengono sempre anche passati per valore.

In una situazione in cui è davvero necessario passare un valore primitivo per valore, ciò che le persone fanno a volte è dichiarare il parametro come una matrice di tipo primitivo e quindi passare un array di elementi singoli come argomento. Quindi si passa un riferimento int [1] e nel metodo è ansible modificare il contenuto dell’array.

Per una soluzione rapida, è ansible utilizzare AtomicInteger o una qualsiasi delle variabili atomiche che consente di modificare il valore all’interno del metodo utilizzando i metodi incorporati. Ecco un esempio di codice:

 import java.util.concurrent.atomic.AtomicInteger; public class PrimitivePassByReferenceSample { /** * @param args */ public static void main(String[] args) { AtomicInteger myNumber = new AtomicInteger(0); System.out.println("MyNumber before method Call:" + myNumber.get()); PrimitivePassByReferenceSample temp = new PrimitivePassByReferenceSample() ; temp.changeMyNumber(myNumber); System.out.println("MyNumber After method Call:" + myNumber.get()); } void changeMyNumber(AtomicInteger myNumber) { myNumber.getAndSet(100); } } 

Produzione:

 MyNumber before method Call:0 MyNumber After method Call:100 
 public static void main(String[] args) { int[] toyNumber = new int[] {5}; NewClass temp = new NewClass(); temp.play(toyNumber); System.out.println("Toy number in main " + toyNumber[0]); } void play(int[] toyNumber){ System.out.println("Toy number in play " + toyNumber[0]); toyNumber[0]++; System.out.println("Toy number in play after increement " + toyNumber[0]); }