Có 2 loại ngoại lệ khác nhau trong Java: Đã chọn và Bỏ chọn. Có một cuộc tranh luận lớn về cái nào tốt hơn để sử dụng, cả hai lý lẽ đều tốt.
Về cơ bản, ngoại lệ được kiểm tra bắt nguồn từ java.lang.Exception
và yêu cầu rằng nếu bạn không chỉ định phương thức của mình là "ném MyCheckedException" thì bạn phải nắm bắt và xử lý ngoại lệ trong phương thức của mình.
// throw the exception
void foo() throws MyCheckedException
{
throw new MyCheckedException();
}
// or handle the exception
void foo()
{
try {
throw new MyCheckedException();
} catch (MyRuntimeException e) {
e.printStackTrace();
}
}
Ngoại lệ không được kiểm tra, bắt nguồn từ java.lang.RuntimeException
, không yêu cầu bạn chỉ định "ném" trong định nghĩa phương pháp của bạn cũng như bạn không xử lý.
void foo()
{
throw new MyUncheckedException();
}
Lợi thế của Kiểm tra là trình biên dịch sẽ cảnh báo bạn khi bạn chưa xử lý ngoại lệ.
Điểm bất lợi là bạn phải khai báo khối try/catch hoặc ném cho mỗi ngoại lệ được kiểm tra, và mã mức cao có thể khá cồng kềnh, cố xử lý tất cả các loại ngoại lệ khác nhau.
Vì lý do này, nếu bạn cẩn thận, bạn có thể thích sử dụng Ngoại lệ không được kiểm soát.
BTW, bạn chỉ có thể chọn loại ngoại lệ khi bạn xác định loại của riêng mình.
Khi gặp ngoại lệ từ Java hoặc thư viện của bên thứ ba, bạn phải quyết định cách xử lý nó. ví dụ. Nếu phương thức của bên thứ ba ném CheckedException1, thì bạn phải xử lý nó hoặc khai báo phương thức gọi là "ném CheckedException1". Nếu bạn muốn tránh sử dụng các trường hợp ngoại lệ được kiểm tra thì bạn có thể bọc nó trong một ngoại lệ không được kiểm tra và ném nó.
void foo() // no throws declaration
{
try {
thirdPartyObj.thirdPartyMethod(); // this throws CheckedException1
}
catch (CheckedException1 e) {
throw new MyUncheckedException(e); // this will wrap the checked in an unchecked.
}
}
Lưu ý rằng bạn có thể ném ngoại lệ không được kiểm soát mà không có khai báo "ném". Để truy cập vào CheckedException1 ban đầu từ trên cao hơn, bạn có thể sử dụng phương thức .getCause() của trường hợp ngoại lệ không được kiểm tra của bạn.
void caller()
{
try {
foo();
} catch (MyUncheckedException e) {
CheckedException1 ce1 = e.getCause();
ce1.printStackTrace();
}
}
... nhưng vì ngoại lệ từ foo() là không được kiểm soát, bạn không có để xử lý nó hoặc tuyên bố "ném".
Về đăng nhập, có nhiều trường phái tư duy khác nhau về vấn đề này.
- Log nó khi ngoại lệ xảy ra (thấp - mức)
- Log nó khi nó đạt đến đỉnh (cao - level)
- Log nó khi bạn có đủ thông tin để thực hiện một hành động thích hợp và/hoặc một thông điệp tường trình. (giữa cấp)
Một chính sách tốt mà tôi tìm thấy là cài đặt một trình xử lý ngoại lệ chưa được xử lý, sẽ xử lý tất cả ngoại lệ chưa được kiểm tra (không được kiểm soát). Bằng cách này, bất cứ thứ gì bị bỏ qua sẽ được ghi lại và có khả năng xử lý trước khi làm rơi hệ thống.
public class MyExceptionHandler implements UncaughtExceptionHandler
{
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
ex.printStackTrace();
}
}
// In your high-level code
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
và tất cả ngoại lệ có thể được xử lý một cách duyên dáng, nắm bắt và xử lý chúng trong mô-đun nơi bạn biết đủ về tình huống có thể khắc phục sự cố và thử lại.
Mặc dù câu trả lời này là chính xác, câu trả lời của paiego dưới đây hữu ích hơn nhiều. – Gowiem