VieTopik
Tiếng HànTiếng Anh.NET (C#)Java
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
Java CoreClass cơ bản
Bài 12/19
5 phút

Kiểu nguyên thuỷ và kiểu tham chiếu

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 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 = a chép số 5 sang b. Đổi b không đụng tới a.
  • var p2 = p1 chỉ chép tham chiếu. p1 và p2 cù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: int có Integer, long có Long. ArrayList chỉ chứa object, nên phải viết ArrayList<Integer>.
  • String là 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.
a: 5 b: 10 p1 Product: price = 9000 p2
a và b giữ hai số riêng, p1 và p2 cùng trỏ một object

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
4000

Khô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());   // 1

So 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ới Integer và String, nên so chúng bằng equals.

Tự kiểm tra

0/3 câu
Câu 1

var a = new ArrayList<Integer>(); a.add(1); var b = a; b.add(2); System.out.println(a.size()); In ra gì?

Câu 2

int x = 7; int y = x; x = 0; System.out.println(y); In ra gì?

Câu 3

Kiểu nào là kiểu nguyên thuỷ?

Getter, setter và constructornull và Optional

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt