Lưu ý : Ban đầu tôi đã đăng mã C # trong câu trả lời này cho mục đích minh họa, vì C # cho phép bạn truyền int
tham số bằng cách tham chiếu với ref
từ khóa. Tôi đã quyết định cập nhật nó với mã Java hợp pháp thực tế bằng cách sử dụng MutableInt
lớp đầu tiên tôi tìm thấy trên Google để sắp xếp gần đúng những gì ref
trong C #. Tôi thực sự không thể biết nếu điều đó giúp hoặc làm tổn thương câu trả lời. Tôi sẽ nói rằng cá nhân tôi đã không thực hiện tất cả sự phát triển Java đó; vì vậy đối với tất cả tôi biết có thể có nhiều cách thành ngữ hơn để minh họa điểm này.
Có lẽ nếu chúng ta viết ra một phương pháp để làm tương đương với những gì x++
nó sẽ làm cho điều này rõ ràng hơn.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
Đúng? Tăng giá trị được thông qua và trả về giá trị ban đầu: đó là định nghĩa của toán tử postrement.
Bây giờ, hãy xem cách hành vi này diễn ra trong mã ví dụ của bạn:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)
Làm gì? Tăng x
, vâng. Và sau đó trả về những gì x
là trước khi tăng . Giá trị trả về này sau đó được gán cho x
.
Vì vậy, thứ tự của các giá trị được gán x
là 0, rồi 1, rồi 0.
Điều này có thể rõ ràng hơn nếu chúng ta viết lại ở trên:
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.
Sự cố định của bạn về thực tế là khi bạn thay thế x
ở phía bên trái của bài tập trên y
, "bạn có thể thấy rằng nó đầu tiên tăng x, và sau đó quy nó thành y" khiến tôi bối rối. Nó không phải x
là được giao cho y
; nó là giá trị trước đây được gán chox
. Thực sự, tiêm y
khiến mọi thứ không khác với kịch bản trên; chúng tôi chỉ đơn giản là có:
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.
Vì vậy, rõ ràng: x = x++
hiệu quả không thay đổi giá trị của x. Nó luôn khiến x có các giá trị x 0 , sau đó x 0 + 1 và sau đó x 0 lần nữa.
Cập nhật : Ngẫu nhiên, e rằng bạn nghi ngờ rằng x
đã từng được gán cho 1 "giữa" thao tác tăng và phép gán trong ví dụ trên, tôi đã đưa ra một bản demo nhanh để minh họa rằng giá trị trung gian này thực sự "tồn tại", mặc dù nó sẽ không bao giờ được "nhìn thấy" trên luồng thực thi.
Bản demo gọi x = x++;
trong một vòng lặp trong khi một luồng riêng biệt liên tục in giá trị của x
bàn điều khiển.
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);
}
}
}
Dưới đây là một đoạn trích của đầu ra của chương trình trên. Lưu ý sự xuất hiện bất thường của cả 1 và 0.
Bắt đầu chủ đề nền ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1