Not : Aslında, C # kodunu örnekleme amacıyla bu cevapta yayınladım, çünkü C # int
parametreleri ref
anahtar kelimeyle referans olarak geçirmenize izin veriyor . MutableInt
Google'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ı x
0, 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 x
yukarı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. x
Atanan bu değildir y
; öyle eskiden atanan değerx
. Gerçekten, enjekte y
etmek 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, x
arttı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 x
olarak 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