Réponses:
Java est déroutant car 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), c'est la référence elle-même qui est passée par valeur, donc elle semble être pass-by-reference (et les gens le prétendent souvent). 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 souhaitez imprimer le code ci-dessus Goodbye
sont d' utiliser 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"); }
Puis-je transmettre des paramètres par référence en Java?
Non.
Pourquoi ? Java n'a qu'un seul mode de transmission d'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 et cela s'appelle également passer par valeur.
Tout est dans cette image:
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();
}
}
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"
AtomicReference
(pour les non-primitifs)? Ou AtomicSomething
(par exemple AtomicBoolean
:) pour les primitives?
int
place de Integer
, bool
au lieu de Boolean
et ainsi de suite? Autrement dit, les classes wrapper (qui sont automatiquement déballées si vous vous inquiétez de la syntaxe) ne fonctionnent pas?
De James Gosling dans "The Java Programming Language":
"... Il y a exactement un mode de passage de paramètre en Java - passer par valeur - et cela simplifie les choses. .."
The pronouncement of the language god should be declared the answer
Pas vraiment. Malgré ce que le créateur de Java pense ou croit, la réponse absolue viendrait d'une citation de la spécification du langage.
Je ne pense pas que vous puissiez. Votre meilleure option pourrait être d'encapsuler l'élément que vous voulez passer "par ref" sur une autre instance de classe, et de transmettre la référence de la classe (externe) (par valeur). Si tu vois ce que je veux dire...
c'est-à-dire que votre méthode change l'état interne de l'objet auquel elle est passée, qui est alors visible par l'appelant.
Une autre option est d'utiliser un tableau, par exemple
void method(SomeClass[] v) { v[0] = ...; }
mais 1) le tableau doit être initialisé avant la méthode invoquée, 2) on ne peut toujours pas implémenter par exemple la méthode de swap de cette façon ... Cette façon est utilisée dans JDK, par exemple dans java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[])
.