Static Keyword: Chìa Khóa "Độc Quyền" trong Lớp Học Object
Java – OOP

Static Keyword: Chìa Khóa "Độc Quyền" trong Lớp Học Object

Author

Admin System

@root

Ngày xuất bản

20 Mar, 2026

Lượt xem

2 Lượt

static keyword

Chào các "coder nhí" của thế kỷ 21! Hôm nay, anh Creyt sẽ "tám" với các em về một thằng cha hơi bị "lạnh lùng" nhưng lại cực kỳ quyền lực trong Java: từ khóa static. Nghe cái tên đã thấy nó đứng im, không nhúc nhích rồi đúng không? Nhưng đừng để vẻ ngoài đánh lừa, nó chính là chìa khóa để điều khiển những "tài sản chung" của cả một lớp học đấy!

1. static Keyword: "Tài Sản Chung" của Cả Lớp, Không Của Riêng Ai

Thôi, nói lý thuyết khô khan quá các em lại gật gù mất. Để anh Creyt kể chuyện này: Tưởng tượng lớp mình là một cái Class tên là HocSinh. Mỗi đứa học sinh trong lớp – thằng Tèo, con Tí, thằng Bin – là một Object (đối tượng) của cái Class HocSinh đó. Mỗi đứa có cái cặp sách riêng (biến instance), có quyền tự do đi chơi riêng (phương thức instance).

Nhưng mà, trong lớp mình có cái Bảng Đen đúng không? Hay cái Loa Thông Báo của trường? Mấy cái đó có phải của riêng thằng Tèo hay con Tí không? KHÔNG! Nó là của cả lớp, ai cũng dùng được, ai cũng thấy được, và nếu một đứa viết lên bảng thì cả lớp đều thấy. Đấy, cái Bảng Đen hay cái Loa Thông Báo chính là những thứ mang tính chất static đấy các em ạ!

Nói tóm lại, khi một thứ gì đó được gắn mác static:

  • Nó không thuộc về một đối tượng cụ thể nào (như thằng Tèo hay con Tí).
  • Nó thuộc về chính cái Class đó.
  • Chỉ có DUY NHẤT MỘT BẢN SAO của nó tồn tại trong bộ nhớ, bất kể em tạo bao nhiêu đối tượng đi chăng nữa.

2. static trong Java: Hẹn Hò Với "Tài Sản Chung" Của Class

static có thể được dùng với:

a. Biến (Variables - Fields)

Khi một biến được khai báo là static, nó trở thành biến của lớp (class variable), chứ không phải biến của đối tượng (instance variable). Tất cả các đối tượng của lớp đó đều chia sẻ cùng một bản sao của biến này. Nếu một đối tượng thay đổi giá trị của nó, giá trị đó sẽ thay đổi với tất cả các đối tượng khác.

Metaphor: Cái Bảng Đen trong lớp. Thằng Tèo viết "I love Creyt" lên bảng, cả lớp đều thấy. Con Tí xóa đi, cả lớp đều biết nó bị xóa.

b. Phương Thức (Methods)

Khi một phương thức được khai báo là static, nó trở thành phương thức của lớp (class method). Em không cần tạo một đối tượng của lớp để gọi phương thức này. Nó thường được dùng để thao tác với các biến static hoặc thực hiện các chức năng tiện ích không cần dữ liệu riêng của từng đối tượng.

Metaphor: Cái Loa Thông Báo của trường. Thầy hiệu trưởng (Class) dùng nó để thông báo cho toàn bộ học sinh (Objects), không cần phải gọi riêng từng đứa học sinh lên để thông báo.

c. Khối (Blocks)

Khối static là một khối code đặc biệt chỉ chạy DUY NHẤT MỘT LẦN khi lớp được load vào bộ nhớ lần đầu tiên. Nó thường được dùng để khởi tạo các biến static có giá trị phức tạp hoặc cần logic đặc biệt để thiết lập.

Metaphor: Lễ Khai Giảng đầu năm học. Chỉ diễn ra một lần, để chuẩn bị cho cả năm học, thiết lập mọi thứ sẵn sàng cho lớp học hoạt động.

Gợi Ý Đọc Tiếp
Public Modifier: Mở Cửa Code Của Bạn Cho Gen Z

3 Lượt xem

d. Lớp Lồng (Nested Classes)

Một lớp lồng (nested class) có thể được khai báo là static. Một static nested class không yêu cầu một thể hiện (instance) của lớp bên ngoài để được khởi tạo. Nó giống như một lớp độc lập nhưng được gói gọn về mặt logic bên trong lớp khác.

Metaphor: Một phòng học bộ môn (ví dụ: phòng Lab) nằm trong khuôn viên trường. Em có thể vào thẳng phòng Lab mà không cần phải đi qua một lớp học cụ thể nào đó trước. Nó độc lập, nhưng vẫn là một phần của tổng thể trường học.

Illustration

3. Code Ví Dụ Minh Họa: Xây Dựng "Lớp Học Mẫu"

Giờ thì chúng ta cùng "xây" một cái Class HocSinh để xem static hoạt động như thế nào nhé!

class HocSinh {
    // Biến static: Số lượng học sinh trong lớp (chung cho cả lớp)
    static int soLuongHocSinh = 0;

    // Biến instance: Tên của từng học sinh (riêng của mỗi học sinh)
    String ten;

    // Khối static: Chạy khi Class HocSinh được load vào bộ nhớ
    static {
        System.out.println("--- Lớp học đã được mở! Chuẩn bị đón học sinh ---");
    }

    // Constructor: Khởi tạo một đối tượng HocSinh mới
    public HocSinh(String ten) {
        this.ten = ten;
        soLuongHocSinh++; // Mỗi khi có học sinh mới, tăng biến static lên
        System.out.println(this.ten + " đã nhập học. Tổng số: " + soLuongHocSinh);
    }

    // Phương thức instance: Học sinh tự giới thiệu
    public void tuGioiThieu() {
        System.out.println("Chào các bạn, mình là " + this.ten + ".");
    }

    // Phương thức static: Thông báo chung của lớp
    public static void thongBaoChungCuaLop() {
        System.out.println("\n--- Thông báo từ Ban Giám Hiệu ---");
        System.out.println("Tổng số học sinh hiện tại của lớp là: " + soLuongHocSinh + " em.");
        // Lưu ý: Không thể truy cập biến 'ten' ở đây vì nó là biến instance
        // System.out.println("Tên học sinh đầu tiên: " + ten); // Lỗi biên dịch!
    }

    // Static Nested Class: Lớp Cán Bộ Lớp
    static class CanBoLop {
        String chucVu = "Lớp trưởng";
        public void thongBaoCanBo() {
            System.out.println("\n--- Cán bộ lớp thông báo ---");
            System.out.println(chucVu + " nhắc nhở các bạn đi học đầy đủ.");
        }
    }
}

public class BaiHocStatic {
    public static void main(String[] args) {
        System.out.println("Bắt đầu bài học về Static Keyword\n");

        // Gọi phương thức static mà KHÔNG CẦN tạo đối tượng
        HocSinh.thongBaoChungCuaLop(); // Kết quả: Tổng số học sinh hiện tại của lớp là: 0 em.

        // Tạo các đối tượng HocSinh
        HocSinh hs1 = new HocSinh("Tèo");
        HocSinh hs2 = new HocSinh("Tí");
        HocSinh hs3 = new HocSinh("Bin");

        // Gọi phương thức instance của từng đối tượng
        hs1.tuGioiThieu();
        hs2.tuGioiThieu();

        // Gọi lại phương thức static sau khi tạo đối tượng
        // soLuongHocSinh đã được tăng lên qua constructor của từng HocSinh
        HocSinh.thongBaoChungCuaLop(); // Kết quả: Tổng số học sinh hiện tại của lớp là: 3 em.

        // Truy cập trực tiếp biến static
        System.out.println("\nSố lượng học sinh truy cập trực tiếp: " + HocSinh.soLuongHocSinh);

        // Tạo đối tượng của Static Nested Class
        HocSinh.CanBoLop lopTruong = new HocSinh.CanBoLop();
        lopTruong.thongBaoCanBo();

        System.out.println("\nKết thúc bài học về Static Keyword");
    }
}

Output khi chạy code:

--- Lớp học đã được mở! Chuẩn bị đón học sinh ---
Bắt đầu bài học về Static Keyword

--- Thông báo từ Ban Giám Hiệu ---
Tổng số học sinh hiện tại của lớp là: 0 em.
Tèo đã nhập học. Tổng số: 1
Tí đã nhập học. Tổng số: 2
Bin đã nhập học. Tổng số: 3
Chào các bạn, mình là Tèo.
Chào các bạn, mình là Tí.

--- Thông báo từ Ban Giám Hiệu ---
Tổng số học sinh hiện tại của lớp là: 3 em.

Số lượng học sinh truy cập trực tiếp: 3

--- Cán bộ lớp thông báo ---
Lớp trưởng nhắc nhở các bạn đi học đầy đủ.

Kết thúc bài học về Static Keyword

Thấy chưa? Biến soLuongHocSinh tăng lên cho cả lớp, và phương thức thongBaoChungCuaLop() có thể được gọi mà không cần tạo đối tượng HocSinh nào cả. Quá "đỉnh của chóp"!

4. Mẹo Nhớ Nhanh và Best Practices của Giảng Viên Creyt

  • Mẹo nhớ: static = Share (chia sẻ), Single (duy nhất), Class-level (cấp độ lớp). Cứ nhớ "3 S" là thuộc bài!
  • Khi nào thì dùng static?
    • Hằng số (Constants): Khi em có một giá trị không đổi và cần được chia sẻ bởi tất cả các đối tượng (ví dụ: Math.PI trong Java). Luôn kết hợp với final để tạo static final.
    • Bộ đếm (Counters): Để đếm số lượng đối tượng đã được tạo ra (như ví dụ soLuongHocSinh của chúng ta).
    • Phương thức tiện ích (Utility methods): Các hàm không cần dữ liệu riêng của một đối tượng để hoạt động (ví dụ: Math.sqrt(), Integer.parseInt()).
    • Khởi tạo phức tạp: Dùng static block để thiết lập các biến static cần nhiều bước xử lý.
  • Cảnh báo từ Creyt:
    • static method không thể gọi non-static method hoặc truy cập non-static variable trực tiếp. Vì sao? Đơn giản là phương thức static thuộc về lớp, nó không biết đối tượng nào đang được nói đến để truy cập cái biến riêng của nó cả. Giống như cái loa thông báo của trường không thể biết thằng Tèo hôm nay ăn sáng món gì!
    • Đừng lạm dụng static! Dùng static quá nhiều có thể làm cho code khó kiểm thử, giảm tính linh hoạt và mất đi vẻ đẹp của Lập trình Hướng đối tượng (OOP). Nó tạo ra "global state" – trạng thái toàn cục, dễ dẫn đến các lỗi khó lường.

5. Ứng Dụng Thực Tế: "Static" Quanh Ta

static không phải là cái gì xa vời đâu các em, nó có mặt khắp nơi trong các ứng dụng mà các em vẫn dùng hàng ngày:

  • Thư viện tiện ích của Java:
    • Math.PIMath.random(): Hằng số và hàm toán học không cần tạo đối tượng Math.
    • System.out.println(): out là một biến static trong lớp System của Java, đại diện cho luồng output chuẩn.
    • Arrays.sort(): Phương thức static để sắp xếp mảng mà không cần tạo đối tượng Arrays.
  • Các thư viện tiện ích khác: Ví dụ như StringUtils trong Apache Commons Lang, chứa hàng loạt các phương thức static để xử lý chuỗi một cách tiện lợi.
  • Mẫu thiết kế Singleton: Một mẫu thiết kế để đảm bảo chỉ có DUY NHẤT MỘT thể hiện của một lớp tồn tại trong toàn bộ ứng dụng. Thường sử dụng static để quản lý việc tạo và truy cập thể hiện duy nhất đó (ví dụ: một lớp quản lý kết nối cơ sở dữ liệu).
  • Cấu hình ứng dụng: Các biến static final thường được dùng để lưu trữ các giá trị cấu hình chung của ứng dụng (ví dụ: DATABASE_URL, API_KEY).

6. Thử Nghiệm và Hướng Dẫn Nên Dùng Cho Case Nào

Thử nghiệm nhỏ:

Hãy thử tạo một phương thức static và trong đó, cố gắng truy cập một biến không static của lớp. Các em sẽ thấy ngay "lời nhắc nhở" từ trình biên dịch (compiler error) đấy. Đây là cách tốt nhất để hiểu rõ ranh giới giữa static và non-static.

Vậy khi nào thì "nên" dùng static?

  • Khi dữ liệu hoặc chức năng không phụ thuộc vào trạng thái cụ thể của bất kỳ đối tượng nào. Ví dụ, hàm Math.max() luôn trả về giá trị lớn hơn của hai số, nó không cần biết đối tượng Math nào đang gọi nó.
  • Khi bạn muốn một giá trị hoặc hành vi được chia sẻ và nhất quán trên tất cả các đối tượng của một lớp. Ví dụ, một hằng số COMPANY_NAME cho tất cả các nhân viên.
  • Khi bạn cần một bộ đếm toàn cục cho số lượng đối tượng đã được tạo.
  • Khi bạn tạo các lớp tiện ích (utility classes) mà chủ yếu chứa các hàm độc lập, không cần quản lý trạng thái.

Nhớ nhé, static là một công cụ mạnh mẽ, nhưng cũng giống như "siêu năng lực" vậy, phải dùng đúng lúc, đúng chỗ thì mới phát huy hiệu quả tối đa. Lạm dụng là dễ "gây họa" lắm đấy! Anh Creyt tin rằng với bài giảng này, các em đã "thấm" được cái sự "lạnh lùng" nhưng "đầy quyền năng" của static rồi chứ gì? Cứ thực hành nhiều vào, rồi mọi thứ sẽ "ngấm" thôi!

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!