THIS trong Java: Bí kíp tự gọi tên của Object (GenZ Edition)
Java – OOP

THIS trong Java: Bí kíp tự gọi tên của Object (GenZ Edition)

Author

Admin System

@root

Ngày xuất bản

19 Mar, 2026

Lượt xem

1 Lượt

this keyword

this Keyword trong Java: Khi Object Tự Chỉ Vào Chính Mình

Chào các chiến thần GenZ, Giảng viên Creyt đây! Hôm nay chúng ta sẽ cùng mổ xẻ một từ khóa nghe có vẻ đơn giản nhưng lại cực kỳ quyền năng trong Java: this. Nghe tên là thấy nó 'tự luyến' rồi đúng không? Chính xác! this trong Java, về cơ bản, là cái "gương soi" của một đối tượng, giúp nó tự nhìn thấy và tương tác với chính mình.

Imagine thế này: Bạn đang ở trong một căn phòng, và bạn muốn nói về chính bạn. Bạn sẽ nói "Tôi thích ăn phở", chứ không phải "một người nào đó thích ăn phở". Trong thế giới OOP của Java, mỗi object là một "bạn" riêng biệt, và this chính là cách nó nói "Tôi đây!" hay "chính bản thân tôi đây!". Đơn giản là một tham chiếu đến đối tượng hiện tại (current object).

Nó là "selfie stick" của mỗi object, luôn luôn hướng về chính nó.

1. this dùng để làm gì?

this không chỉ để "tự sướng" đâu nhé, nó có mấy công dụng cực kỳ quan trọng, giúp code của bạn rõ ràng, mạch lạc và "pro" hơn nhiều:

a. Phân biệt Biến Instance và Biến Local/Tham số (Disambiguation)

Đây là công dụng phổ biến nhất của this. Đôi khi, bạn có một biến instance (biến thành viên của đối tượng) và một tham số hoặc biến local trong một method hoặc constructorcùng tên. Java sẽ ưu tiên biến local/tham số. Vậy làm sao để nói "Ê, tôi muốn dùng cái biến của đối tượng này cơ, không phải cái biến cục bộ kia!"? Đó là lúc this ra tay.

Ví dụ Code Minh Họa:

Giả sử bạn có một lớp SinhVien và muốn gán tên cho sinh viên đó. Nếu tham số constructor trùng tên với biến instance, this sẽ giúp bạn giải quyết sự mơ hồ.

class SinhVien {
    String ten;
    int tuoi;

    // Constructor
    public SinhVien(String ten, int tuoi) {
        // Nếu không có 'this.', Java sẽ hiểu 'ten = ten' là gán biến local cho chính nó, không gán vào biến instance
        this.ten = ten;   // 'this.ten' là biến instance của đối tượng hiện tại
        this.tuoi = tuoi; // 'tuoi' không bị trùng tên nên không nhất thiết phải dùng 'this.tuoi', nhưng dùng thì cũng không sai và tăng tính rõ ràng
    }

    public void inThongTin() {
        System.out.println("Tên: " + this.ten + ", Tuổi: " + this.tuoi);
    }

    public void capNhatTen(String ten) {
        // Đây là một ví dụ khác về việc phân biệt biến
        if (ten != null && !ten.isEmpty()) {
            this.ten = ten; // Cập nhật biến instance 'ten' bằng tham số 'ten'
        }
    }
}

public class ViDuThis {
    public static void main(String[] args) {
        SinhVien sv1 = new SinhVien("Nguyễn Văn A", 20);
        sv1.inThongTin(); // Output: Tên: Nguyễn Văn A, Tuổi: 20

        sv1.capNhatTen("Trần Thị B");
        sv1.inThongTin(); // Output: Tên: Trần Thị B, Tuổi: 20
    }
}

Trong ví dụ trên, this.ten rõ ràng chỉ ra rằng bạn đang nói đến biến ten thuộc về đối tượng SinhVien hiện tại, chứ không phải tham số ten của phương thức.

b. Gọi Constructor Khác trong Cùng Lớp (Constructor Chaining)

Bạn có thể dùng this() (với dấu ngoặc đơn và các tham số) để gọi một constructor khác của chính lớp đó từ bên trong một constructor. Điều này cực kỳ hữu ích khi bạn muốn tái sử dụng logic khởi tạo và tránh lặp code.

Ví dụ Code Minh Họa:

Giả sử một SinhVien có thể được tạo chỉ với tên, và tuổi mặc định là 18.

class SinhVienFull {
    String ten;
    int tuoi;
    String maSinhVien;

    // Constructor 1: Đầy đủ thông tin
    public SinhVienFull(String ten, int tuoi, String maSinhVien) {
        this.ten = ten;
        this.tuoi = tuoi;
        this.maSinhVien = maSinhVien;
        System.out.println("Khởi tạo SinhVienFull với 3 tham số.");
    }

    // Constructor 2: Chỉ có tên và tuổi, mã sinh viên mặc định là "SV001"
    public SinhVienFull(String ten, int tuoi) {
        // Gọi constructor 1 với giá trị mặc định cho maSinhVien
        this(ten, tuoi, "SV001"); // LƯU Ý: 'this()' phải là câu lệnh ĐẦU TIÊN trong constructor!
        System.out.println("Khởi tạo SinhVienFull với 2 tham số.");
    }

    // Constructor 3: Chỉ có tên, tuổi mặc định 18, mã sinh viên mặc định "SV001"
    public SinhVienFull(String ten) {
        // Gọi constructor 2 với tuổi mặc định
        this(ten, 18);
        System.out.println("Khởi tạo SinhVienFull với 1 tham số.");
    }

    public void inThongTin() {
        System.out.println("Tên: " + ten + ", Tuổi: " + tuoi + ", Mã SV: " + maSinhVien);
    }
}

public class ViDuThisConstructor {
    public static void main(String[] args) {
        System.out.println("\n--- Tạo SV với 3 tham số ---");
        SinhVienFull svA = new SinhVienFull("Nguyễn C", 22, "K2023_001");
        svA.inThongTin();

        System.out.println("\n--- Tạo SV với 2 tham số ---");
        SinhVienFull svB = new SinhVienFull("Lê D", 19);
        svB.inThongTin();

        System.out.println("\n--- Tạo SV với 1 tham số ---");
        SinhVienFull svC = new SinhVienFull("Phạm E");
        svC.inThongTin();
    }
}

Output sẽ cho thấy các constructor được gọi theo chuỗi, giúp bạn dễ dàng quản lý các cách khởi tạo khác nhau cho đối tượng của mình.

c. Trả về Đối tượng Hiện tại (Method Chaining)

Khi bạn muốn tạo ra các phương thức có thể gọi nối tiếp nhau (kiểu như object.doSomething().thenDoThis().finallyDoThat();), bạn cần các phương thức đó trả về chính đối tượng hiện tại. Và đoán xem ai sẽ giúp bạn làm điều đó? Chính là return this;.

Ví dụ Code Minh Họa:

class CauHinhMayTinh {
    private String cpu;
    private int ramGB;
    private String gpu;

    public CauHinhMayTinh() {
        // Default values
        this.cpu = "Intel i5";
        this.ramGB = 8;
        this.gpu = "Integrated";
    }

    public CauHinhMayTinh setCpu(String cpu) {
        this.cpu = cpu;
        return this; // Trả về chính đối tượng hiện tại
    }

    public CauHinhMayTinh setRam(int ramGB) {
        this.ramGB = ramGB;
        return this; // Trả về chính đối tượng hiện tại
    }

    public CauHinhMayTinh setGpu(String gpu) {
        this.gpu = gpu;
        return this; // Trả về chính đối tượng hiện tại
    }

    public void inCauHinh() {
        System.out.println("Cấu hình: CPU = " + cpu + ", RAM = " + ramGB + "GB, GPU = " + gpu);
    }
}

public class ViDuMethodChaining {
    public static void main(String[] args) {
        CauHinhMayTinh myPC = new CauHinhMayTinh();

        // Sử dụng method chaining nhờ 'return this;'
        myPC.setCpu("AMD Ryzen 7")
            .setRam(16)
            .setGpu("NVIDIA RTX 3060")
            .inCauHinh(); // Output: Cấu hình: CPU = AMD Ryzen 7, RAM = 16GB, GPU = NVIDIA RTX 3060

        CauHinhMayTinh workPC = new CauHinhMayTinh()
                                .setRam(32)
                                .inCauHinh(); // Output: Cấu hình: CPU = Intel i5, RAM = 32GB, GPU = Integrated
    }
}

Kiểu gọi phương thức liên tục này cực kỳ phổ biến trong các thư viện và framework hiện đại, đặc biệt là trong Builder Pattern (sẽ học sau này).

Illustration

2. Mẹo (Best Practices) để ghi nhớ và dùng thực tế

  • Khi nào dùng this.? Luôn dùng khi có sự trùng tên giữa biến instance và biến local/tham số để giải quyết sự mơ hồ. Nó giúp code của bạn rõ ràng như ban ngày.
  • Khi nào dùng this()? Chỉ dùng trong constructor để gọi một constructor khác của cùng lớp. Nhớ kỹ: nó phải là câu lệnh đầu tiên trong constructor đó, không được có bất kỳ dòng code nào khác trước nó.
  • Khi nào return this;? Khi bạn muốn xây dựng các API "fluent" (chảy mượt mà), cho phép gọi nhiều phương thức liên tiếp trên cùng một đối tượng. Rất hay dùng trong Builder Pattern hoặc các setter phương thức.
  • Có nên dùng this. mọi lúc không? Không nhất thiết! Nếu không có sự trùng tên, việc dùng this. chỉ làm code dài hơn một chút mà không tăng thêm nhiều giá trị. Tuy nhiên, một số đội/dự án có quy tắc là luôn dùng this. cho tất cả các biến instance để thống nhất và dễ nhận biết. Cái này tùy team style guide nhé.

3. Ứng dụng thực tế các website/ứng dụng đã ứng dụng

Thực ra, this được dùng khắp mọi nơi trong các ứng dụng Java, từ website dùng Spring Boot, ứng dụng di động Android, cho đến các hệ thống backend lớn. Bạn không nhìn thấy nó tường minh trên giao diện người dùng, nhưng nó là nền tảng của cách các đối tượng tương tác với dữ liệu của chính chúng.

  • Setter methods trong các POJO/JavaBeans: Hầu hết các lớp dữ liệu (như User, Product, Order) đều có các phương thức setter kiểu public void setName(String name) { this.name = name; }.
  • Builder Pattern: Đây là một design pattern cực kỳ phổ biến trong các framework như Spring, Hibernate, hay khi xây dựng các đối tượng phức tạp trong Android (ví dụ: AlertDialog.Builder). Các phương thức withX(), setY() trong builder thường return this; để cho phép chuỗi gọi.
  • Spring Framework: Khi bạn định nghĩa các @Bean trong Spring, hoặc khi bạn làm việc với các thành phần trong ngữ cảnh của chúng, this luôn ngầm định tồn tại để tham chiếu đến instance bean hiện tại.

4. Thử nghiệm đã từng và hướng dẫn nên dùng cho case nào

Creyt đã từng thấy nhiều bạn newbie quên dùng this khi có sự trùng tên, dẫn đến biến instance không được gán giá trị đúng, gây ra lỗi null hoặc dữ liệu sai. Đó là một trong những lỗi kinh điển nhất!

Khi nào nên dùng this (must-have):

  1. Phân biệt biến: Bắt buộc phải dùng this.variableName khi tham số/biến local trùng tên với biến instance. Đây là trường hợp không thể thiếu.
  2. Constructor chaining: Bắt buộc phải dùng this(...) để gọi constructor khác từ một constructor. Không có cách nào khác để làm điều này một cách trực tiếp.

Khi nào nên dùng this (nice-to-have, nhưng tăng tính rõ ràng):

  1. Method chaining: Khi bạn muốn thiết kế API của mình theo kiểu fluent, dễ đọc, dễ viết. return this; là chìa khóa.
  2. Explicitly passing current object: Đôi khi bạn cần truyền chính đối tượng hiện tại vào một phương thức của một đối tượng khác. Ví dụ: someOtherObject.register(this);.
  3. Đọc code: Một số lập trình viên thích luôn dùng this. cho tất cả các biến instance để dễ dàng phân biệt chúng với các biến local ngay lập tức, ngay cả khi không có sự trùng tên. Điều này tùy thuộc vào quy ước của dự án.

Nhớ nhé, this không phải là một từ khóa phức tạp, nó chỉ đơn giản là cách một đối tượng tự tham chiếu đến chính nó. Nắm vững nó, bạn sẽ viết code Java "mượt" hơn, "nghệ" hơn và tránh được nhiều bug không đáng có. Cứ coi nó là "cái tên" của object trong ngữ cảnh hiện tại là hiểu ngay!

Đó là tất cả về this keyword. Giờ thì bắt tay vào code và thử nghiệm ngay đi các bạn trẻ! Có gì khó cứ hỏi Creyt nhé!

Thuộc Series: Java – OOP

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!