Trang chủHướng dẫnJava truyền bằng giá trị hay tham chiếu? Java truyền bằng giá trị hay tham chiếu: Tất tần tật kiến thức 2025
Java

Java truyền bằng giá trị hay tham chiếu? Java truyền bằng giá trị hay tham chiếu: Tất tần tật kiến thức 2025

CyStack blog 5 phút để đọc
CyStack blog02/06/2025
Reading Time: 5 minutes

Java truyền bằng giá trị hay tham chiếu? Nhiều lập trình viên Java thắc mắc liệu ngôn ngữ này thuộc loại pass by value (truyền bằng giá trị) hay pass by reference (truyền bằng tham chiếu). Bài viết này sẽ giải thích tại sao Java luôn là pass by value.

Đầu tiên, bạn nên hiểu pass by value và pass by reference là gì:

  • Pass by value: Các giá trị của tham số phương thức được sao chép sang một biến khác. Sau đó bản sao của chúng được truyền vào phương thức. Phương thức sẽ làm việc với bản sao này.
  • Pass by reference: Một alias (bí danh) hoặc tham chiếu trực tiếp đến tham số gốc được truyền vào phương thức. Phương thức sẽ truy cập trực tiếp và có thể thay đổi tham số gốc.

Thường thì, sự nhầm lẫn xoay quanh các thuật ngữ này xuất phát từ khái niệm object reference (tham chiếu đối tượng) trong Java. Về mặt kỹ thuật, Java luôn là pass by value. Lý do là ngay cả khi một biến chứa tham chiếu đến một đối tượng khác, thì chính tham chiếu đối tượng đó cũng chính là một giá trị (địa chỉ bộ nhớ của đối tượng). Do đó, các tham chiếu đối tượng được truyền đi bằng cách sao chép giá trị của tham chiếu đó.

Cả kiểu dữ liệu tham chiếu (reference) lẫn kiểu dữ liệu nguyên thủy (primitive) đều được truyền bằng giá trị.

Ngoài việc hiểu về các kiểu dữ liệu, việc nắm rõ cách cấp phát bộ nhớ trong Java cũng rất quan trọng bởi vì kiểu dữ liệu tham chiếu và kiểu dữ liệu nguyên thủy được lưu trữ theo những cách khác nhau.

Minh họa cơ chế pass by value

Ví dụ sau đây minh họa cách các giá trị được truyền trong Java bằng một chương trình sử dụng class sau:

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;
	}
}

Chương trình sau đây sử dụng một phương thức generic nhằm mục đích hoán đổi hai biến. Một phương thức khác là changeValue() sẽ cố gắng thay đổi giá trị của các biến.

public class Test {

	public static void main(String[] args) {

		Balloon red = new Balloon("Red"); // memory reference = 50
		Balloon blue = new Balloon("Blue"); // memory reference = 100
		
		swap(red, blue);
		System.out.println("After the swap method executes:");
		System.out.println("`red` color value = " + red.getColor());
		System.out.println("`blue` color value = " + blue.getColor());
		
		changeValue(blue);
		System.out.println("After the changeValue method executes:");
		System.out.println("`blue` color value = " + blue.getColor());
		
	}

	// Generic swap method
	public static void swap(Object o1, Object o2){
		Object temp = o1;
		o1 = o2;
		o2 = temp;
	}

	private static void changeValue(Balloon balloon) { // balloon = 100
		balloon.setColor("Red"); // balloon = 100
		balloon = new Balloon("Green"); // balloon = 200
		balloon.setColor("Blue"); // balloon = 200
	}

}

Khi ta thực thi chương trình ví dụ, ta nhận được output sau:

After the swap method executes:
'red' color value = Red
'blue' color value = Blue
After the changeValue method executes:
'blue' color value = Red

Output cho thấy phương thức swap() đã không thực sự hoán đổi các đối tượng gốc. Việc này thể hiện qua việc giá trị màu của chúng không đổi. Điều này giúp chứng minh rằng Java là pass by value vì phương thức này chỉ hoạt động trên các bản sao của giá trị tham chiếu đối tượng ban đầu.

Cách kiểm tra này có thể được áp dụng với bất kỳ ngôn ngữ lập trình nào để xác định xem ngôn ngữ đó là pass by value hay pass by reference.

Giải thích phương thức hoán đổi swap()

Khi ta sử dụng toán tử new để tạo một instance của một class, đối tượng đó sẽ được tạo ra và hai biến sau sẽ chứa địa chỉ vị trí trong bộ nhớ nơi đối tượng được lưu trữ.

Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");

Dưới đây là giải thích cụ thể về những gì xảy ra khi phương thức hoán đổi swap() được gọi:

  • Giả sử biến red đang trỏ đến đối tượng Balloon tại vị trí bộ nhớ 50 và biến blue đang trỏ đến đối tượng Balloon khác tại vị trí bộ nhớ 100.
  • Khi class gọi phương thức swap() với các biến redblue làm đối số, hai biến tham số mới o1o2 được tạo ra. Chúng trỏ đến vị trí bộ nhớ 50 và 100.
  • Đoạn code sau gải thích những gì xảy ra trong swap():
public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100
	Object temp = o1; // assign the object reference value of o1 to temp: temp = 50, o1 = 50, o2 = 100
	o1 = o2; // assign the object reference value of o2 to o1: temp = 50, o1 = 100, o2 = 100
	o2 = temp; // assign the object reference value of temp to o2: temp = 50, o1 = 100, o2 = 50
} // method terminated
  • Các giá trị trong o1o2 được hoán đổi. Tuy nhiên, o1o2 chứa các giá trị là địa chỉ trong bộ nhớ của redblue. Do đó, giá trị của các biến redblue không bị ảnh hưởng gì.

Vì các biến chứa tham chiếu đến các đối tượng, nhiều người thường lầm tưởng rằng ta đang truyền tham chiếu và Java là pass by reference. Tuy nhiên, thực tế là ta đang truyền một giá trị. Giá trị này là một bản sao của tham chiếu, và do đó Java là pass by value.

Giải thích phương thức changeValue()

Phương thức tiếp theo trong chương trình changeValue() thay đổi thuộc tính color của các đối tượng được tham chiếu bởi biến blue:

private static void changeValue(Balloon balloon) { // balloon = 100
	balloon.setColor("Red"); // balloon = 100
	balloon = new Balloon("Green"); // balloon = 200
	balloon.setColor("Blue"); // balloon = 200
}

Đây là giải thích từng bước về những gì xảy ra bên trong phương thức changeValue():

  • Phương thức changeValue() được gọi trên biến blue, vốn đang tham chiếu đến vùng nhớ 100. Dòng đầu tiên tạo ra một tham chiếu cũng trỏ đến vùng nhớ 100. Thuộc tính color của đối tượng tại vùng nhớ 100 được đổi thành “Red”.
  • Dòng thứ hai tạo một đối tượng mới (với thuộc tính color là “Green”) nằm ở vùng nhớ 200. Mọi phương thức tiếp theo được thực thi trên biến balloon sẽ tác động lên đối tượng tại vùng nhớ 200 và không ảnh hưởng đến đối tượng tại vùng nhớ 100. Biến balloon mới này ghi đè lên tham chiếu được tạo ở dòng 1, và tham chiếu balloon từ dòng 1 sẽ không còn có thể truy cập được bên trong phương thức này nữa.
  • Dòng thứ ba thay đổi thuộc tính color của đối tượng Balloon mới tại vùng nhớ 200 thành “Blue”, nhưng không ảnh hưởng đến đối tượng ban đầu được blue tham chiếu tại vùng nhớ 100. Điều này giải thích tại sao dòng cuối cùng trong kết quả đầu ra của chương trình ví dụ lại in ra blue color value = Red (phản ánh sự thay đổi từ dòng 1).

Kết luận

Trong bài viết này, chúng ta đã trả lời câu hỏi Java truyền bằng giá trị hay tham chiếu, tìm hiểu lý do tại sao Java là pass by value. Hãy tham khảo những bài viết khác của chúng tôi để tìm hiểu thêm về những khía cạnh khác của ngôn ngữ này.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.