Catatan : Awalnya saya memposting kode C # dalam jawaban ini untuk tujuan ilustrasi, karena C # memungkinkan Anda untuk melewati int
parameter dengan referensi dengan ref
kata kunci. Saya telah memutuskan untuk memperbaruinya dengan kode Java legal yang sebenarnya menggunakan MutableInt
kelas pertama yang saya temukan di Google untuk semacam perkiraan apa yang ref
ada di C #. Saya benar-benar tidak tahu apakah itu membantu atau menyakiti jawabannya. Saya akan mengatakan bahwa saya secara pribadi belum melakukan semua pengembangan Java; jadi untuk semua yang saya tahu ada banyak cara idiomatis untuk menggambarkan hal ini.
Mungkin jika kita menulis metode untuk melakukan hal yang setara dengan apa x++
yang akan membuatnya lebih jelas.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
Baik? Tambahkan nilai yang diteruskan dan kembalikan nilai asli: itulah definisi dari operator peningkatan.
Sekarang, mari kita lihat bagaimana perilaku ini diputar dalam kode contoh Anda:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)
melakukan apa? Penambahan x
, ya. Dan kemudian mengembalikan apa yang x
ada sebelum kenaikan . Nilai pengembalian ini kemudian ditugaskan untuk x
.
Jadi urutan nilai yang ditetapkan x
adalah 0, lalu 1, lalu 0.
Ini mungkin masih lebih jelas jika kita menulis ulang di atas:
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.
Fiksasi Anda pada fakta bahwa ketika Anda mengganti x
di sisi kiri dari tugas di atas dengan y
, "Anda dapat melihat bahwa itu pertama kali menambah x, dan kemudian mengaitkannya dengan y" menurut saya bingung. Bukan x
yang ditugaskan y
; ini adalah nilai yang sebelumnya ditugaskanx
. Sungguh, menyuntikkan y
membuat segalanya tidak berbeda dari skenario di atas; kami hanya punya:
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.
Jadi sudah jelas: x = x++
secara efektif tidak mengubah nilai x. Itu selalu menyebabkan x memiliki nilai x 0 , lalu x 0 +1, dan kemudian x 0 lagi.
Pembaruan : Secara kebetulan, jangan sampai Anda ragu x
akan pernah mendapat 1 "antara" operasi kenaikan dan penugasan dalam contoh di atas, saya telah mengumpulkan demo singkat untuk menggambarkan bahwa nilai perantara ini memang "ada," meskipun akan tidak pernah "terlihat" di utas pelaksana.
Demo memanggil x = x++;
secara berulang sementara utas terpisah terus mencetak nilai x
ke konsol.
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 bawah ini adalah kutipan dari output program di atas. Perhatikan kejadian 1s dan 0s yang tidak beraturan.
Mulai utas latar ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1