Một trong những nhầm lẫn trong ngôn ngữ lập trình Java là liệu Java được truyền theo giá trị hay truyền theo tham chiếu. Nhưng trước tiên chúng ta cũng cần hiểu nghĩa của truyền theo giá trị và truyền theo tham chiếu là gì?
- Truyền theo giá trị: Các giá trị tham số phương thức được sao chép sang một biến khác và sau đó sao chép của object được truyền, đó là lý do tại sao nó được gọi là truyền theo giá trị
- Truyền theo tham chiếu: Một alias hoặc tham chiếu đến tham số thực tế được truyền cho phương thức, đó là lý do tại sao nó được gọi là truyền theo tham chiếu
Java luôn luôn được truyền theo giá trị và không truyền theo tham chiếu, chúng ta có thể chứng minh điều đó bằng ví dụ đơn giản sau đây
Giả sử chúng ta có class Balloon
như sau:
package com.example.test; public class Balloon { private String color; public Balloon(){} public Balloon(String c){ this.color = c; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } }
Và chúng ta có một chương trình đơn giản với một phương thức chung dùng để hoán đổi hai object, clas như sau:
package com.example.test; public class Test { public static void main(String[] args) { Balloon red = new Balloon("Red"); // tham chiếu bộ nhớ 50 Balloon blue = new Balloon("Blue"); // tham chiếu bộ nhớ 100 swap(red, blue); System.out.println("red color=" + red.getColor()); System.out.println("blue color=" + blue.getColor()); foo(blue); System.out.println("blue color=" + blue.getColor()); } private static void foo(Balloon balloon) { //baloon=100 balloon.setColor("Red"); //baloon=100 balloon = new Balloon("Green"); //baloon=200 balloon.setColor("Blue"); //baloon = 200 } // Phương thức hoán đổi chung public static void swap(Object o1, Object o2){ Object temp = o1; o1=o2; o2=temp; } }
Kết quả
red color=Red blue color=Blue blue color=Red
Nếu bạn nhìn 2 hàng đầu tiên của kết quả, rõ ràng rằng phương thức hoán đổi đã không hoạt động. Đấy là bởi vì Java được truyền bởi giá trị, phương thức swap()
này có thể sử dụng với bất kỳ ngôn ngữ lập trình này để kiểm tra liệu nó được truyền theo giá trị hay tham chiếu.
Tiếp theo hãy cùng phân tích các bước chạy chương trình
Balloon red = new Balloon("Red"); Balloon blue = new Balloon("Blue");
Khi chúng ta sử dụng toán tử new
để tạo một instance, instance được tạo và biến chứa vị trí tham chiếu của bộ nhớ nơi object được lưu. Trong ví dụ của chúng ta, giả sử “red” được trỏ đến 50 và “blue” được trỏ đến 100 và đây là những vị trí bộ nhớ của cả 2 Ballon object
Bây giờ khi chúng ta gọi phương thức swap()
, cả 2 biến mới o1 và o2 được tạo và đều trỏ đến 50 và 100 tương ứng.
Đoạn trích code bên dưới đây sẽ giải thích phương thức swap()
hoạt động như thế nào
public static void swap(Object o1, Object o2){ //o1=50, o2=100 Object temp = o1; //temp=50, o1=50, o2=100 o1=o2; //temp=50, o1=100, o2=100 o2=temp; //temp=50, o1=100, o2=50 } // phương thức kết thúc
Chú ý rằng chúng ta đang thay đổi giá trị của o1 và o2 nhưng chúng được sao chép vị trí tham chiếu của “red” và “blue” do đó không có sự thay đổi trong giá trị “red” và “blue” và kết quả như đã thấy
Nếu bạn đã hiểu cho đến đây, thì bạn có thể hiểu nguyên nhân của sự nhầm lẫn. Do các biến chỉ được tham chiếu đến các object, nên nó gây nhầm lẫn rằng chúng ta đang truyền tham chiếu để Java được truyền bằng tham chiếu. Tuy nhiên, chúng ta đang truyền một bản sao của tham chiếu và vì thế nó được truyền bởi giá trị. Hy vọng rằng các nghi ngờ hiện tại đã rõ ràng
Tiếp theo hãy cùng phân tích phương thức food()
private static void foo(Balloon balloon) { //baloon=100 balloon.setColor("Red"); //baloon=100 balloon = new Balloon("Green"); //baloon=200 balloon.setColor("Blue"); //baloon = 200 }
Dòng đầu tiên là dòng quan trọng, khi chúng ta gọi một phương thức, phương thức được gọi trên object tại vị trí tham chiếu. Tại vị trí này Ballon đang trỏ đến 100 và do đó color được chuyển sang thành “Red”.
Dòng tiếp theo, tham chiếu ballon được chuyển thành 200 và bất kỳ phương thức nào được gọi thêm nữa sẽ xảy ra trên object tại vị trí bộ nhớ 200 và nó không có bất kỳ ảnh hưởng nào tại vị trí bộ nhớ 100. Điều này giải thích vì sao dòng thứ 3 kết quả in ra blue color=Red.
Hy vọng giải thích trên giúp bạn hiểu rõ hơn và loại bỏ được các nghi ngờ, nhớ rằng các biến là các tham chiếu hay các con trỏ và nó sao chép lại được truyền đến các phương thức, nên Java luôn luôn được truyền bằng giá trị.