Truyền Exception Cho Caller
Truyền Ngoại Lệ là khi một phương thức ném ra một ngoại lệ và không xử lý nó, ngoại lệ đó sẽ được truyền lên các phương thức gọi đến cho đến khi được xử lý hoặc cho đến khi nó chạm đến đáy của call stack. Nếu không được xử lý, chương trình sẽ kết thúc với lỗi.
Call Stack là khi bạn gọi một phương thức trong Java, nó được thêm vào call stack. Call stack là một cấu trúc dữ liệu theo dạng ngăn xếp (stack) dùng để theo dõi các phương thức đang hoạt động. Khi một phương thức gọi phương thức khác, phương thức gọi được thêm vào trên cùng của stack.
Quy tắc truyền ngoại lệ
↳ Ngoại lệ được kiểm tra (checked exceptions): Phải được khai báo trong chữ ký của phương thức bằng từ khóa throws. Nếu không, trình biên dịch sẽ báo lỗi.
↳ Ngoại lệ không được kiểm tra (unchecked exceptions): Không cần phải khai báo trong chữ ký của phương thức.
Các trường hợp truyền ngoại lệ:
1. Truyền ngoại lệ Checked exception
Checked exception là các ngoại lệ cần phải được khai báo hoặc xử lý trong mã nguồn. Chúng bao gồm các lớp con của Exception nhưng không phải là RuntimeException, ví dụ như IOException, SQLException, v.v.
Ví dụ: Example.java
import java.io.IOException;
class Parent {
void readFile() throws IOException {
throw new IOException("File not found"); // Gây ra IOException
}
}
class Child extends Parent {
void callReadFile() throws IOException {
readFile(); // Phải khai báo ngoại lệ IOException
}
}
public class Example {
public static void main(String[] args) {
try {
Child child = new Child();
child.callReadFile(); // Gọi phương thức có thể gây ra ngoại lệ
} catch (IOException e) {
System.out.println("Ngoại lệ được xử lý: " + e.getMessage());
}
System.out.println("Chương trình tiếp tục...");
}
}
Kết quả của chương trình là:
Chương trình tiếp tục...
Giải thích:
↳ readFile() trong lớp Parent ném ra IOException, một ngoại lệ checked.
↳ callReadFile() trong lớp Child cũng khai báo rằng nó ném ra IOException.
↳ Trong phương thức main, khi gọi callReadFile(), ngoại lệ IOException được truyền từ callReadFile() đến main, nơi nó được xử lý trong khối catch.
2. Truyền ngoại lệ Unchecked exception (RuntimeException)
Uncheck exception là các ngoại lệ không cần phải khai báo hoặc xử lý trong mã nguồn. Chúng bao gồm các lớp con của RuntimeException, ví dụ như ArithmeticException, NullPointerException, v.v.
Ví dụ: Example.java
class Parent {
void riskyMethod() {
int result = 10 / 0; // Gây ra ArithmeticException
}
}
class Child extends Parent {
void callRiskyMethod() {
riskyMethod(); // Không xử lý ngoại lệ
}
}
public class Example {
public static void main(String[] args) {
try {
Child child = new Child();
child.callRiskyMethod(); // Gọi phương thức có thể gây ra ngoại lệ
} catch (ArithmeticException e) {
System.out.println("Ngoại lệ được xử lý: " + e.getMessage());
}
System.out.println("Chương trình tiếp tục...");
}
}
Kết quả của chương trình là:
Chương trình tiếp tục...
Giải thích:
↳ riskyMethod() trong lớp Parent gây ra ArithmeticException, một ngoại lệ unchecked.
↳ callRiskyMethod() trong lớp Child gọi riskyMethod() mà không xử lý ngoại lệ.
↳ Trong phương thức main, khi gọi callRiskyMethod(), ngoại lệ ArithmeticException được truyền lên từ callRiskyMethod() đến main, nơi nó được xử lý trong khối catch.

Trong ví dụ về ngoại lệ trên xảy ra trong phương thức riskyMethod() nơi nó không được xử lý, do đó nó được truyền đến phương thức callRiskyMethod() nhưng nó không được xử lý, một lần nữa nó được truyền đến phương thức main() trong đó ngoại lệ được xử lý.
Ngoại lệ có thể được xử lý trong bất kỳ phương thức nào trong call stack hoặc trong phương thức main(), phương thức riskyMethod(), phương thức callRiskyMethod().