Puis-je passer des paramètres par référence en Java?


J'aimerais sémantique similaire à C#'s ref mot-clé.

Author: oxbow_lakes, 2009-07-01

7 answers

Java est source de confusion car tout est passé par la valeur . Cependant, pour un paramètre de type de référence (c'est à dire pas un paramètre de type primitif), il est la référence elle-même, qui est passé par valeur, donc il apparaît pour être passé par référence (et souvent les gens disent qu'il est). Ce n'est pas le cas, comme le montre ce qui suit:

Object o = "Hello";
mutate(o)
System.out.println(o);

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

Imprimera Hello sur la console. Les options si vous vouliez que le code ci-dessus imprime Goodbye sont de utiliser un référence explicite comme suit:

AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!

private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
 215
Author: oxbow_lakes, 2009-07-01 13:01:12

Puis-je passer des paramètres par référence dans Java?

Non.

Pourquoi ? Java n'a qu'un seul mode pour passer des arguments aux méthodes: par valeur.

Remarque:

Pour les primitives c'est facile à comprendre: vous obtenez une copie de la valeur.

Pour tous les autres, vous obtenez une copie de la référence et cela s'appelle également passer par valeur.

Tout est dans cette image:

entrez la description de l'image ici

 66
Author: PeterMmm, 2011-09-23 09:13:19

En Java, il n'y a rien au niveau du langage similaire à ref. En Java il n'y a que le passage par valeur sémantique

Par curiosité, vous pouvez implémenter une sémantique de type ref en Java en enveloppant simplement vos objets dans une classe mutable:

public class Ref<T> {

    private T value;

    public Ref(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

    public void set(T anotherValue) {
        value = anotherValue;
    }

    @Override
    public String toString() {
        return value.toString();
    }

    @Override
    public boolean equals(Object obj) {
        return value.equals(obj);
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }
}

Testcase:

public void changeRef(Ref<String> ref) {
    ref.set("bbb");
}

// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"
 23
Author: dfa, 2009-11-27 11:45:40

De James Gosling dans "Le langage de programmation Java":

"...Il y a exactement un mode de passage de paramètre en Java - pass by value - et cela garde les choses simples. .."

 18
Author: duffymo, 2009-07-01 22:06:43

Je ne pense pas que vous pouvez. Votre meilleure option pourrait être d'encapsuler la chose que vous voulez passer "par ref" sur une autre instance de classe, et de passer la référence de la classe (externe) (par valeur). Si vous voyez ce que je veux dire...

C'est-à-dire que votre méthode change l'état interne de l'objet qu'elle passe, qui est alors visible pour l'appelant.

 10
Author: Marc Gravell, 2009-07-01 12:06:14

Java est toujours passé par valeur.

Lorsque vous passez une primitive c'est une copie de la valeur, lorsque vous passez un objet c'est une copie du pointeur de référence.

 5
Author: Nick Holt, 2009-07-01 12:23:50

Une autre option consiste à utiliser un tableau, par exemple void method(SomeClass[] v) { v[0] = ...; } mais 1) le tableau doit être initialisé avant que la méthode ne soit invoquée, 2) on ne peut toujours pas implémenter par exemple la méthode swap de cette façon... Cette méthode est utilisée dans JDK, par exemple dans java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).

 4
Author: Michal Misiak, 2012-06-25 09:52:22