Từ Khóa: static (Static Keywords)
"Trong Java, từ khóa static là một công cụ quan trọng, cho phép bạn định nghĩa các thành phần có thể truy cập mà không cần tạo đối tượng. Điều này giúp tối ưu hóa bộ nhớ và làm cho chương trình trở nên hiệu quả hơn. Dưới đây là những điều cơ bản bạn cần biết về từ khóa static trong Java."
Từ khóa static trong Java được sử dụng để quản lý bộ nhớ một cách hiệu quả. Khi một thành phần được khai báo là static thì nó thuộc về lớp chứ không phải thuộc về một đối tượng cụ thể nào của lớp đó. Từ khóa static có thể được áp dụng cho:
↳ Biến static.
↳ Phương thức static.
↳ Khối lệnh static.

Từ khóa static là một công cụ mạnh mẽ trong Java, nhưng cần được sử dụng một cách hợp lý. Hiểu rõ các đặc điểm và ứng dụng của static sẽ giúp bạn viết code Java hiệu quả hơn.
Ⅰ. Biến static
Khi bạn khai báo một biến là static, thì biến đó được gọi là biến tĩnh, hay biến static.
Đặc điểm của biến static:
↳ Thuộc về lớp, chứ không thuộc về đối tượng nào.
↳ Có một bản sao duy nhất cho toàn bộ lớp, bất kể có bao nhiêu đối tượng được tạo ra.
↳ Được khởi tạo khi lớp được tải vào bộ nhớ.
Cách sử dụng biến static:
↳ Để lưu trữ các thông tin chung cho tất cả các đối tượng của lớp, ví dụ như số lượng đối tượng đã được tạo, các hằng số chung, tên công ty, tên trường học...
↳ Truy cập trực tiếp thông qua tên lớp mà không cần tạo đối tượng.
Ví dụ 1:
Hãy tưởng tượng một công ty tên là ABC Corp có nhiều nhân viên. Tất cả nhân viên đều làm việc cho cùng một công ty, vì vậy tên công ty của họ giống nhau. Trong trường hợp này, tên công ty có thể là biến static trong lớp Employee. Dưới đây là một ví dụ cụ thể để bạn hiểu rõ hơn:
Không sử dụng biến static
Ví dụ: Employee.java
public class Employee {
String companyName = "ABC Corp";
int id;
String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public void display() {
System.out.println(id +". "+ name + " Làm việc tại " + companyName);
}
public static void main(String[] args) {
Employee employee1 = new Employee("Vương");
Employee employee2 = new Employee("Trường");
employee1.display();
employee2.display();
}
}
Kết quả của chương trình là:
2. Trường Làm việc tại ABC Corp
Trong ví dụ này, mỗi đối tượng Employee có một bản sao riêng của biến companyName. Điều này không hiệu quả về bộ nhớ vì companyName là thuộc tính chung của tất cả các đối tượng.
Sử dụng biến static
Ví dụ: Employee.java
public class Employee {
static String companyName = "ABC Corp";
int id;
String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public void display() {
System.out.println(id +". "+ name + " Làm việc tại " + companyName);
}
public static void main(String[] args) {
Employee employee1 = new Employee("Vương");
Employee employee2 = new Employee("Trường");
employee1.display();
employee2.display();
}
}
Kết quả của chương trình là:
2. Trường Làm việc tại ABC Corp
Trong ví dụ này, biến companyName được khai báo là static, do đó chỉ có một bản sao duy nhất của biến này được chia sẻ giữa tất cả các đối tượng Employee, giúp tiết kiệm bộ nhớ.

Ví dụ 2:
↳ Trong ví dụ này, biến static được dùng để đếm số lượng đối tượng được tạo từ một lớp, so sánh với cách không sử dụng biến static.
Không sử dụng biến static
Trong ví dụ này, mỗi đối tượng sẽ có biến count riêng của nó, do đó, biến đếm không hoạt động chính xác.
Ví dụ: ECounter.java
public class Counter {
int count = 0; // Biến đếm không static
public Counter() {
count++;
System.out.println("Biến đếm số lượng không dùng static: " + count);
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();
}
}
Kết quả của chương trình là:
Biến đếm số lượng không dùng static: 1
Biến đếm số lượng không dùng static: 1
Trong ví dụ này, mỗi đối tượng Counter có biến count riêng, nên giá trị của count không được chia sẻ giữa các đối tượng.
Sử dụng biến static
Trong ví dụ này, biến count được khai báo là static, do đó, nó được chia sẻ giữa tất cả các đối tượng và đếm chính xác số lượng đối tượng được tạo ra.
Ví dụ: Counter.java
public class Counter {
static int count = 0; // Biến đếm dùng static
public Counter() {
count++;
System.out.println("Biến đếm số lượng dùng static: " + count);
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();
}
}
Kết quả của chương trình là:
Biến đếm số lượng dùng static: 2
Biến đếm số lượng dùng static: 3
Trong ví dụ này, biến count được chia sẻ giữa tất cả các đối tượng Counter, do đó, nó đếm chính xác số lượng đối tượng được tạo ra.
Bảng so sánh chi tiết giữa biến static và biến thể hiện (instance variable) trong Java.
Đặc điểm | Biến static (Biến lớp) | Biến thể hiện (Biến instance) |
---|---|---|
Thuộc về | Lớp | Đối tượng (instance) của lớp |
Bộ nhớ | Vùng nhớ chung của lớp | Vùng nhớ riêng của mỗi đối tượng |
Số lượng bản sao | Chỉ có một bản sao cho toàn bộ lớp | Mỗi đối tượng có một bản sao riêng biệt |
Cách truy cập | Truy cập trực tiếp qua tên lớp | Truy cập qua đối tượng của lớp |
Vòng đời | Được tạo khi lớp được load và tồn tại cho đến khi chương trình kết thúc | Được tạo khi đối tượng được khởi tạo và bị hủy khi đối tượng bị thu hồi bộ nhớ |
Sử dụng | Để lưu trữ thông tin chung cho tất cả các đối tượng của lớp, các hằng số, các phương thức tiện ích | Để lưu trữ dữ liệu riêng của từng đối tượng |
Ví dụ | Số lượng đối tượng đã được tạo, giá trị Pi, tên chung… | Tên của một người, tuổi, địa chỉ |
Ⅱ. Phương thức static.
Nếu bạn áp dụng từ khóa static với bất cứ phương thức nào, thì phương thức đó được gọi là phương thức static.
Đặc điểm của phương thức static:
↳ Phương thức static thuộc về lớp và có thể được gọi mà không cần tạo đối tượng của lớp đó.
↳ Phương thức static thường được sử dụng trong các lớp tiện ích hoặc để thực hiện các tác vụ không liên quan đến các biến thể hiện (biến instance).
↳ Phương thức static có thể truy cập các biến static khác và gọi các phương thức static khác trong cùng một lớp.
Cách sử dụng phương thức static:
↳ Để thực hiện các tác vụ liên quan đến lớp chứ không phải đối tượng cụ thể, ví dụ như các phương thức tiện ích (utility methods).
↳ Phương thức main luôn là một phương thức static.
Ví dụ 1: Phương thức static trong một lớp tiện ích.
Phương thức static thường được sử dụng trong các lớp tiện ích (utility classes) nơi mà các phương thức không cần đến trạng thái của đối tượng.
Ví dụ: Math.java
public class Math {
// Phương thức static để tính tổng hai số
public static int add(int a, int b) {
return a + b;
}
// Phương thức static để tính hiệu hai số
public static int subtract(int a, int b) {
return a - b;
}
// Phương thức static để tính tích hai số
public static int multiply(int a, int b) {
return a * b;
}
public static void main(String[] args) {
// Gọi các phương thức static mà không cần tạo đối tượng
int tong = Math.add(10, 5);
int hieu = Math.subtract(10, 5);
int nhan = Math.multiply(10, 5);
// In kết quả ra màn hình
System.out.println("Tổng hai số: " + tong);
System.out.println("Hiệu hai số: " + hieu);
System.out.println("Nhân hai số: " + nhan);
}
}
Kết quả của chương trình là:
Hiệu hai số: 5
Nhân hai số: 50
Trong ví dụ này, các phương thức add, subtract và multiply là các phương thức static. Chúng có thể được gọi trực tiếp bằng tên lớp Math mà không cần tạo đối tượng của lớp này.
Ví dụ 2: Phương thức static trong một lớp thông thường.
Phương thức static cũng có thể được sử dụng trong một lớp thông thường để thực hiện các tác vụ không liên quan đến các biến thể hiện (instance variables):
Ví dụ: Counter.java
public class Counter {
private static int count = 0;
// Phương thức static để tăng giá trị của biến count
public static void increment() {
count++;
}
// Phương thức static để lấy giá trị hiện tại của biến count
public static int getCount() {
return count;
}
public static void main(String[] args) {
// Gọi các phương thức static mà không cần tạo đối tượng
Counter.increment();
Counter.increment();
Counter.increment();
// In giá trị của biến count ra màn hình
System.out.println("Count: " + Counter.getCount());
}
}
Kết quả của chương trình là:
Hiệu hai số: 5
Nhân hai số: 50
Trong ví dụ này, phương thức increment và getCount là các phương thức static. Chúng có thể được gọi trực tiếp bằng tên lớp Counter mà không cần tạo đối tượng của lớp này. Biến count là biến static và được chia sẻ giữa tất cả các đối tượng của lớp Counter.
Các hạn chế chính của phương thức static
1. Không thể truy cập trực tiếp biến instance:
↳ Phương thức static không thể truy cập trực tiếp các biến instance (biến không phải static) của lớp. Điều này là do phương thức static không liên kết với bất kỳ đối tượng cụ thể nào, trong khi biến instance lại thuộc về một đối tượng nhất định.
2. Không thể gọi trực tiếp phương thức instance:
↳ Tương tự như biến instance, phương thức static cũng không thể gọi trực tiếp các phương thức instance. Lý do là phương thức static không có ngữ cảnh của một đối tượng.
3. Không thể sử dụng từ khóa this và super:
↳ Từ khóa this đại diện cho đối tượng hiện tại, còn super dùng để gọi đến phương thức của lớp cha. Do phương thức static không liên quan đến bất kỳ đối tượng cụ thể nào, nên không thể sử dụng hai từ khóa này trong phương thức static.
4. Không thể ghi đè (override):
↳ Phương thức static không thể bị ghi đè bởi các lớp con. Điều này là do phương thức static thuộc về lớp chứ không thuộc về đối tượng, và việc ghi đè chỉ áp dụng cho các phương thức instance.
Ví dụ minh họa các hạn chế của phương thức static:
Ví dụ: Animal.java
class Animal {
public static void sound() {
System.out.println("Âm thanh của động vật");
}
}
class Dog extends Animal {
@Override
public static void sound() {
System.out.println("Tiếng chó sủa");
}
}
public class Main {
public static void main(String[] args) {
// Gọi phương thức static bằng tên lớp
Dog.sound();
}
}
Kết quả của chương trình là:
So sánh chi tiết giữa phương thức static và phương thức không static (instance method) trong Java:
Đặc điểm | Phương thức static | Phương thức không static (instance method) |
---|---|---|
Thuộc về | Lớp | Đối tượng (instance) của lớp |
Cách gọi | Gọi trực tiếp qua tên lớp | Gọi thông qua đối tượng của lớp |
Truy cập | Có thể truy cập biến static và phương thức static khác | Có thể truy cập cả biến static, biến instance và phương thức static, phương thức instance |
Từ khóa this và super | Không thể sử dụng | Có thể sử dụng |
Ghi đè | Không thể ghi đè | Có thể ghi đè |
Sử dụng | Các phương thức tiện ích, hằng số, điểm vào của chương trình (main ) | Các hành động liên quan đến trạng thái của đối tượng |
Ⅲ. Khối lệnh static.
Khối lệnh static được sử dụng để khởi tạo dữ liệu tĩnh. Nó được thực thi trước phương thức main tại lúc tải lớp.
Ví dụ: Example.java
public class Example {
public static int number;
static {
number = 42;
System.out.println("Xin chào, Java");
System.out.println("Khối lệnh Static được thực thi");
}
public static void main(String[] args) {
System.out.println("\nXin chào, Main");
System.out.println("Giá trị của number: " + Example.number);
}
}
Kết quả của chương trình là:
Khối lệnh Static được thực thi
Xin chào, Main
Giá trị của number: 42
Câu hỏi: Tại sao phương thức main trong Java lại là static?
Câu trả lời ngắn gọn: Phương thức main trong Java được khai báo là static để JVM (Java Virtual Machine) có thể gọi trực tiếp nó mà không cần phải tạo ra một đối tượng nào của lớp chứa phương thức main.
Giải thích chi tiết:
↳ JVM và điểm khởi đầu: Khi bạn chạy một chương trình Java, JVM sẽ tìm đến phương thức main() để bắt đầu thực thi.
↳ Không cần tạo đối tượng: Để đơn giản hóa quá trình khởi động chương trình, JVM không cần phải tạo ra một đối tượng của lớp chứa phương thức main. Việc khai báo main là static cho phép JVM gọi trực tiếp phương thức này mà không cần qua các bước tạo đối tượng phức tạp.
↳ Tính độc lập: Phương thức static thuộc về lớp chứ không thuộc về bất kỳ đối tượng nào của lớp đó. Điều này có nghĩa là phương thức main có thể được gọi ngay cả khi chưa có bất kỳ đối tượng nào của lớp được tạo ra.
↳ Tính tiện lợi: Việc khai báo main là static giúp cho việc viết và chạy các chương trình Java trở nên đơn giản và trực quan hơn.
Ví dụ: Example.java
public class Example {
public static void main(String[] args) {
System.out.println("Xin chào, thế giới!");
}
}
Trong ví dụ trên, khi bạn chạy chương trình này, JVM sẽ tìm đến lớp Example và gọi trực tiếp phương thức main() mà không cần tạo ra một đối tượng nào của lớp Example.
Các câu hỏi liên quan bạn có thể quan tâm:
Câu hỏi: Tại sao phương thức main phải là public?
↳ Trả lời: Để JVM có thể truy cập được phương thức main từ bất kỳ lớp nào.
Câu hỏi: Tại sao phương thức main phải là void?
↳ Trả lời: Vì phương thức main không cần trả về bất kỳ giá trị nào.
Câu hỏi: Có thể có nhiều phương thức main trong một lớp không?
↳ Trả lời: Không, một lớp chỉ có thể có một phương thức main.
Câu hỏi: Phương thức main có thể được override không?
↳ Trả lời: Không, phương thức static không thể bị override.
So sánh khối static và phương thức main trong Java nhé.
Đặc điểm | Khối static | Phương thức main |
---|---|---|
Mục đích | Khởi tạo biến static, công việc chuẩn bị | Điểm bắt đầu của chương trình |
Thời điểm thực thi | Khi lớp được load | Khi chương trình được chạy |
Tham số | Không có | Mảng String[] (đối số dòng lệnh) |
Giá trị trả về | Không | void (không có) |
Có thể gọi trực tiếp | Không | Có (JVM gọi) |