Tôi thường thấy ngoại lệ được ném bởi khung công tác hoặc thư viện chẳng hạn như tham chiếu Hibernate hoặc Spring làm nguyên nhân (gây nhầm lẫn GUI GUI trong quá trình).
Tôi luôn tự hỏi tại sao họ làm điều này vì nó có vẻ như một ý tưởng tồi. Và hôm nay nó thực sự gây ra một vấn đề khi tôi đang cố gắng sắp xếp một thứ tự vào JSON: bam, chu kỳ không cần thiết.
Vì vậy, tôi nghiên cứu nó một chút nữa:
Trong mã nguồn của Throwable
(tất cả các mã nguồn được liệt kê ở đây là từ JDK 1.7), chúng tôi có điều này:
/**
* The throwable that caused this throwable to get thrown, or null if this
* throwable was not caused by another throwable, or if the causative
* throwable is unknown. If this field is equal to this throwable itself,
* it indicates that the cause of this throwable has not yet been
* initialized.
*
* @serial
* @since 1.4
*/
private Throwable cause = this;
Bây giờ tôi đặc biệt đáp ứng được vấn đề với một lớp ngoại lệ mở rộng RuntimeException
, vì vậy tôi đã đi từ đó. Một trong những nhà xây dựng của RuntimeException
:
/** Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public RuntimeException(String message) {
super(message);
}
Constructor của Exception
gọi bằng ở trên:
/**
* Constructs a new exception with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Exception(String message) {
super(message);
}
Constructor của Throwable
gọi bằng ở trên:
/**
* Constructs a new throwable with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* <p>The {@link #fillInStackTrace()} method is called to initialize
* the stack trace data in the newly created throwable.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
fillInStackTrace
là một phương pháp tự nhiên và dường như không sửa đổi trường nguyên nhân.
Như bạn có thể thấy, trừ khi phương pháp initCause
được gọi sau đó, trường cause
không bao giờ được thay đổi từ giá trị ban đầu của this
.
Kết luận: nếu bạn tạo mới Exception
(hoặc một trong nhiều nhiều lớp con tồn tại trong tự nhiên và không ghi đè hành vi này) bằng cách sử dụng hàm tạo không tham số cause
và bạn không gọi phương thức initCause
, nguyên nhân của ngoại lệ sẽ là chính nó!
Vì vậy, tôi đoán điều đó sẽ làm cho nó trở thành một sự xuất hiện rất phổ biến.
Thực hành mã hóa không đúng, nếu ngoại lệ là nguyên nhân, nó không phải xác định nguyên nhân gốc. –
Chắc chắn ... nếu bạn muốn * để tạo phụ thuộc vòng tròn mà từ đó không có lối thoát. Tôi bằng cách nào đó nghĩ rằng mã không làm những gì bạn nghĩ rằng nó đang làm. –
Thực hành không tốt, nhưng có thể xảy ra là mã bắt ngoại lệ X và ném một ngoại lệ X mới, với nguyên tắc cũ làm nguyên nhân. Vì vậy, chúng có thể trông giống nhau, nhưng thực sự khác biệt ngoại lệ. – Luciano