Note: a l'Origine, j'ai posté le code C# dans cette réponse, pour les fins de l'illustration, depuis C# permet de passer int
des paramètres par référence avec l' ref
mot-clé. J'ai décidé de le mettre à jour avec la réalité juridique de code Java à l'aide de la première MutableInt
classe que j'ai trouvé sur Google pour en quelque sorte une approximation de ce qu' ref
t en C#. Je ne peux pas vraiment dire si cela aide ou blesse la réponse. Je dirai que, personnellement, je n'ai pas fait beaucoup de développement Java, de sorte que pour tout ce que je sais, il pourrait être beaucoup plus idiomatiques façons d'illustrer ce point.
Peut-être que si nous écrivons une méthode pour faire l'équivalent de ce qu' x++
qu'il ne fera plus claire à ce sujet.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
Droit? Incrémenter la valeur passée et retourner à la valeur originale: c'est la définition de l'opérateur de post-incrémentation.
Maintenant, nous allons voir comment ce comportement se joue dans votre exemple de code:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)
fait quoi? Incréments x
, oui. Et puis retourne ce x
a été avant de l'incrément. Cette valeur de retour, puis se voit assignée x
.
Donc l'ordre des valeurs assignées à l' x
0, puis 1, puis 0.
Cela peut être plus clair encore si nous ré-écrivez ci-dessus:
MutableInt x = new MutableInt(); // x is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
x = temp; // Now x is 0 again.
Votre fixation sur le fait que lorsque vous remplacez x
sur le côté gauche de l'affectation ci-dessus avec y
", vous pouvez voir qu'il incrémente x et version ultérieure des attributs de il y" me semble confus. Il n'est pas x
qui est affecté à l' y
; c'est la valeur anciennement attribuée à l' x
. Vraiment, l'injection d' y
rend les choses ne sont pas différents de scénario ci-dessus; nous avons simplement obtenu:
MutableInt x = new MutableInt(); // x is 0.
MutableInt y = new MutableInt(); // y is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
y = temp; // y is still 0.
Il est donc clair: x = x++
effectivement ne change pas la valeur de x. Il provoque toujours à x les valeurs de x0, alors x0 + 1, puis x0 nouveau.
Mise à jour: par ailleurs, de peur de vous en doutez x
est affectée à 1 "entre" l'opération d'incrémentation et de l'affectation dans l'exemple ci-dessus, j'ai jeté un rapide de démonstration pour illustrer le fait que cette valeur intermédiaire ne fait "exister", mais il ne sera jamais "vu" sur le thread qui s'exécute.
La démo appels x = x++;
dans une boucle alors qu'un thread séparé en permanence imprime la valeur de x
à la console.
public class Main {
public static volatile int x = 0;
public static void main(String[] args) {
LoopingThread t = new LoopingThread();
System.out.println("Starting background thread...");
t.start();
while (true) {
x = x++;
}
}
}
class LoopingThread extends Thread {
public @Override void run() {
while (true) {
System.out.println(Main.x);
}
}
}
Ci-dessous est un extrait du programme ci-dessus est de sortie. Avis de l'alternance irrégulière de deux 1s et 0s.
Départ thread d'arrière-plan...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1