Câu trả lời:
Nói chung RuntimeExceptions là các ngoại lệ có thể được ngăn chặn bằng lập trình. Ví dụ NullPointerException
, ArrayIndexOutOfBoundException
. Nếu bạn kiểm tra null
trước khi gọi bất kỳ phương thức nào, NullPointerException
sẽ không bao giờ xảy ra. Tương tự ArrayIndexOutOfBoundException
sẽ không bao giờ xảy ra nếu bạn kiểm tra chỉ số đầu tiên. RuntimeException
không được kiểm tra bởi trình biên dịch, vì vậy nó là mã sạch.
EDIT : Ngày nay mọi người ủng hộ RuntimeException
vì mã sạch mà nó tạo ra. Nó hoàn toàn là một lựa chọn cá nhân.
RuntimeException
là vì nó đơn giản và không cần phải suy nghĩ về sự khác biệt giữa các ngoại lệ được kiểm tra và không được kiểm tra. Tôi nghĩ rằng bắt các ngoại lệ trong thời gian chạy là một ý tưởng tồi tệ bởi vì bạn sẽ bắt được các ngoại lệ không thể phục hồi như NullPointerException
.
Trong Java, có hai loại ngoại lệ: ngoại lệ được kiểm tra và ngoại lệ không được kiểm tra. Một ngoại lệ được kiểm tra phải được xử lý rõ ràng bằng mã, trong khi đó, một ngoại lệ không được kiểm tra không cần phải được xử lý rõ ràng.
Đối với các ngoại lệ được kiểm tra, bạn phải đặt một khối thử / bắt xung quanh mã có khả năng ném ngoại lệ hoặc thêm mệnh đề "ném" vào phương thức, để chỉ ra rằng phương thức có thể ném loại ngoại lệ này (phải là xử lý trong lớp gọi trở lên).
Bất kỳ ngoại lệ nào xuất phát từ "Ngoại lệ" là một ngoại lệ được kiểm tra, trong khi một lớp xuất phát từ RuntimeException không được kiểm tra. RuntimeExceptions không cần phải được xử lý rõ ràng bằng mã gọi.
Trước khi nhìn vào sự khác biệt giữa java.lang.RuntimeException
và java.lang.Exception
các lớp, bạn phải biết Exception
thứ bậc. Cả hai Exception
và Error
các lớp đều có nguồn gốc từ lớp Throwable
(xuất phát từ lớp Object
). Và lớp học RuntimeException
có nguồn gốc từ lớp Exception
.
Tất cả các ngoại lệ được bắt nguồn từ Exception
hoặc RuntimeException
.
Tất cả các ngoại lệ xuất phát từ RuntimeException
được gọi là ngoại lệ không được kiểm tra . Và tất cả các ngoại lệ khác được kiểm tra ngoại lệ. Một ngoại lệ được kiểm tra phải được bắt gặp ở đâu đó trong mã của bạn, nếu không, nó sẽ không biên dịch. Đó là lý do tại sao chúng được gọi là ngoại lệ được kiểm tra. Mặt khác, với các ngoại lệ không được kiểm soát, phương thức gọi không có nghĩa vụ phải xử lý hoặc khai báo nó.
Do đó, tất cả các trường hợp ngoại lệ mà trình biên dịch buộc bạn phải xử lý đều có nguồn gốc trực tiếp java.lang.Exception
và tất cả các trường hợp khác mà trình biên dịch không buộc bạn phải xử lý đều bắt nguồn từ đó java.lang.RuntimeException
.
Sau đây là một số lớp con trực tiếp được biết đến của RuntimeException .
AnnotationTypeMismatchException,
ArithmeticException,
ArrayStoreException,
BufferOverflowException,
BufferUnderflowException,
CannotRedoException,
CannotUndoException,
ClassCastException,
CMMException,
ConcurrentModificationException,
DataBindingException,
DOMException,
EmptyStackException,
EnumConstantNotPresentException,
EventException,
IllegalArgumentException,
IllegalMonitorStateException,
IllegalPathStateException,
IllegalStateException,
ImagingOpException,
IncompleteAnnotationException,
IndexOutOfBoundsException,
JMRuntimeException,
LSException,
MalformedParameterizedTypeException,
MirroredTypeException,
MirroredTypesException,
MissingResourceException,
NegativeArraySizeException,
NoSuchElementException,
NoSuchMechanismException,
NullPointerException,
ProfileDataException,
ProviderException,
RasterFormatException,
RejectedExecutionException,
SecurityException,
SystemException,
TypeConstraintException,
TypeNotPresentException,
UndeclaredThrowableException,
UnknownAnnotationValueException,
UnknownElementException,
UnknownTypeException,
UnmodifiableSetException,
UnsupportedOperationException,
WebServiceException
Một ngoại lệ được kiểm tra và RuntimeException không được chọn.
Đã kiểm tra có nghĩa là trình biên dịch yêu cầu bạn xử lý ngoại lệ trong một lần bắt hoặc khai báo phương thức của bạn là ném nó (hoặc một trong các siêu lớp của nó).
Nói chung, ném ngoại lệ được kiểm tra nếu người gọi API dự kiến sẽ xử lý ngoại lệ đó và ngoại lệ không được kiểm tra nếu đó là điều mà người gọi thường không thể xử lý, chẳng hạn như lỗi với một trong các tham số, tức là lập trình sai lầm.
Các lớp ngoại lệ thời gian chạy (RuntimeException và các lớp con của nó) được miễn kiểm tra thời gian biên dịch, vì trình biên dịch không thể thiết lập rằng các ngoại lệ thời gian chạy có thể xảy ra. (từ JLS).
Trong các lớp mà bạn thiết kế, bạn nên phân lớp Ngoại lệ và ném các thể hiện của nó để báo hiệu bất kỳ kịch bản đặc biệt nào. Làm như vậy bạn sẽ báo hiệu rõ ràng cho khách hàng của lớp rằng việc sử dụng lớp của bạn có thể tạo ra ngoại lệ và họ phải thực hiện các bước để xử lý các tình huống đặc biệt đó.
Đoạn mã dưới đây giải thích điểm này:
//Create your own exception class subclassing from Exception
class MyException extends Exception {
public MyException(final String message) {
super(message);
}
}
public class Process {
public void execute() {
throw new RuntimeException("Runtime");
}
public void process() throws MyException {
throw new MyException("Checked");
}
}
Trong định nghĩa lớp trên của lớp Process , phương thức execute
có thể đưa ra RuntimeException nhưng khai báo phương thức không cần xác định rằng nó ném RuntimeException .
Phương thức process
đưa ra một ngoại lệ được kiểm tra và nó sẽ tuyên bố rằng nó sẽ ném một ngoại lệ được kiểm tra thuộc loại MyException và không làm như vậy sẽ là một lỗi biên dịch.
Định nghĩa lớp trên cũng sẽ ảnh hưởng đến mã sử dụng lớp Process .
Cuộc gọi new Process().execute()
là một lời gọi hợp lệ trong đó khi cuộc gọi của biểu mẫu
new Process().process()
đưa ra lỗi biên dịch. Điều này là do mã máy khách nên thực hiện các bước để xử lý MyException
(có thể đặt lệnh gọi để xử lý () trong một khối thử / bắt).
Sử dụng RuntimeException đúng cách?
Từ các trường hợp ngoại lệ không được kiểm tra - Cuộc tranh cãi :
Nếu một khách hàng có thể được mong đợi phục hồi một cách hợp lý từ một ngoại lệ, hãy biến nó thành một ngoại lệ được kiểm tra. Nếu một khách hàng không thể làm bất cứ điều gì để phục hồi từ ngoại lệ, hãy biến nó thành một ngoại lệ không được kiểm soát.
Lưu ý rằng một ngoại lệ không được kiểm tra là một ngoại lệ bắt nguồn từ RuntimeException
và một ngoại lệ được kiểm tra là một ngoại lệ bắt nguồn từ đó Exception
.
Tại sao lại ném RuntimeException
nếu khách hàng không thể làm gì để phục hồi ngoại lệ? Bài viết giải thích:
Các ngoại lệ thời gian chạy thể hiện các vấn đề là kết quả của một vấn đề lập trình và do đó, mã máy khách API có thể được mong đợi một cách hợp lý để phục hồi từ chúng hoặc xử lý chúng theo bất kỳ cách nào. Những vấn đề như vậy bao gồm các ngoại lệ số học, chẳng hạn như chia cho số 0; ngoại lệ con trỏ, chẳng hạn như cố gắng truy cập một đối tượng thông qua tham chiếu null; và ngoại lệ lập chỉ mục, chẳng hạn như cố gắng truy cập một phần tử mảng thông qua một chỉ mục quá lớn hoặc quá nhỏ.
Từ tài liệu orory:
Đây là hướng dẫn quan trọng: Nếu một khách hàng có thể được mong đợi phục hồi một cách hợp lý từ một ngoại lệ, hãy biến nó thành một ngoại lệ được kiểm tra. Nếu một khách hàng không thể làm bất cứ điều gì để phục hồi từ ngoại lệ, hãy biến nó thành một ngoại lệ không được kiểm soát.
Các ngoại lệ thời gian chạy thể hiện các vấn đề là kết quả của một vấn đề lập trình và do đó, mã máy khách API có thể được mong đợi một cách hợp lý để phục hồi từ chúng hoặc xử lý chúng theo bất kỳ cách nào.
RuntimeExceptions giống như các trường hợp "ngoại lệ do sử dụng api không hợp lệ" của runtimeexceptions: IllegalStateException, NegativeArraySizeException, NullpulumException
Với Ngoại lệ, bạn phải nắm bắt rõ ràng vì bạn vẫn có thể làm gì đó để khôi phục. Ví dụ về các trường hợp ngoại lệ là: IOException, TimeoutException, PrintException ...
Nói một cách đơn giản, nếu khách hàng / người dùng của bạn có thể khôi phục từ Ngoại lệ thì hãy biến nó thành Ngoại lệ được kiểm tra , nếu khách hàng của bạn không thể làm gì để khôi phục từ Ngoại lệ thì hãy bỏ chọn RuntimeException . Ví dụ, RuntimeException sẽ là một lỗi lập trình, như chia cho số 0, không người dùng nào có thể làm bất cứ điều gì ngoài bản thân người lập trình, thì đó là RuntimeException .
RuntimeException là một lớp con của lớp Exception
Đây là một trong nhiều lớp con của lớp Exception. RuntimeException là siêu lớp của những ngoại lệ có thể được ném trong quá trình hoạt động bình thường của Máy ảo Java. Một phương thức không bắt buộc phải khai báo trong mệnh đề ném của nó bất kỳ lớp con nào của RuntimeException có thể bị ném trong quá trình thực thi phương thức nhưng không bị bắt.
Các chữ tượng hình là
java.lang.Object
--- java.lang.Throwable
------- java.lang.Exception
------------- java.lang.R.78Exception
Ngoại lệ là một cách tốt để xử lý các sự kiện bất ngờ trong luồng ứng dụng của bạn. RuntimeException không được kiểm tra bởi Trình biên dịch nhưng bạn có thể thích sử dụng Ngoại lệ mở rộng Lớp ngoại lệ để kiểm soát hành vi của các máy khách api của bạn vì chúng bắt buộc phải bắt lỗi để chúng biên dịch. Cũng hình thành tài liệu tốt.
Nếu muốn đạt được giao diện sạch, hãy sử dụng tính kế thừa để phân lớp các loại ngoại lệ khác nhau mà ứng dụng của bạn có và sau đó phơi bày ngoại lệ cha.
Có hai loại ngoại lệ, Bạn có thể khôi phục từ ngoại lệ được kiểm tra nếu bạn nhận được loại ngoại lệ đó. Ngoại lệ thời gian chạy là không thể phục hồi, ngoại lệ thời gian chạy là lỗi lập trình và lập trình viên nên xử lý nó trong khi viết mã và tiếp tục thực hiện điều này có thể cho bạn kết quả không chính xác. Ngoại lệ thời gian chạy là về vi phạm điều kiện tiên quyết. bạn có một mảng có kích thước 10 và bạn đang cố truy cập vào phần tử thứ 11, nó sẽ ném ArrayIndexOutOfBoundException
Ngoại lệ do người dùng định nghĩa có thể được kiểm tra Ngoại lệ hoặc Ngoại lệ không được kiểm tra, Nó phụ thuộc vào lớp mà nó được mở rộng.
Ngoại lệ do người dùng định nghĩa có thể là Ngoại lệ được kiểm tra tùy chỉnh, nếu nó được mở rộng sang lớp Ngoại lệ
Ngoại lệ do người dùng định nghĩa có thể là Ngoại lệ không được kiểm tra tùy chỉnh, nếu nó đang mở rộng sang lớp Ngoại lệ thời gian chạy.
Xác định một lớp và biến nó thành một đứa trẻ để Ngoại lệ hoặc Chạy thời gian Ngoại lệ