Xin chào tất cả các bạn!
Biến (variable) là một khái niệm cực kỳ quen thuộc với một developer, và đi kèm với nó chính là các kiểu dữ liệu. Ở bài trước, tớ đã cho các bạn thấy cách phân loại các kiểu dữ liệu trong Java. Và ở bài này, tớ sẽ cho các bạn thấy rõ hơn sự khác nhau giữa chúng qua các ví dụ cực kỳ chi tiết và hi vọng là dễ hiểu…
Let’s go!
1. Kiểu:
- Primitive Data Type (kiểu dữ liệu cơ sở): bao gồm các kiểu dữ liệu byte, short, int, long, float, double, boolean, char.
- Reference Data Type (kiểu dữ liệu tham chiếu): bao gồm các kiểu dữ liệu còn lại.
2. Lưu trữ:
- Primitive Data Type: Biến được lưu tại vùng nhớ stack, giá trị là các kiểu dữ liệu cơ sở.
- Reference Data Type: Biến được lưu tại vùng nhớ stack, giá trị là địa chỉ của một đối tượng được lưu tại vùng nhớ heap.
⇒ Khi thực hiện việc gán giá trị, so sánh bằng toán tử ==, truyền tham số vào phương thức hay lấy dữ liệu trả về từ hàm thì giá trị của biến được truyền vào.
- với biến là kiểu dữ liệu cơ sở giá trị của nó chính là giá trị mà đã được truyền cho nó
- với biến kiểu dữ liệu tham chiếu, giá trị của nó là địa chỉ của một đối tượng nào đó, hoặc là null.
Để hiểu rõ hơn, chúng ta cùng đi qua các ví dụ bên dưới nào!!!
3. Gán giá trị:
Khi thực hiện phép gán, giá trị của biến sẽ được copy đến biến mới.
- Primitive Data Type:
Ví dụ:
int a = 10;
int b = a;
Sau khi thực thi 2 câu lệnh này,
b
sẽ có giá trị là 10
. Xem hình minh họa:int a = 10; a được gán giá trị là 10.
int b = a; b
được gán giá trị của a
(10
).- Reference Data Type:
Ví dụ:
String a = new String("Java");
String b = a;
Sau khi thực hiện 2 câu lệnh này, biến tham chiếu
b
sẽ có giá trị là địa chỉ của đối tượng "Java"
. Xem hình minh họa:String a = new String("Java");
Biến tham chiếu a
có giá trị là địa chỉ của đối tượng "Java"
. (ở đây là 50000
).String b = a;
Giá trị 50000
của biến tham chiếu a
được copy sang biến tham chiếu b
⇒ cả a
và b
đều tham chiếu đến cùng một đối tượng "Java"
.4. So sánh bằng toán tử ==
:
Khi so sánh bằng toán tử
==
, giá trị của biến sẽ được so sánh.- Primitive Data Type:
Ví dụ:
int a = 10;
int b = 10;
System.out.println(a == b);
Chương trình sẽ hiển thị kết quả là
true
.Mô tả các bước thực thi chương trình:
int a = 10;
a
được gán giá trị là 10
int b = 10;
b
cũng được giá trị là10
Khi so sánh
(a == b)
tương đương với so sánh (10 == 10)
nên phép toán sẽ trả vềtrue
.- Reference Data Type:
Ví dụ:
String a = new String("Java");
String b = new String("Java");
System.out.println(a == b);
Chương trình sẽ hiển thị kết quả là
false
. Why?? Cùng đi nào!!! Ở đây do chúng ta sử dụng 2 lần toán tử
new
nên chương trình sẽ tạo ra 2 đối tượng"Java"
trên vùng nhớ heap. Do đó, 2 biến tham chiếu a
và b
sẽ tham chiếu đến 2 đối tượng "Java"
khác nhau có địa chỉ lần lượt là 50000
và 50008
.String a = new String("Java"); a
có giá trị là 50000
.String b = new String("Java"); b
có giá trị là 50008
.Khi so sánh
(a == b)
tương đương với so sánh (50000 == 50008)
nên phép toán sẽ trả về false
.5. Truyền tham số:
Khi truyền tham số vào một phương thức, chương trình sẽ copy giá trị đã truyền đó vào một biến khác có phạm vi trong phương thức đó để sử dụng. Xem ví dụ để dễ hiểu hơn nhé… :v
- Primitive data type:
Ví dụ: Ta có chương trình:
public static void swap(int a, int b){
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args){
int x = 10;
int y = 20;
swap(x, y);
System.out.println(x + "-" + y)
;}
Sau khi thực thi chương trình, kết quả sẽ là
10-20
.Mô tả các bước thực thi chương trình:
Khi vào phương thức main(), chương trình sẽ tạo ra 1 stack frame (SF) và push nó vào vùng nhớ stack.
int x = 10;
int y = 20;
2 biến trên được khai báo trong phương thức main() và là biến kiểu cơ sở nên nó sẽ được cấp phát trong SF main.
swap(x, y);
Sau khi gọi phương thức
swap
, chương trình sẽ tạo ra một SF khác cho phương thức này và push nó vào vùng nhớ stack. Vì phương thức swap
có 2 đối số là a
và b
, nên khi gọi đến phương thức này nó sẽ tạo ra 2 biến a
và b
tương ứng, sau đó nó sẽ copy giá trị của biến x
và y
từ SF main vào biến a
và b
của SF swap.int temp = a;
Sau khi thực hiện câu lệnh này, chương trình sẽ tạo ra một biến temp nằm trong SF swap (vì biến temp được khai báo trong phương thức
swap
). Sau đó nó sẽ copy giá trị của biến a
sang biến temp
.a = b;
Sau khi thực hiện câu lệnh này, chương trình sẽ copy giá trị của biến
b
vào biến a
.b = temp;
tương tự, giá trị của biến
temp
sẽ được copy vào biến b
.Sau khi ra khỏi phương thức
swap
, SF swap được pop ra khỏi vùng nhớ stack, các biếna
, b
, temp
đồng thời được giải phóng.System.out.println(x + "-“ + y);
Do vậy, sau khi thực hiện câu lệnh này, kết quả vẫn là
10-20
.- Reference Data Type:
Ví dụ: Ta có chương trình:
public class MyInteger{
public int num;
public MyInteger(int num){
this.num = num;
}
}
public static void swap(MyInteger a, MyInteger b){
int temp = a.num;
a.num = b.num;
b.num = temp.num;
}
public static void main(String[] args){
MyInteger x = new MyInteger (10);
MyInteger y = new MyInteger (20);
swap(x, y);
System.out.println(x.num + "-" + y.num);
}
Sau khi thực thi chương trình, kết quả sẽ là
20-10
. Tại sao lại như vậy? Cùng xem mô tả chi tiết bên dưới nhé…Mô tả các bước thực thi chương trình:
MyInteger x = new MyInteger (10);
MyInteger y = new MyInteger (20);
Chương trình sẽ cấp phát 2 đối tượng
MyInteger
trên vùng nhớ heap và 2 ô nhớ trên vùng nhớ stack để lưu trữ địa chỉ của 2 đối tượng trên. (Giống như con trỏ trên C/C++, các biến tham chiếu x
và y
sẽ trỏ đến địa chỉ của các đối tượng chứa giá trị 10
và 20
trên vùng nhớ heap)Khi phương thức
swap
được gọi, một SF mới được push vào vùng nhớ stack. Phương thức swap
chứa các đối số a
, b
kiểu MyInteger
(kiểu tham chiếu) nên trong SF swap sẽ cấp phát 2 biến a
, b
tương ứng (kiểu tham chiếu) và sau đó sẽ copy giá trị của các biến x
và y
vào các biến a
và b
.Các biến
x
và y
tham chiếu đến đối tượng10
và 20
trên vùng nhớ heap, nên sau khi copy, các biến a
và b
cũng tham chiếu đến đối tượng 10
và 20
đó. Tại thời điểm này, đối tượng 10
sẽ được tham chiếu bởi biếnx
và a
, còn đối tượng 20
sẽ được tham chiếu bởi biến y
và b
.int temp = a.num;
Sau khi câu lệnh này thực hiện, chương trình sẽ tạo ra một biến
temp
trong SF swap (vì biến temp
được khai báo trong phương thức swap
) và copy giá trị num
của đối tượng mà biến a
đang tham chiếu vào biến temp
.Sau khi câu lệnh này thực hiện, chương trình sẽ copy giá trị
num
của đối tượng mà biến b
đang tham chiếu đến vào biến num
của đối tượng mà biến a
đang tham chiếu đến.Sau khi câu lệnh này được thực hiện, chương trình sẽ copy giá trị của biến
temp
vào biến num
của đối tượng mà biến b
đang tham chiếu đến.Sau khi ra khỏi phương thức
swap
, SF swap được pop ra khỏi vùng nhớ stack, các biếna
, b
, temp
đồng thời được giải phóng.Tại thời điểm này, biến
x
đang tham chiếu đến đối tượng có giá trị của num
là 20
và y
tham chiếu đến đối tượng có giá trị num
là10
. Do đó, kết quả hiển thị sẽ là 20-10
. Thật tuyệt đúng không nào? Ở trên là phương thức swap kinh điển đã được nhiều người dùng để ví dụ cho con trỏ trong C/C++ và bây giờ là biến tham chiếu trong Java có cơ chế tương tự như một biến con trỏ.
6. Giá trị trả về:
Tương tự như những phần trên, giá trị trả về của một phương thức chính là giá trị của biến được
return
.- Với các biến kiểu cơ sở, phương thức sẽ trả về giá trị mà biến đó đang chứa, một giá trị kiểu cơ sở.
- Với các biến kiểu tham chiếu, phương thức cũng sẽ trả về giá trị mà biến đó đang chứa, nhưng giá trị bây giờ là một địa chỉ của một đối tượng mà biến đó đang tham chiếu đến.
Bạn học Java bao lâu rồi? Và bạn đã nắm vững được những kiến thức trên chưa? Hi vọng những kiến thức cơ bản này sẽ giúp các bạn giải thích được những “hiện tượng” mà lâu nay bạn chưa biết tại sao nó lại như thế.
Nhận xét
Đăng nhận xét