# Bài 9: Static Keyword trong Java

#### I. Static Methods (Phương thức tĩnh)

**Định nghĩa:** Phương thức tĩnh là phương thức được khai báo với từ khóa `static`. Phương thức này thuộc về lớp (class) chứ không phải là một đối tượng cụ thể của lớp. Phương thức tĩnh có thể được gọi mà không cần tạo một đối tượng của lớp chứa nó.

**Khi nào sử dụng:**

* Khi phương thức không cần truy cập hoặc sửa đổi trạng thái của đối tượng (các biến instance).
    
* Khi cần tạo các tiện ích (utility methods) hoặc phương thức trợ giúp mà không liên quan đến một đối tượng cụ thể.
    

**Ví dụ chi tiết:**

```java
public class MathUtils {

    // Phương thức tĩnh để tính tổng hai số nguyên
    public static int add(int a, int b) {
        return a + b;
    }

    // Phương thức tĩnh để tính hiệu hai số nguyên
    public static int subtract(int a, int b) {
        return a - b;
    }

    public static void main(String[] args) {
        // Gọi phương thức tĩnh mà không cần tạo đối tượng
        int sum = MathUtils.add(5, 10);
        int difference = MathUtils.subtract(10, 5);

        System.out.println("Sum: " + sum);           // In ra kết quả: Sum: 15
        System.out.println("Difference: " + difference); // In ra kết quả: Difference: 5
    }
}
```

**Giải thích:** Trong ví dụ trên, chúng ta có hai phương thức tĩnh `add` và `subtract` trong lớp `MathUtils`. Các phương thức này có thể được gọi trực tiếp thông qua tên lớp mà không cần phải tạo một đối tượng của lớp `MathUtils`. Điều này rất hữu ích khi bạn cần một tập hợp các phương thức tiện ích chung có thể được sử dụng bởi nhiều phần khác nhau của ứng dụng.

#### II. Static Variables (Biến tĩnh)

**Định nghĩa:** Biến tĩnh là biến được khai báo với từ khóa `static`. Biến này thuộc về lớp và được chia sẻ giữa tất cả các đối tượng của lớp. Ngược lại, biến instance là biến thuộc về một đối tượng cụ thể và mỗi đối tượng có bản sao riêng của biến đó.

**Ví dụ chi tiết:**

```java
public class Counter {
    // Biến tĩnh
    private static int count = 0;

    // Constructor tăng giá trị của biến tĩnh
    public Counter() {
        count++;
    }

    // Phương thức tĩnh để lấy giá trị của biến tĩnh
    public static int getCount() {
        return count;
    }

    public static void main(String[] args) {
        Counter c1 = new Counter();
        Counter c2 = new Counter();
        Counter c3 = new Counter();

        // Biến count chia sẻ giữa tất cả các đối tượng
        System.out.println("Number of objects created: " + Counter.getCount()); // In ra kết quả: Number of objects created: 3
    }
}
```

**Giải thích:** Trong ví dụ này, biến `count` là một biến tĩnh và được chia sẻ giữa tất cả các đối tượng của lớp `Counter`. Mỗi khi một đối tượng mới của lớp `Counter` được tạo, constructor của lớp sẽ tăng giá trị của biến `count` lên 1. Phương thức tĩnh `getCount` trả về giá trị hiện tại của biến `count`.

#### III. Static Blocks (Khối tĩnh)

**Định nghĩa:** Khối tĩnh là một khối mã được khai báo với từ khóa `static`. Khối này được thực thi chỉ một lần khi lớp được tải vào bộ nhớ. Khối tĩnh thường được sử dụng để khởi tạo các biến tĩnh hoặc thực hiện các công việc khởi tạo mà chỉ cần làm một lần.

**Ví dụ chi tiết:**

```java
public class StaticBlockExample {
    // Biến tĩnh
    private static int staticValue;

    // Khối tĩnh
    static {
        staticValue = 10;
        System.out.println("Static block executed. staticValue = " + staticValue);
    }

    public static void main(String[] args) {
        // Khối tĩnh đã được thực thi trước khi main chạy
        System.out.println("Main method executed. staticValue = " + staticValue);
    }
}
```

**Giải thích:** Trong ví dụ này, khối tĩnh được thực thi ngay khi lớp `StaticBlockExample` được tải vào bộ nhớ. Biến `staticValue` được khởi tạo với giá trị 10 và thông báo được in ra. Sau đó, khi phương thức `main` được thực thi, giá trị của `staticValue` đã được khởi tạo và sẵn sàng để sử dụng.

#### IV. Bài tập thực hành

**Bài tập:** Tạo một hệ thống quản lý đơn hàng sử dụng static methods, variables, và blocks.

**Yêu cầu:**

1. Tạo lớp `Order` với biến tĩnh `orderCount` để đếm số lượng đơn hàng.
    
2. Khởi tạo biến `orderCount` trong một khối tĩnh.
    
3. Tạo phương thức tĩnh `getOrderCount()` để lấy giá trị của biến `orderCount`.
    
4. Tạo các phương thức để thêm đơn hàng và hiển thị thông tin đơn hàng.
    
5. Viết chương trình chính để tạo các đối tượng đơn hàng và gọi các phương thức.
    

**Mã nguồn mẫu:**

```java
public class Order {
    // Biến tĩnh để đếm số lượng đơn hàng
    private static int orderCount;

    // Khối tĩnh để khởi tạo biến tĩnh
    static {
        orderCount = 0;
        System.out.println("Static block executed. orderCount initialized to " + orderCount);
    }

    // Biến instance
    private int orderId;
    private String product;
    private int quantity;

    // Constructor để tạo đơn hàng
    public Order(String product, int quantity) {
        this.orderId = ++orderCount;
        this.product = product;
        this.quantity = quantity;
    }

    // Phương thức tĩnh để lấy giá trị của biến tĩnh
    public static int getOrderCount() {
        return orderCount;
    }

    // Phương thức để hiển thị thông tin đơn hàng
    public void displayOrder() {
        System.out.println("Order ID: " + orderId);
        System.out.println("Product: " + product);
        System.out.println("Quantity: " + quantity);
    }

    public static void main(String[] args) {
        Order order1 = new Order("Laptop", 2);
        Order order2 = new Order("Smartphone", 5);

        order1.displayOrder();
        System.out.println();
        order2.displayOrder();

        // Hiển thị số lượng đơn hàng đã được tạo
        System.out.println("\nTotal orders created: " + Order.getOrderCount());
    }
}
```

**Giải thích:** Trong bài tập này, chúng ta có lớp `Order` với biến tĩnh `orderCount` để đếm số lượng đơn hàng. Biến `orderCount` được khởi tạo trong một khối tĩnh và tăng lên mỗi khi một đối tượng `Order` mới được tạo. Phương thức `getOrderCount` trả về giá trị hiện tại của biến `orderCount`, cho biết số lượng đơn hàng đã được tạo.

#### Tổng kết

Bài học này cung cấp một cái nhìn chi tiết về từ khóa `static` trong Java, bao gồm static methods, static variables, và static blocks. Chúng ta đã thấy cách sử dụng chúng và lợi ích của chúng trong việc quản lý và tối ưu hóa mã nguồn. Việc nắm vững các khái niệm này sẽ giúp bạn xây dựng các hệ thống phần mềm hiệu quả hơn và dễ bảo trì hơn.
