Java qui định kiểu tham số nào là tham trị năm 2024

Tham chiếu và tham trị trong java rất dễ gây nhầm lẫn cho các bạn mới học,kể cả các lập trình viên code lâu năm cũng đôi lúc có sự nhầm lẫn về sự phân biệt khái niệm tham chiếu và tham trị trong java.Trong bài này,tôi sẽ chia sẻ theo kinh nghiệm cũng như hiểu biết của mình để các bạn tham khảo cùng thảo luận về vấn đề trên.

Trong JAVA có 2 loại kiểu dữ liệu: cơ bản và tham chiếu : – Kiểu cơ bản : Số nguyên, số thực, kí tự , logic – Kiểu tham chiếu : Kiểu mảng, kiểu lớp đối tượng Class, kiểu Interface

Truyền tham trị là gì?

Khi các bạn truyền tham trị thì trình biên dịch sẽ tạo 1 bản sao và sau đó truyền bản sao đó vào nơi muốn truyền, vì vậy mà mọi thay đổi sẽ sảy ra trên bản sao này và ko ảnh hưởng đến biến gốc.

Truyền tham chiếu là gì?

Truyền tham chiếu thì các bạn sẽ truyền ngay địa chỉ hay gọi là chính cái biến đó vào nơi cần truyền, nên ở trong hàm mà mình truyền vào có thay đổi gì thì biến ngoài cũng thay đổi theo.


Để làm rõ hơn về vấn đề này,tôi sẽ vào một ví dụ để các bạn dễ hình dùng như sau :

1.Ví dụ về truyền kiểu dữ liệu nguyên thủy :

Class TestDemo1.java :

package demo; public class TestDemo1 { private static int number; public void showNumber(){

System.out.println(number);  
} public void changeNumber(int number){
number = 4;  
} public static void main(String[] args) {
TestDemo1 demo1 = new TestDemo1();  
demo1.number  = 10;  
demo1.changeNumber(number);  
demo1.showNumber();  
} } Khi bạn truyền tham số cho hàm trong Java, Java sẽ tạo ra một bản sao của biến và truyền vào phương thức đó. Vậy nên khi thực thi hàm chỉ có bản sao bị ảnh hưởng mà biến không hề bị ảnh hưởng.Vì lý do vậy nên khi chạy trường trình thì giá trị của biến number vẫn bằng 10.

2. Java không có kiểu truyền tham chiếu (reference)

Thường thì chúng ta sẽ nghĩ rằng Kiểu dữ liệu cơ sở được truyền theo tham trị, kiểu object được truyền theo tham chiếu. Ok.Nhưng đó là một sự nhầm lẫn.

Khi các bạn truyền một biến có kiểu object vào một hàm thì lúc đó có nghĩa ta đã truyền giá trị của biến đó để sử dụng trong hàm, chứ không phải truyền đối tượng được biến đó tham chiếu tới. Vậy nên việc thay đổi giá trị của biến có kiểu object này bằng cách gán cho một biến kiểu object khác thì object được tham chiếu đến lúc đầu không bị ảnh hưởng, chỉ khi sử dụng các method của chính các object được tham chiếu này thì dữ liệu của object mới được thay đổi sau khi ra khỏi hàm.

Các bạn hãy xem ví dụ dưới đây :

package demo; import bean.SinhVien; public class TestDemo2 { public static void main(String[] args) {

TestDemo2 demo2 = new TestDemo2();  
// tạo đối tượng sinh viên  
SinhVien sinhVien = new SinhVien("Lan Anh");  
// lấy tên trước khi gọi phương thức   
System.out.println("Trước khi gọi method change1: "+sinhVien.getName());  
demo2.change1(sinhVien);  
System.out.println("Sau khi gọi method change1 : "+sinhVien.getName());  
System.out.println("Trước khi gọi method change2: "+sinhVien.getName());  
demo2.change2(sinhVien);  
System.out.println("Sau khi gọi method change2: "+sinhVien.getName());  
} public void change1(SinhVien sinhVien){
SinhVien objSV = new SinhVien();  
sinhVien = objSV;  
} public void change2(SinhVien sinhVien){
sinhVien.setName("Phú Trần IT");  
} } Qua ví dụ này,các bạn thấy được rằng với Java không có tryền tham chiếu như thấy ở trường hợp 1 sử dụng phương thức change1,chúng ta vẫn lấy được name là “Lan Anh” .Giá trị của biến kiểu object là địa chỉ của object mà biến đó tham chiếu đến đến. Cho nên lúc này việc thay đổi giá trị của biến kiểu object này bằng cách gán cho một biến kiểu object khác thì object được tham chiếu đến lúc đầu không bị ảnh hưởng.

Khi dùng change2 thì lúc này,khi biến tham chiếu đến chúng ta đã thay đổi giá trị ở trong phương thức bằng cách setName lại mà không thông qua một đối tượng tham chiếu tạo ra mới nào,nên lúc này chỉ khi sử dụng các method của chính các object được tham chiếu này thì dữ liệu của object mới được thay đổi sau khi ra khỏi hàm.Vậy kết quả lần lượt sẽ là : “Lan Anh” , “Phú Trần IT”.

Xin chào! Tôi là Phú Trần.Kiến thức nền tảng và tư duy tốt về hướng đối tượng. Không ràng buộc ở ngôn ngữ mà căn bản ở giải thuật và tư duy con người. Lập trình JAVA/PHP.

Ví dụ bạn có 1 hàm addNumber(int num) thì khi chúng ta truyền(pass) 1 biến vào làm đối số(argument) cho hàm trên thì chương trình sẽ không dùng thẳng biến đó trong hàm mà sẽ sao chép giá trị của biến vào 1 địa chỉ khác trong bộ nhớ và dùng biến sao chép này làm việc với hàm. Vậy nên dù trong hàm có thay đổi như thế nào nhưng biến ban đầu vẫn không thay đổi.

Cùng xem qua ví dụ sau:

void addNumber(int num) {

num = num + 10;
} int main() {
int number = 10;
addNumber(number);
System.out.println(number);
}

Kết quả: 10

Vậy có nghĩa là truyền tham trị không làm thay đổi giá trị của biến truyền vào.

Truyền tham chiếu (Pass by reference)

Ngược lại với truyền tham trị thì khi bạn truyền 1 biến vào làm đối số cho hàm thì sau khi hàm được thực hiện biến đó sẽ thay đổi theo. Bởi java không có truyền tham chiếu nên ví dụ sẽ được lấy trong C++.

void addNumber(int *num) {

*num = *num + 10;
} int main() {
int number = 10;
addNumber(&number);
cout << number;
return 0;
}

Kết quả: 20

Giá trị của biến number đã thay đổi, khi truyền tham chiếu ta dùng con trỏ trỏ đến địa chỉ của biến trong bộ nhớ nên sẽ thay đổi trực tiếp biến đó, còn truyền tham trị thì ta chỉ chỉnh sửa “phân thân” của biến đó mà thôi. Cùng xem hình minh họa phía dưới để hiểu hơn:

Java qui định kiểu tham số nào là tham trị năm 2024

Định nghĩa truyền tham chiếu dễ hiểu nhất khi dùng với C++. Còn ở Java khái niệm Pointer không còn nên không còn truyền theo tham chiếu nữa, chỉ còn truyền tham trị mà thôi!

Có thể bạn thấy trong 1 số diễn đàn thảo luận hay các bài viết chẳng hạn như https://viettuts.vn/java/truyen-gia-tri-va-tham-chieu-pass-value-va-pass-reference-trong-java họ cho rằng Java vẫn có truyền tham chiếu. Theo họ thì khi truyền biến kiểu nguyên thủy(Primitive ) thì nó sẽ là truyền tham trị còn khi truyền biến kiểu tham chiếu(Reference ) thì đó là truyền tham chiếu.

Ở đây có một sự nhầm lẫn đó là biến kiểu Reference Type và Pass by Reference. Hai từ Reference này là khác nhau! Vậy khi chúng ta truyền 1 biến Reference Type vào hàm thì sao?

Khi truyền 1 biến kiểu Reference Type vào, sau khi hàm thực hiện ta thấy giá trị của biến cũng thay đổi, khá giống với truyền tham chiếu phải không nào? Nhưng cách mà Java hoạt động thì không giống với C++ đâu.

Cùng giải thích qua 1 ví dụ sau:

public class Main {

 public static void main(String[] args) {
      Foo f = new Foo("f");
      changeReference(f); // It won't change the reference!
      modifyReference(f); // It will modify the object that the reference variable "f" refers to!
 }
 public static void changeReference(Foo a) {
      Foo b = new Foo("b");
      a = b;
 }
 public static void modifyReference(Foo c) {
      c.setAttribute("c");
 }
}

Khai báo một tham chiếu có tên f thuộc loại Foo và gán cho nó một đối tượng mới của loại Foo với thuộc tính “f”.

Java qui định kiểu tham số nào là tham trị năm 2024

Từ phía phương thức, một tham chiếu kiểu Foo có tên a được khai báo và ban đầu nó được gán null.

public static void changeReference(Foo a)

Java qui định kiểu tham số nào là tham trị năm 2024

Khi bạn gọi phương thức changeReference, tham chiếu a sẽ được gán đối tượng được truyền dưới dạng đối số.

changeReference(f);

Java qui định kiểu tham số nào là tham trị năm 2024

Khai báo một tham chiếu có tên b thuộc loại Foo và gán cho nó một đối tượng mới của loại Foo với thuộc tính “b”.

Foo b = new Foo("b");

Java qui định kiểu tham số nào là tham trị năm 2024

a = b thực hiện một phép gán mới cho tham chiếu a, không phải f, a sẽ lại tham chiếu tới b

Java qui định kiểu tham số nào là tham trị năm 2024

Khi bạn gọi phương thức modifyReference(Foo c), một tham chiếu c được tạo và gán đối tượng với thuộc tính “f”.

Java qui định kiểu tham số nào là tham trị năm 2024

c.setAttribution (“c”); sẽ thay đổi thuộc tính của đối tượng tham chiếu c đến nó và và đó cũng là đối tượng mà f trỏ đến.

Java qui định kiểu tham số nào là tham trị năm 2024

Vậy khi thực hiện hàm modifyReference() ta thấy giá trị Attribute của đối tượng đã bị thay đổi nhưng thực tế ở đây hàm đã gọi đến một tham chiếu khác của đối tượng là c để thực hiện chứ không phải thực hiện trên f, nghĩa là tạo ra 1 clone khác của đối tượng. Vậy nên không thể gọi là Pass by Reference được. Hi vọng các bạn hiểu được truyền đối tượng làm đối số trong java và rõ ràng hơn trong việc truyền tham trị hay tham chiếu.

Kết luận

Có thể bạn nghĩ rằng khi đổi attribute của reference thì đối tượng thực tế cũng đổi, nó chính là Pass-by-reference, vậy Java có nó. Thật ra điều đó không quan trọng. Java có Pass-by-reference hay không? Câu này đối với dev, nó cũng vô nghĩa như câu Java có phải ngôn ngữ thuần hướng đối tượng(purely Object-Oriented Language) hay không! Vì khái niệm vẫn chỉ là khái niệm, học thuộc khái niệm không giúp bạn code tốt hơn, hãy hiểu bản chất, hiểu cú pháp hơn là tranh cãi mấy điều vô bổ.