Hiểu về khởi tạo lớp trong Java: Các tình huống quan trọng và ví dụ minh họa

0 0 0

Người đăng: Gung Typical

Theo Viblo Asia

Việc khởi tạo lớp (class initialization) trong Java có thể là một chủ đề phức tạp, nhưng hiểu rõ khi nào và cách các lớp được khởi tạo là điều cần thiết để làm chủ ngôn ngữ Java. Theo Đặc tả Máy Ảo Java (Java Virtual Machine Specification) – Chương 5.5 về Khởi tạo, có chính xác 6 tình huống khiến một lớp phải được khởi tạo ngay lập tức:

Các tình huống kích hoạt việc khởi tạo lớp

1. Gặp phải các câu lệnh bytecode sau:

  • new (tạo một thể hiện đối tượng)
  • getstatic (đọc một trường tĩnh không được đánh dấu final)
  • putstatic (gán giá trị cho một trường tĩnh không được đánh dấu final)
  • invokestatic (gọi một phương thức tĩnh)

2. Sử dụng các phương thức phản chiếu (reflection) từ gói java.lang.reflect.

3. Khi lớp cha (superclass) chưa được khởi tạo.

4. Khi JVM bắt đầu thực thi và một lớp chính (main class) được chỉ định.

5. Khi sử dụng hỗ trợ ngôn ngữ động trong Java 7+ và MethodHandle được phân giải đến một trong các dạng sau:

  • REF_getStatic
  • REF_putStatic
  • REF_invokeStatic
  • REF_newInvokeSpecial

6. Một interface định nghĩa phương thức mặc định (default method), và lớp triển khai interface đó được khởi tạo đồng thời.

Các tình huống khởi tạo lớp với ví dụ

1. Lớp con tham chiếu đến lớp cha

Việc tham chiếu đến một trường tĩnh của lớp cha thông qua lớp con không khởi tạo lớp con:

class Super { static { System.out.println("Super"); } public static int value = 1;
} class Sub extends Super { static { System.out.println("Sub"); }
} public class Main { public static void main(String[] args) { System.out.println(Sub.value); }
}

Kết quả:

Super
1

Giải thích:

  • Chỉ lớp Super được khởi tạo vì trường value thuộc về nó. Việc truy cập Sub.value chỉ kích hoạt khởi tạo lớp cha Super.

2. Tạo mảng không kích hoạt khởi tạo lớp

Việc tạo một mảng của một lớp không dẫn đến khởi tạo lớp đó:

public class Main { public static void main(String[] args) { Sub[] array = new Sub[5]; }
}

Kết quả:

  • Không có đầu ra, tức là lớp Sub không được khởi tạo.

Giải thích:

  • Tham chiếu mảng không làm kích hoạt việc khởi tạo lớp. JVM chỉ tạo một lớp đặc biệt với tên là "[Lcom.example.demo.Sub" để biểu diễn mảng một chiều, nhưng không khởi tạo bản thân lớp Sub.

3. Tham Chiếu Hằng Số Trong Constant Pool

Nếu một hằng số được khai báo là final, nó sẽ được chèn trực tiếp vào constant pool của lớp gọi tại thời điểm biên dịch, do đó tránh việc khởi tạo lớp chứa hằng:

class Super { static { System.out.println("Super"); } public static final String HELLO = "Hello";
} public class Main { public static void main(String[] args) { System.out.println(Super.HELLO); }
}

Kết quả:

Hello

Giải thích:

  • Vì hằng số HELLO được biên dịch và chèn trực tiếp vào lớp Main, nên lớp Super không bị khởi tạo.

4. Quy tắc khởi tạo Interface

Khác với lớp, interface không khởi tạo tất cả interface cha cùng lúc. Chúng chỉ được khởi tạo khi thật sự cần thiết. Ngoài ra, interface không thể có các khối static block, nhưng có thể có phương thức khởi tạo tĩnh ẩn (phương thức <clinit>) để khởi tạo các biến.

Kết luận

Hiểu rõ các tình huống cụ thể trong quá trình khởi tạo lớp giúp bạn kiểm soát hành vi khởi tạo trong Java, từ đó tối ưu hóa thời gian khởi động ứng dụng và tránh những hành vi không mong đợi. Việc nắm bắt những kiến thức này đặc biệt quan trọng khi xây dựng các hệ thống lớn hoặc tối ưu hiệu suất khởi chạy.

Cảm ơn các bạn đã theo dõi!

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 313

- vừa được xem lúc

Học Spring Boot bắt đầu từ đâu?

1. Giới thiệu Spring Boot. 1.1.

0 0 288

- vừa được xem lúc

Cần chuẩn bị gì để bắt đầu học Java

Cần chuẩn bị những gì để bắt đầu lập trình Java. 1.1. Cài JDK hay JRE.

0 0 58

- vừa được xem lúc

Sử dụng ModelMapper trong Spring Boot

Bài hôm nay sẽ là cách sử dụng thư viện ModelMapper để mapping qua lại giữa các object trong Spring nhé. Trang chủ của ModelMapper đây http://modelmapper.org/, đọc rất dễ hiểu dành cho các bạn muốn tìm hiểu sâu hơn. 1.

0 0 199

- vừa được xem lúc

[Java] 1 vài tip nhỏ khi sử dụng String hoặc Collection part 1

. Hello các bạn, hôm nay mình sẽ chia sẻ về mẹo check String null hay full space một cách tiện lợi. Mình sẽ sử dụng thư viện Lớp StringUtils download file jar để import vào thư viện tại (link).

0 0 78

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 150