Hãy luôn nhớ rằng, Java chỉ sử dụng truyền tham trị. Khi bạn truyền tham số vào hàm trong Java, tùy thuộc vào kiểu dữ liệu của tham số (kiểu nguyên thủy hay kiểu không nguyên thủy), việc tương tác với vùng nhớ stack và heap sẽ khác nhau.
Xét đoạn mã sau đây:
public class Main {
public static void setX(int y){
y = 2;
}
public static void main(String args[]){
int x = 1;
System.out.println(x); // -> 1
setX(x);
System.out.println(x); // -> 1
}
}Trong ví dụ này:
- Biến
xđược khai báo và khởi tạo giá trị là1trong phương thứcmain(). xlà biến địa phương của phương thứcmain()được lưu trữ trên vùng nhớ stack của phương thứcmain().- Khi gọi phương thức
setX(x), giá trị củaxđược sao chép vào một biến mới tên làycủa phương thứcsetX(). - Trong phương thức
setX(), biếnyđược thay đổi giá trị thành2. Tuy nhiên, sự thay đổi này chỉ ảnh hưởng đếny, biến địa phương trongsetX(), và không ảnh hưởng gì đếnxở trongmain()vìylà một bản sao riêng biệt củax. - Do đó, khi in ra giá trị của
xsau khi gọisetX(), kết quả vẫn là1như giá trị ban đầu.
Xét tiếp đoạn mã sau:
public class Main {
public static void setX(int x) {
x = 2;
}
public static void main(String args[]) {
int x = 1;
System.out.println(x); // -> 1
setX(x);
System.out.println(x); // -> 1
}
}Mặc dù phương thức setX() sử dụng tham số tên là x (giống như tên biến x trong phương thức main()) nhưng nó vẫn là biến địa phương của phương thức setX(). Việc đặt tên tham số trong phương thức setX() là x hoặc y (hoặc bất kỳ tên nào khác) không ảnh hưởng đến cơ chế truyền tham trị của Java, nhưng nó có thể ảnh hưởng đến tính rõ ràng và dễ đọc của mã. Việc chọn tên tham số có thể làm tăng hoặc giảm sự rõ ràng của mã, đặc biệt là trong việc hiểu rằng các biến trong các phương thức khác nhau là độc lập với nhau.
-
Khi dùng cùng tên
x: Trong ví dụ gần nhất, cả biến địa phương trongmain()và tham số củasetX()đều được đặt tên làx. Điều này có thể gây ra nhầm lẫn khi đọc và hiểu mã, vì có vẻ như cùng một biếnxđang được sử dụng trong cả hai phương thức, mặc dù thực tế chúng là hai biến hoàn toàn độc lập. -
Khi dùng tên khác nhau (
y): Trong ví dụ trước đó, biến trongmain()làxvà tham số trongsetX()lày. Sự khác biệt trong đặt tên này giúp làm rõ rằng biếnytrongsetX()chỉ là một bản sao của giá trị củaxvà là một biến hoàn toàn độc lập. Điều này làm giảm khả năng gây nhầm lẫn về việc liệu thay đổiycó ảnh hưởng đếnxhay không.
Xét đoạn mã sau đây:
public class Main {
int x;
Main(int y) {
x = y;
}
static void changeX(int x) {
x = 10;
}
static void changeX(Main object) {
object.x = 10;
}
void changeX() {
this.x = 20;
}
public static void main(String[] args) {
Main obj = new Main(5);
changeX(obj.x);
System.out.println(obj.x); // -> 5
changeX(obj);
System.out.println(obj.x); // -> 10, thực sự bị thay đổi
obj.changeX();
System.out.println(obj.x); // -> 20, thực sự bị thay đổi
}
}-
Phương thức
changeX(int x):- Gọi phương thức:
changeX(obj.x): Trong phương thức này,xlà một tham số kiểu nguyên thủy. Khi phương thức này được gọi, giá trị củaobj.x(là5) được truyền vào phương thức. Trong stack của thread, một khung mới (stack frame) được tạo cho lời gọichangeX(int), và giá trị5được sao chép vào biến địa phươngxcủa khung này. - Thực thi: Giá trị của biến địa phương
xtrong phương thức được thay đổi thành10, nhưng điều này không ảnh hưởng đến biếnxcủa đối tượngobjtrongmain, vì chỉ bản sao của giá trị được thay đổi. - Kết quả:
System.out.println(obj.x); // -> 5- Giá trị củaxtrong đối tượngobjkhông thay đổi vì chỉ giá trị sao chép trong stack của phương thứcchangeX(int)được thay đổi.
- Gọi phương thức:
-
Phương thức
changeX(Main obj):- Gọi phương thức:
changeX(object): Ở đây, tham chiếu đến đối tượngMainđược truyền vào. Trong stack, một khung mới được tạo chochangeX(Main), và tham chiếu tớiobjđược sao chép vào biến địa phương. - Thực thi: Tham chiếu này trỏ đến cùng một đối tượng trên heap như tham chiếu ban đầu trong
main. Do đó, khi thuộc tínhxcủa đối tượng được thay đổi thành10trong phương thức, nó thực sự thay đổi đối tượng trên heap. - Kết quả:
System.out.println(obj.x); // -> 10- Giá trị củaxtrong đối tượngobjđược cập nhật thành10do sự thay đổi trực tiếp trên đối tượng trên heap.
- Gọi phương thức:
Chi tiết như sau:
- Phương thức
changeX()của lớpMain:- Gọi phương thức:
obj.changeX(): Phương thức này là một phương thức phi tĩnh của lớpMain, do đó nó cần một thực thể của lớp để gọi. - Thực thi: Trong phương thức này,
this.x = 20; đề cập đến biếnxcủa đối tượngobjthông qua từ khóathis, chỉ thị rằng thay đổi nên áp dụng cho đối tượng mà phương thức được gọi từ. - Kết quả:
System.out.println(obj.x); // -> 20- Giá trị củaxđược thay đổi thành20trên cùng một đối tượngobjtrên heap.
- Gọi phương thức:

