web-dev-qa-db-fra.com

Comment faire l'équivalent de passer par référence pour les primitives dans Java

Ce code 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);   
    }   
}  

affichera ceci:

 
 Numéro de jouet en jeu 5 
 Numéro de jouet en jeu après augmentation 6 
 Numéro de jouet dans la partie principale 5 

En C++, je peux passer la variable toyNumber comme passe par référence pour éviter l'observation, c'est-à-dire créer une copie de la même variable que ci-dessous:

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;   
} 

et la sortie C++ sera la suivante:

 Numéro de jouet en jeu 5 
 Numéro de jouet en jeu après augmentation 6 
 Numéro de jouet dans la partie principale 6 

Ma question est la suivante: quel est le code équivalent dans Java pour obtenir le même résultat que le code C++, étant donné que Java est transmis par valeur plutôt que par référence ?

104
Student

Vous avez plusieurs choix. Celui qui a le plus de sens dépend vraiment de ce que vous essayez de faire.

Choix 1: faire de toyNumber une variable membre publique dans une classe

class MyToy {
  public int toyNumber;
}

puis passez une référence à un MyToy à votre méthode.

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);   
}

Choix 2: renvoyer la valeur au lieu de passer par référence

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
}

Ce choix nécessiterait une petite modification du site d’appel dans main afin qu’il se lise, toyNumber = temp.play(toyNumber);.

Choix 3: en faire une classe ou une variable statique

Si les deux fonctions sont des méthodes d'une même classe ou d'une même instance de classe, vous pouvez convertir toyNumber en une variable de membre de classe.

Choix 4: Créez un tableau à un seul élément de type int et transmettez-le

Ceci est considéré comme un hack, mais est parfois utilisé pour renvoyer des valeurs d'invocations de classe en ligne.

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]);   
}
167
laslowh

Java is not appel par référence il est appel par valeur uniquement

Mais toutes les variables de type d'objet sont en réalité des pointeurs.

Donc, si vous utilisez un objet mutable, vous verrez le comportement que vous souhaitez

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);
    }
}

Sortie de ce code:

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)

Vous pouvez également constater ce comportement dans les bibliothèques standard. Par exemple Collections.sort (); Collections.shuffle (); Ces méthodes ne renvoient pas une nouvelle liste mais modifient son objet argument.

    List<Integer> mutableList = new ArrayList<Integer>();

    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);

Sortie de ce code:

run:
[1, 2, 3, 4, 5]
[3, 4, 1, 5, 2]
[1, 2, 3, 4, 5]
BUILD SUCCESSFUL (total time: 0 seconds)
28
Kerem Baydoğan

Faire un

class PassMeByRef { public int theValue; }

puis passez une référence à une instance de celle-ci. Notez qu’il est préférable d’éviter une méthode qui mute d’état par le biais de ses arguments, en particulier dans le code parallèle.

18
Ingo

Vous ne pouvez pas transmettre de primitives par référence en Java. Toutes les variables de type d'objet sont en fait des pointeurs, bien sûr, mais nous les appelons "références", et elles sont également toujours passées par valeur.

Dans une situation où vous avez vraiment besoin de passer une primitive par référence, ce que les gens vont parfois faire, c'est déclarer le paramètre en tant que tableau de type primitif, puis passer un tableau à un seul élément en tant qu'argument. Donc, vous passez une référence int [1], et dans la méthode, vous pouvez changer le contenu du tableau.

10

Pour une solution rapide, vous pouvez utiliser AtomicInteger ou l’une des variables atomiques, ce qui vous permettra de modifier la valeur dans la méthode à l’aide des méthodes incorporées. Voici un exemple de code:

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);

    }

}

Sortie:

MyNumber before method Call:0

MyNumber After method Call:100
10
premSiva
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]);
}
2
itun