Not : Aslında, C # kodunu örnekleme amacıyla bu cevapta yayınladım, çünkü C # intparametreleri refanahtar kelimeyle referans olarak geçirmenize izin veriyor . MutableIntGoogle'da bulduğum birinci sınıfı kullanarak gerçek yasal Java koduyla güncellemeye karar verdim ref. Bunun cevaba yardım edip etmediğini gerçekten söyleyemem. Ben şahsen bu kadar çok Java geliştirmesi yapmadığımı söyleyeceğim; bu yüzden bildiğim kadarıyla bu noktayı açıklamanın çok daha deyimsel yolları olabilir.
Belki de bunu yapan şeyin eşdeğerini yapmak için bir yöntem yazarsak x++, bunu daha net hale getirir.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
Sağ? Geçirilen değeri artırın ve orijinal değeri döndürün: bu, arttırma operatörünün tanımıdır.
Şimdi bu davranışın örnek kodunuzda nasıl oynandığını görelim:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)ne yapar? Artışlar x, evet. Ve sonra neler döndürür x oldu sayının önceki . Bu dönüş değeri daha sonra atandı x.
Böylece, atanan değerlerin sırası x0, sonra 1, sonra 0 olur.
Yukarıdakileri yeniden yazarsak, bu daha net olabilir:
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.
Aslında üzerinde sabitleme değiştirdiğinizde, o xyukarıda atama sol tarafında y, "Eğer ilk artışlarla x olduğunu görebilir ve daha sonra y de ilişkilendirir" karıştırılmamalıdır olarak beni oldukça etkiliyor. xAtanan bu değildir y; öyle eskiden atanan değerx . Gerçekten, enjekte yetmek işleri yukarıdaki senaryodan farklı kılmaz ; basitçe:
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.
Bu yüzden açık: x = x++x'in değerini etkili bir şekilde değiştirmez. Her zaman x'in x 0 , sonra x 0 + 1 ve tekrar x 0 değerlerine sahip olmasına neden olur .
Güncelleme : Bu arada, xarttırma işlemi ve yukarıdaki örnekte atama arasında 1 "e atanmış olduğundan şüphe ederseniz , bu ara değerin gerçekten" var "olduğunu göstermek için hızlı bir demo attım. yürütme iş parçacığında asla "görülmez".
x = x++;Ayrı bir iş parçacığı sürekli xolarak konsola değerini yazdırırken demo bir döngü içinde çağırır .
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);
}
}
}
Aşağıda, yukarıdaki programın çıktısından bir alıntı yer almaktadır. Hem 1s hem de 0s'ın düzensiz oluşumuna dikkat edin.
Arka plan iş parçacığı başlatılıyor ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1