Java – Truyền theo giá trị và không truyền theo tham chiếu

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ị.

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.