Trước khi trả lời câu hỏi này, chúng ta cần hiểu sự khác biệt giữa pass-by-value(tham trị) và pass-by-reference(tham chiếu).
Pass by value
- Pass-by-value được hiểu là khi bạn pass biến vào làm argument cho một function, chương trình sẽ không dùng thẳng biến đó mà sao chép giá trị và đưa cho function, và hệ quả là dù bên trong function xảy ra chuyện gì thì biến thực tế vẫn được bảo toàn.
- Kết quả
Pass by reference
- Ngược lại với Pass-by-value, khi bạn pass biến vào làm argument cho một function, chương trình sẽ đưa thẳng biến đó cho function tùy ý xử lý, và hệ quả là nếu bên trong function mà thay đổi giá trị của argument thì biến thực tế bên ngoài cũng bị thay đổi, vì trong trường hợp này biến bên ngoài và biến(argument) của function là một.
- Kết quả
- Có thể xem hình minh họa bên dưới để hiểu rõ hơn
Vậy trong java thì sao ?
- Theo một cách hiểu nhất định và là cách hiểu mà đa phần đồng ý, thì Java không có Pass-by-reference mà chỉ có Pass-by-value !
- Đọc đến đây, có lẽ nhiều bạn sẽ tự hỏi: vậy tại sao khi tôi truyền 1 tham số không phải dạng primitive type, giá trị của tham số đó lại bị thay đổi.
Điều gì thực sự xảy ra khi tôi truyền 1 tham số non-primitive type vào function?
- Trước tiên, bạn cần hiểu reference trong Java là gì. Ví dụ ta khai báo biến f, có type là Foo như sau:
- Đoạn trên có thể giải thích như sau:
- Biến f mà chúng ta luôn nghĩ là đối tượng thực trong bộ nhớ thực ra không phải, nó chỉ là tham chiếu đến đối tượng ở bên trong ô nhớ.
- Và trên thực tế là khi bạn pass một reference vào một function, ví dụ là ta truyền f vào thì chương trình sẽ tạo ra một reference khác (tạm gọi là a)và link nó đến cùng đối tượng mà f trỏ vào, hay nói cách khác, nó copy reference f.
- Do đó, khi truyền biến f vào 1 function, ví dụ:
public static void setAttribute(Foo f) {
f.setAttribute("c");
}
và khi function setAttribute chạy xong, reference a(clone từ f) tạm coi là biến mất do đã ra ngoài function, lúc này chỉ còn f và đối tượng Foo đã được thay đổi.
- Nghe có vẻ giống Pass-by-reference, nhưng sự thật là không. Phương pháp này của Java không phải Pass-by-reference, nó nên được hiểu là Pass-by-value reference, chương trình không thực sự pass chính xác reference f vào function modifyReference, mà chương trình chỉ pass cái clone của nó(reference a) vào mà thôi. Giờ thì nghe giống Pass-by-value chưa!
Kết luận
- Để có thể hiểu rõ hơn về phần này, các bạn có thể đọc trong cuốn sách có thể gọi là gối tay khi bắt đầu học Java, đó là cuốn ‘Head First Java’. Và chúng ta có thể kết luận là trong Java, chỉ có Pass-by-value !