Liệu có ý nghĩa gì khi làm thử


127

Tôi thấy một số mã như thế này:

    try
    {
        db.store(mydata);
    }
    finally
    {
        db.cleanup();
    }

Tôi nghĩ trylà phải có một catch?

Tại sao mã này làm theo cách này?


1
nó đảm bảo dọn dẹp như các phản hồi khác được đề cập, đặc biệt là đối với các tệp xử lý tệp fopenhoặc kết nối DB (cũng trong PHP)
MediaVince

Câu trả lời:


181

Điều này rất hữu ích nếu bạn muốn phương thức hiện đang thực thi vẫn ném ngoại lệ trong khi cho phép các tài nguyên được dọn sạch một cách thích hợp. Dưới đây là một ví dụ cụ thể về xử lý ngoại lệ từ phương thức gọi.

public void yourOtherMethod() {
    try {
        yourMethod();
    } catch (YourException ex) {
        // handle exception
    }
}    

public void yourMethod() throws YourException {
    try {
        db.store(mydata);
    } finally {
        db.cleanup();
    }
}

17
thường được sử dụng với các khóa như trong: lock.lock (); thử {/ * bị khóa * /} cuối cùng {lock.unlock ()}
phút

Điều gì xảy ra nếu một ngoại lệ được ném vào bên trong cuối cùng?
barth

1
@barth Khi không có catchkhối, ngoại lệ được ném vào finallysẽ được thực thi trước bất kỳ ngoại lệ nào trong trykhối. Vì vậy, nếu có hai ngoại lệ một tryvà một trong finallyngoại lệ duy nhất sẽ được ném là một ngoại lệ finally. Hành vi này không giống nhau trong PHP và Python vì cả hai ngoại lệ sẽ được đưa ra cùng một lúc trong các ngôn ngữ này và thứ tự ngoại lệ trytrước tiên là sau đó finally.
Mưa

72

Đó là bởi vì lập trình viên muốn đảm bảo rằng nó db.cleanup()được gọi ngay cả khi mã bên trong khối thử ném một ngoại lệ. Bất kỳ trường hợp ngoại lệ nào sẽ không được xử lý bởi khối đó, nhưng chúng sẽ chỉ được truyền lên trên sau khi khối cuối cùng được thực thi.


23
+1 Chính xác. Chỉ trylà ở đó để cho phép finally. Ngoại lệ không được bắt.
zockman

2
+1 để làm rõ rằng ngoại lệ tiếp tục ngăn xếp cho đến khi nó bị bắt. Cảm ơn
Code J Racer

20

Tại sao mã này làm theo cách này?

Bởi vì rõ ràng mã không biết cách xử lý các ngoại lệ ở cấp độ này. Điều đó tốt - miễn là một trong những người gọi thực hiện, tức là miễn là ngoại lệ cuối cùng được xử lý ở đâu đó.

Thông thường, mã cấp thấp không thể phản ứng thích hợp với các ngoại lệ vì người dùng cần được thông báo hoặc ngoại lệ phải được ghi lại hoặc phải thử một chiến lược khác. Mã cấp thấp thực hiện một chức năng và không biết về việc ra quyết định cấp cao hơn.

Nhưng mã vẫn cần phải dọn sạch các tài nguyên của nó (vì nếu không, chúng sẽ bị rò rỉ), do đó, nó chỉ thực hiện điều đó trong finallyđiều khoản, đảm bảo rằng nó luôn xảy ra, cho dù có ngoại lệ được ném hay không.


2

Khối cuối cùng đảm bảo rằng ngay cả khi ném RuntimeException (có thể do một số lỗi trong mã được gọi), db.cleanup()cuộc gọi sẽ được thực hiện.

Điều này cũng thường được sử dụng để ngăn chặn quá nhiều lồng:

try
{
    if (foo) return false;
    //bla ...
    return true;
}
finally
{
    //clean up
}

Đặc biệt là khi có nhiều điểm mà phương thức trả về, điều này cải thiện khả năng đọc vì bất kỳ ai cũng có thể thấy mã dọn dẹp được gọi trong mọi trường hợp.


0

Mã đang làm điều đó để đảm bảo rằng cơ sở dữ liệu được đóng lại.
Thông thường, cách bạn sẽ làm là đặt tất cả mã truy cập cơ sở dữ liệu của bạn vào khối thử, sau đó thực hiện cuộc gọi để đóng cơ sở dữ liệu trong khối cuối cùng.
Cách thử ... cuối cùng cũng hoạt động, có nghĩa là mã trong khối thử được chạy và mã trong khối cuối cùng được chạy khi kết thúc ... không có vấn đề gì.
Ngắn máy tính bị kéo mạnh ra khỏi tường, cuối cùng sẽ thực thi.
Điều này có nghĩa là ngay cả khi một ngoại lệ được gọi và phương thức phải mất ba năm để thực thi, nó vẫn sẽ đi vào khối cuối cùng và cơ sở dữ liệu sẽ bị đóng.


0

Nếu bất kỳ mã nào trong khối thử có thể đưa ra một ngoại lệ được kiểm tra, thì nó phải xuất hiện trong mệnh đề ném của chữ ký phương thức. Nếu một ngoại lệ không được kiểm tra được ném ra, nó sẽ bị bong ra khỏi phương thức.

Khối cuối cùng luôn được thực thi, cho dù có ngoại lệ được ném hay không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.