Kiểu nguyên thuỷ và kiểu tham chiếu
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Bạn chép giỏ hàng mẫu cho khách A, rồi thêm món vào giỏ của A. Mở giỏ mẫu ra, món đó cũng có mặt. Không có dòng nào gán nhầm. Lý do: Java sao chép kiểu nguyên thuỷ và kiểu tham chiếu theo hai cách khác nhau.
Khái niệm
📑 Kiểu nguyên thuỷ (primitive type): kiểu mà biến chứa trực tiếp giá trị, gán sang biến khác là chép cả giá trị.
🔗 Kiểu tham chiếu (reference type): kiểu mà biến chỉ chứa tham chiếu tới object, gán sang biến khác là chép tham chiếu, và hai biến cùng trỏ tới một object.
| Loại | Gồm những kiểu |
|---|---|
| Kiểu nguyên thuỷ | int, long, double, boolean (viết thường) |
| Kiểu tham chiếu | mọi class, String, array, List, Map, Integer |
Ví dụ
// Main.java
void main() {
int a = 5;
int b = a;
b = 10;
System.out.println(a); // 5
var p1 = new Product(5000);
var p2 = p1;
p2.setPrice(9000);
System.out.println(p1.getPrice()); // 9000
}
// Product.java
class Product {
private long price;
public Product(long price) {
this.price = price;
}
public long getPrice() { return price; }
public void setPrice(long price) {
this.price = price;
}
}int b = achép số 5 sangb. Đổibkhông đụng tớia.var p2 = p1chỉ chép tham chiếu.p1vàp2cùng trỏ một object, sửa qua biến nào thì biến kia cũng thấy.- Mỗi kiểu nguyên thuỷ có một class bọc:
intcóInteger,longcóLong.ArrayListchỉ chứa object, nên phải viếtArrayList<Integer>. Stringlà kiểu tham chiếu nhưng không sửa được nội dung, nên dùng giống kiểu nguyên thuỷ mà không gặp vấn đề này.
Thử ngay
Giữ nguyên Product.java, thay nội dung Main.java bằng đoạn sau rồi chạy
java Main.java:
// Main.java
void main() {
long price = 5000;
var pen = new Product(5000);
discountNumber(price);
discountProduct(pen);
System.out.println(price);
System.out.println(pen.getPrice());
}
void discountNumber(long value) {
value = value - 1000;
}
void discountProduct(Product product) {
product.setPrice(product.getPrice() - 1000);
}Đoán trước khi chạy: hai method làm cùng một việc. Cả hai giá trị in ra có cùng bị giảm không?
Xem kết quả
5000
4000Không. Tham số long nhận bản chép của số, nên price bên ngoài giữ nguyên.
Tham số Product nhận bản chép của tham chiếu, bản chép này vẫn trỏ tới
object pen, nên sửa bên trong method thì pen đổi theo.
Lỗi hay gặp
Tưởng gán là tạo bản sao. Hai giỏ hàng thành một.
// SAI — cartA và sample là cùng một list
var sample = new ArrayList<String>();
sample.add("Bút bi");
var cartA = sample;
cartA.add("Vở");
System.out.println(sample.size()); // 2// ĐÚNG — tạo list mới, chép phần tử sang
var sample = new ArrayList<String>();
sample.add("Bút bi");
var cartA = new ArrayList<String>(sample);
cartA.add("Vở");
System.out.println(sample.size()); // 1So sánh hai object bằng ==. Với kiểu tham chiếu, == so tham chiếu chứ
không so dữ liệu.
// SAI — in false dù hai sản phẩm giống hệt nhau
var x = new Product(5000);
var y = new Product(5000);
System.out.println(x == y);// ĐÚNG — so sánh chính dữ liệu cần kiểm tra
var x = new Product(5000);
var y = new Product(5000);
System.out.println(x.getPrice() == y.getPrice());Tóm tắt
- Kiểu nguyên thuỷ chép giá trị, kiểu tham chiếu chép tham chiếu.
- Hai biến cùng trỏ một object thì sửa qua biến này, biến kia thấy ngay.
- Truyền object vào method thì method sửa được chính object đó.
- Muốn bản sao độc lập thì phải tạo object mới.
==giữa hai object so tham chiếu, không so dữ liệu. Điều này đúng cả vớiIntegervàString, nên so chúng bằngequals.
Tự kiểm tra
0/3 câuvar a = new ArrayList<Integer>(); a.add(1); var b = a; b.add(2); System.out.println(a.size()); In ra gì?
int x = 7; int y = x; x = 0; System.out.println(y); In ra gì?
Kiểu nào là kiểu nguyên thuỷ?