web-dev-qa-db-fra.com

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

Je voudrais une sémantique semblable à C# _ ref mot clé.

143
ripper234

Java est déroutant parce que tout est passé par valeur. Cependant, pour un paramètre de type référence (c’est-à-dire pas un paramètre de type primitif), il s’agit de la référence elle-même qui est passé par valeur, d'où il ressort qu'il est passé par référence (et les gens prétendent souvent que c'est le cas) . 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!

Imprime Hello sur la console. Si vous voulez que le code ci-dessus soit imprimé, les options Goodbye sont les suivantes : utilisez une 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"); }
222
oxbow_lakes

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

Non.

Pourquoi ? Java a n seul= le mode de transmission des arguments aux méthodes: par valeur.

Remarque:

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

Pour tous les autres, vous obtenez une copie de la référence, que l'on appelle également transmission par valeur.

Tout est dans cette image:

enter image description here

65
PeterMmm

Dans Java, il n'y a rien au niveau de la langue semblable à ref. Dans Java il n'y a que le passage sémantique de la valeur

Par souci de curiosité, vous pouvez implémenter une sémantique de type ref dans 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();
    }
}

cas de test:

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
dfa

De James Gosling dans "Le Java Langage de programmation"):

"... Il y a exactement un mode de passage de paramètre dans Java - passer par valeur - et cela simplifie les choses. ..."

18
duffymo

Je ne pense pas que tu peux. Votre meilleure option pourrait consister à encapsuler la chose que vous voulez transmettre "par référence" sur une autre instance de classe et à transmettre la référence de la classe (externe) (par valeur). Si vous voyez ce que je veux dire...

en d'autres termes, votre méthode modifie l'état interne de l'objet qui le transmet, lequel est ensuite visible pour l'appelant.

10
Marc Gravell

Java est toujours passé par valeur.

Lorsque vous transmettez une primitive, il s'agit d'une copie de la valeur. Lorsque vous transmettez un objet, vous copiez le pointeur de référence.

7
Nick Holt

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 soit invoquée, 2) on ne peut toujours pas implémenter, par exemple. échanger la méthode de cette manière ... Cette manière est utilisée dans JDK, par exemple. dans Java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).

4
Michal Misiak