10 tháng 6 2006

Java: pass by value or pass by reference

Hồi trước học Pascal cũng như mấy bữa nay học VB đều thấy nó cho phép ta có thể lựa chọn giữa việc truyền tham số theo tham trị (pass by value) hay truyền theo tham chiếu (pass by reference).
Pascal VB Theo thầy giảng thì điều đó thể hiện tính linh động, dễ dùng của VB. Tuy vậy, chẳng bao giờ thấy mấy cái ByVal hay ByRef hay var gì gì đó trong Java bao giờ cả, vậy thì Java truyền tham số theo cơ chế nào???
Hãy xem vd sau : Sau khi chạy đoạn chương trình trên, giá trị của a sẽ vẫn là 0 nhưng b[0] bấy giờ sẽ là 1. Như vậy là sao, khác biệt nằm ở đâu?
Điểm khác quan trọng nhất của int aint[] b chính là a sẽ là primitive type còn b sẽ là một đối tượng (object). Tới đây có thể bạn sẽ nghĩ là Java sẽ truyền theo tham trị đối với các biến thuộc primitive type (int, double, char, boolean, ...) và truyền theo tham chiếu đối với các biến là object. Điều đó là hoàn toàn sai lầm và là 1 một trong những sai lầm thường gặp nhất của những người mới học Java. Thực sự là Java luôn luôn truyền theo tham trị (Java is strictly pass-by-value). Hãy xem thêm đoạn chương trình sau Kết quả sau khi chạy biến c vẫn chứa giá trị là 0 mặc dù c là một Object. Vậy tại sao giá trị của b[1] lại thay đổi ở đoạn chương trình trước???

Lý do là biến b thực sự chỉ chứa địa chỉ, chứa tham chiếu tới một đối tượng mảng int[] trong bộ nhớ mà thôi. Khi bạn gọi changeValue2(b) thì tham số hình thức val trong phương thức changeValue2 sẽ nhận được giá trị của biến b, nghĩa là giá trị của b sẽ được copy và gán cho val (đó chính là ý nghĩa của pass by value). Lúc này biến val cũng sẽ chứa tham chiếu tới địa chỉ của mảng int[] trong bộ nhớ mà b tham chiếu tới. Việc gán val[0] = 1 sẽ làm thay đổi giá trị của mảng int[] trong bộ nhớ, khi method kết thúc, biến val bị xóa bỏ, biến b vẫn tiếp tục chứa tham chiếu tới mảng int[] như ban đầu (b không hề thay đổi) nhưng mảng int[] bây giờ đã thay đổi giá trị. Kết quả là ta thấy b[0] bây giờ bằng 1, b đã thay đổi (mà thực sự là giá trị của object mà c tham chiếu tới thay đổi).

Tương tự, trong method changeValue3, do class Integer không thể thay đổi giá trị sau khi constructor thực thi nên ta phải dùng val = new Integer(1). Kết quả là biến val lúc này đã thay đổi, nó chứa tham chiếu tới một object khác có giá trị bằng 1 trong bộ nhớ. Kết thúc phương thức, biến val bị xóa bỏ, biến c, như trên, vẫn không thay đổi và chứa tham chiếu tới object ban đầu có giá trị bằng 0. Vì thế giá trị của c (thực sự là giá trị của object mà c tham chiếu tới) vẫn không thay đổi.

Tóm lại là Java luôn luôn truyền bằng tham trị, luôn luôn pass-by-value và khi bạn tạo một đối tượng kiểu như val = new Integer(1) thì biến val không phải chứa đối tượng mà chỉ chứa tham chiếu tới đối tượng trong bộ nhớ mà thôi.

0 Comments:

Post a Comment




 

Copyright 2006| Blogger Templates by GeckoandFly modified and converted to Blogger Beta by Blogcrowds.
No part of the content or the blog may be reproduced without prior written permission.