Điều khoản throws
là một phần của chữ ký của phương thức và để ghi đè phương thức, phương thức ghi đè phải có chữ ký giống như phương pháp ghi đè.
Do đó, nếu lớp B
mở rộng lớp A
và A
định nghĩa:
public void foo (int param) throws SomeException
{
....
if (something)
throw new SomeException();
....
}
Sau đó B
chỉ có thể ghi đè lên foo bằng cách sử dụng chữ ký giống nhau:
public void foo (int param) throws SomeException
{
super.foo(param);
....
if (something)
throw new SomeOtherException();
....
}
SomeOtherException
phải là một sub-class của SomeException
, vì đó là loại ngoại lệ mà chữ ký phương thức cho phép ném. Nếu phương pháp ghi đè sẽ cố gắng loại trừ một loại ngoại lệ là loại siêu hạng SomeException
, nó sẽ vi phạm hợp đồng của phương thức.
Hãy khai báo một số hệ thống phân cấp lớp của các lớp ngoại lệ:
SuperException
SomeException
SomeOtherException
AnotherSomeException
gì bạn đề xuất (Java allows parent class method to have checked exception which is child to the child class method checked exception
) sẽ cho phép các phương pháp trọng trong lớp trẻ để ném bất kỳ trường hợp ngoại lệ của loại SuperException
, mà sẽ cho phép nó để ném AnotherSomeException
. Điều này vi phạm chữ ký của phương thức, vì AnotherSomeException
không phải là loại phụ của SomeException
.
Để mở rộng nhận xét của tôi, hãy xem xét điều gì sẽ xảy ra nếu Java cho phép những gì bạn đề xuất.
Giả sử lớp C
có phương thức bar
chấp nhận một thể hiện của lớp A
và gọi phương thức foo
.
public class C
{
....
public void bar (A a)
{
try {
a.foo();
}
catch (SomeException ex) {
....
}
}
}
Kể từ foo
được khai báo để ném SomeException
, bất kỳ mã mà các cuộc gọi foo
phải xử lý ngoại lệ này hoặc tuyên bố rằng nó có thể ném ngoại lệ này. Bây giờ, nếu Java cho phép B
ghi đè foo
, nhưng thay đổi tuyên bố thành public void foo() throws Exception
, việc triển khai foo
trong B
có thể hủy bất kỳ lớp con nào là Exception
. Kể từ khi bar
thậm chí không biết rằng B
tồn tại, nó không biết nó có để bắt bất kỳ ngoại lệ khác hơn SomeException
và các lớp con của nó. Do đó trình biên dịch không thể đánh dấu mã này là một lỗi, nhưng nếu người gọi bar
sẽ chuyển cho nó một trường hợp B
, mã sẽ trở thành không hợp lệ chỉ trong thời gian chạy, vì nó có thể ném một bài kiểm tra không bị bắt hoặc khai báo bởi bar
. Đó là lý do tại sao Java không cho phép bạn thay đổi mệnh đề throws
khi bạn ghi đè phương thức.
Giải thích lý do tại sao * điều gì * không được phép? Bạn có thể thêm một số mã để minh họa không? –
@OliverCharlesworth Tôi nghĩ rằng vấn đề của anh ta là một phương thức overriden không thể có mệnh đề 'throws' nếu phương thức cha mẹ không ném cùng một ngoại lệ (hoặc một tổng quát hơn). – Tom
@Tom Có, vì ngoại lệ đã kiểm tra là một phần của hợp đồng của lớp học và, theo Nguyên tắc thay thế của Liskov, các lớp con phải tuân theo hợp đồng. Ngoài ra, tôi không hiểu một từ nào trong phần thứ hai của câu hỏi của OP. – Powerslave