123 votes

Comment faire l'équivalent de passage par référence pour les primitives en 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);   
    }   
}  

seront de sortie ce:

Jouet nombre de jouer à 5 
Jouet nombre dans le jeu après increement 6 
Jouet numéro principal 5 

En C++, je peux passer l' toyNumber variable que le passage par référence pour éviter les effets d'ombre c'est à dire la création d'une copie de la même variable comme 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 ceci:

Jouet nombre de jouer à 5 
Jouet nombre dans le jeu après increement 6 
Jouet numéro principal 6 

Ma question est - Ce qui est l'équivalent de code en Java pour obtenir le même résultat que le code C++, étant donné que Java est le passage par valeur plutôt que de passer par référence?

185voto

laslowh Points 3209

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

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

class MyToy {
  public int toyNumber;
}

puis passer 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: le retour de 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 aurait besoin d'un petit changement à la callsite principale, de sorte qu'il lit, toyNumber = temp.play(toyNumber);.

Choix 3: faire une classe ou d'une variable statique

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

Choix 4: Créer un seul élément de tableau de type int et de l'

Ceci est considéré comme un hack, mais est parfois utilisé pour les valeurs de retour de inline classe des invocations.

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

30voto

Kerem Baydoğan Points 4814

Java n'est pas d'appel par référence , il est appel par valeur seulement

Mais un objet de valeur est aussi sa référence

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

La 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 voir ce comportement dans les bibliothèques Standard. Par exemple des Collections.sort(); Collections.shuffle(); Cette méthode ne renvoie pas une nouvelle liste, mais modifie l'argument de l'objet.

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

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

18voto

Ingo Points 21438

Faire un

class PassMeByRef { public int theValue; }

puis passer une référence à une instance. Noter qu'une méthode qui mute de l'état par le biais de ses arguments est préférable d'éviter, surtout dans du code en parallèle.

11voto

Ernest Friedman-Hill Points 56605

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

Dans une situation où vous avez vraiment besoin de passer un primitif, par valeur, ce que les gens font parfois de déclarer le paramètre comme un tableau de type primitif, et puis de passer un seul élément de tableau comme argument. De sorte que vous passer une référence int[1], et dans la méthode, vous pouvez modifier le contenu de la matrice.

10voto

premSiva Points 11

Pour une solution rapide, vous pouvez utiliser AtomicInteger ou de toute atomique variables qui vous permettra de changer la valeur à l'intérieur de la méthode à l'aide de la fonction intégrée de méthodes. 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X