Class variable (biến lớp) còn gọi là static variable (biến tĩnh) – được khai báo với từ khóa static bên trong class nhưng ngoài mọi method/constructor/block.
Đặc điểm chính
- Thuộc về class, không thuộc về instance (object) nào.
- Chỉ có một bản sao (single copy) được chia sẻ bởi tất cả instances của class.
- Khởi tạo khi class được load (class loading), trước khi bất kỳ object nào được tạo.
- Truy cập qua
ClassName.variableName(khuyên dùng) hoặcinstance.variableName(được nhưng warning). - Biến instance (non-static) mỗi object có bản sao riêng.
Ví dụ minh họa
public class Counter {
// Static variable - chia sẻ bởi tất cả instances
private static int instanceCount = 0;
// Instance variable - mỗi object có bản sao riêng
private int id;
public Counter() {
this.id = ++instanceCount; // Tăng counter khi tạo object mới
System.out.println("Created instance #" + id + " (total: " + instanceCount + ")");
}
public static int getInstanceCount() {
return instanceCount;
}
public int getId() { return id; }
public static void main(String[] args) {
System.out.println("Initial count: " + Counter.getInstanceCount()); // 0
Counter c1 = new Counter(); // #1
Counter c2 = new Counter(); // #2
Counter c3 = new Counter(); // #3
System.out.println("c1.id = " + c1.getId()); // 1
System.out.println("c2.id = " + c2.getId()); // 2
System.out.println("c3.id = " + c3.getId()); // 3
System.out.println("Final count: " + Counter.getInstanceCount()); // 3
// Truy cập static variable qua class name (best practice)
Counter.instanceCount = 100; // Có thể truy cập nếu không private
System.out.println("After manual set: " + Counter.getInstanceCount()); // 100
}
}
Static Variable vs Instance Variable
| Tiêu chí | Static Variable (Class Variable) | Instance Variable | |
|---|---|---|---|
| Khai báo | static type name; | type name; (không có static) | |
| Bộ nhớ | Metaspace (class metadata) / Heap (static field storage) | Heap (bên trong object) | |
| Số lượng bản sao | 1 cho toàn class | 1 cho mỗi instance | |
| Khởi tạo | Khi class load (static initializer) | Khi object tạo (constructor) | |
| Truy cập | ClassName.var hoặc obj.var | obj.var (cần instance) | |
| Thread-safety | Cần synchronization nếu mutable | Mỗi thread có object riêng → an toàn hơn | |
| Serialization | Không được serialize (transient mặc định) | Được serialize mặc định |
Static Initialization Block
public class Config {
static final String APP_NAME;
static final int MAX_CONNECTIONS;
static {
// Khởi tạo phức tạp, đọc config file, v.v.
APP_NAME = "MyApp";
MAX_CONNECTIONS = loadFromConfig();
System.out.println("Config loaded");
}
private static int loadFromConfig() { return 100; }
}
Best Practices
- Dùng
static finalcho constants (naming: UPPER_SNAKE_CASE). - Tránh mutable static state (global state) – gây khó test, race condition, memory leak.
- Nếu cần mutable shared state: dùng
AtomicInteger,ConcurrentHashMap, hoặc encapsulate trong singleton thread-safe. - Static variable của generic class:
class Box { static T item; }– KHÔNG được phép (type erasure).
Ví dụ thực tế: Singleton pattern
public class DatabaseConnection {
private static volatile DatabaseConnection instance;
private static final Object lock = new Object();
private DatabaseConnection() { /* init connection */ }
public static DatabaseConnection getInstance() {
if (instance == null) {
synchronized (lock) {
if (instance == null) instance = new DatabaseConnection();
}
}
return instance;
}
}