0

Phân biệt Throwable, Exception và Error trong lập trình: Hiểu đúng bản chất để bắt lỗi chuẩn xác

Chào anh em!

Trong quá trình viết code lập trình hướng đối tượng (như Java, PHP,...), việc xử lý ngoại lệ (try...catch) là công việc diễn ra hàng ngày. Tuy nhiên, khi nhìn vào sơ đồ phân cấp lỗi, chắc hẳn không ít lần anh em tự hỏi: Throwable khác gì với Exception? Tại sao có những lúc ta bắt được Exception, nhưng có những thảm họa hệ thống lại phải dùng đến Error hay Throwable?

Hôm nay, hãy cùng mổ xẻ tường tận hệ thống phân cấp lỗi để hiểu rõ bản chất và biết cách áp dụng chúng vào thực tế dự án nhé!

1. Sơ đồ gia phả: Ai là "trùm cuối"?

Đầu tiên, hãy nhìn vào bức tranh toàn cảnh của hệ thống xử lý lỗi. Tất cả các loại lỗi và ngoại lệ trong hệ thống đều phải tuân theo một nguyên tắc thừa kế xoay quanh nhân vật quyền lực nhất:

Throwable (Trùm cuối - Mọi thứ có thể ném ra)
├── 1. Error (Thảm họa hệ thống - Không nên bắt)
└── 2. Exception (Ngoại lệ ứng dụng - Cần xử lý)
    ├── Checked Exception (Lỗi kiểm tra tại biên dịch)
    └── Unchecked Exception / RuntimeException (Lỗi khi đang chạy)

Hiểu một cách ngắn gọn: Throwable là lớp cha tối cao, còn Exception chỉ là một người con nằm bên trong nhánh cấp dưới của nó.

2. Mổ xẻ chi tiết từng thành phần

A. Throwable – Cấp độ cao nhất của sự cố

  • Bản chất: Throwable là lớp gốc (base class) cho tất cả các đối tượng có thể được ném ra (throw) hoặc bắt lại (catch) trong môi trường thực thi.
  • Phạm vi: Bất cứ thứ gì có khả năng làm gián đoạn luồng chạy bình thường của chương trình (dù là lỗi phần cứng, lỗi code, hay ngoại lệ nghiệp vụ) đều kế thừa từ Throwable.
  • Lời khuyên: Trong code thông thường, tuyệt đối không nên viết lệnh catch (Throwable $e) chung chung trừ khi bạn đang viết các lớp Framework xử lý lỗi toàn cục (Global Exception Handler) để ghi log hệ thống ở tầng ngoài cùng.

B. Exception – Ngoại lệ của ứng dụng (Thứ chúng ta hay xử lý)

Nằm ngay dưới ThrowableException. Đây là lớp đại diện cho những sự cố mà ứng dụng của bạn hoàn toàn có thể dự đoán và xử lý được bằng logic code. Exception được chia làm hai nhánh chính:

  • Checked Exceptions (Lỗi biên dịch): Các lỗi mà lập trình viên bắt buộc phải xử lý bằng try...catch ngay từ lúc viết code (ví dụ: lỗi đọc file không tồn tại, lỗi kết nối mạng). Nếu không bắt, trình biên dịch sẽ từ chối chạy.
  • Unchecked Exceptions / RuntimeExceptions (Lỗi khi chạy): Các lỗi phát sinh do sơ suất trong logic lập trình (ví dụ: chia cho 0, gọi hàm trên một đối tượng null - NullPointerException).

3. Đặt lên bàn cân so sánh trực diện

Để anh em dễ hình dung sự khác biệt mấu chốt giữa hai khái niệm này, hãy xem bảng đối chiếu nhanh:

Tiêu chí Throwable Exception
Vị trí trong cây thừa kế Là lớp cha cấp cao nhất (Root). Là lớp con nằm dưới Throwable.
Bao gồm những gì? Chứa cả Exception lẫn Error (lỗi phần cứng/hệ thống). Chỉ chứa các ngoại lệ liên quan đến logic ứng dụng.
Ứng dụng thực tế trong try...catch Dùng ở tầng Global Handler tối cao để hứng toàn bộ sự cố không lường trước. Dùng thường xuyên trong business logic để bắt lỗi cụ thể (như sai mật khẩu, hết hàng trong kho).

4. Còn Error là gì mà đứng chung mâm với Exception?

Bên cạnh Exception, nhánh còn lại của Throwable chính là Error (ví dụ: OutOfMemoryError, StackOverflowError).

  • Đặc điểm: Đây là các thảm họa chí mạng từ phía máy chủ hoặc môi trường thực thi (như tràn bộ nhớ RAM, sập nhân hệ thống).
  • Quy tắc vàng: Lập trình viên không bao giờ dùng try...catch để bắt các đối tượng thuộc tầng Error, vì khi hệ thống đã tràn RAM hoặc sập phần cứng, việc cố gắng bắt lỗi và chạy tiếp là vô nghĩa; ứng dụng cần phải được dừng lại an toàn để DevOps can thiệp.

Lời kết

ThrowableException không phải là đối thủ của nhau, mà chúng nằm trong một mối quan hệ cha - con chặt chẽ. Hiểu rõ cấu trúc phân cấp này giúp bạn viết ra các khối lệnh try...catch chính xác, bắt đúng bệnh, xử lý đúng chỗ và giữ cho hệ thống Backend luôn bền bỉ, ổn định trước mọi tình huống!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí