Nota : in origine ho inserito il codice C # in questa risposta a scopo illustrativo, poiché C # consente di passare intparametri tramite riferimento con la refparola chiave. Ho deciso di aggiornarlo con l'effettivo codice Java legale utilizzando la prima MutableIntclasse che ho trovato su Google per una sorta di approssimazione di ciò che reffa in C #. Non posso davvero dire se questo aiuta o fa male la risposta. Dirò che personalmente non ho fatto molto sviluppo Java; quindi, per quanto ne so, potrebbero esserci modi molto più idiomatici per illustrare questo punto.
Forse se scriviamo un metodo per fare l'equivalente di ciò x++che lo renderà più chiaro.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
Giusto? Incrementa il valore passato e restituisce il valore originale: questa è la definizione dell'operatore di postincremento.
Ora vediamo come si comporta questo comportamento nel tuo codice di esempio:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)fa cosa? Incrementi x, si. E quindi restituisce ciò che x era prima dell'incremento . Questo valore restituito viene quindi assegnato a x.
Quindi l'ordine dei valori assegnati xè 0, quindi 1, quindi 0.
Questo potrebbe essere ancora più chiaro se riscriviamo quanto sopra:
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.
La tua fissazione sul fatto che quando sostituisci xsul lato sinistro del compito sopra con y"puoi vedere che prima incrementa x, e successivamente lo attribuisce a y" mi sembra confuso. Non è xche viene assegnato a y; è il valore precedentemente assegnato ax . In realtà, l'iniezione yrende le cose non diverse dallo scenario sopra; abbiamo semplicemente ottenuto:
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.
Quindi è chiaro: x = x++effettivamente non cambia il valore di x. Fa sempre in modo che x abbia i valori x 0 , quindi x 0 + 1, quindi nuovamente x 0 .
Aggiornamento : Per inciso, per non dubitare che xvenga mai assegnato a 1 "tra" l'operazione di incremento e l'assegnazione nell'esempio sopra, ho gettato insieme una rapida demo per illustrare che questo valore intermedio effettivamente "esiste", anche se sarà mai essere "visto" sul thread in esecuzione.
La demo chiama x = x++;in loop mentre un thread separato stampa continuamente il valore di xsulla 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);
}
}
}
Di seguito è riportato un estratto dell'output del programma precedente. Notare il verificarsi irregolare di entrambi 1 e 0.
Avvio del thread in background ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1