2011-10-04 25 views
5

Hầu hết thời gian, điều duy nhất tôi nhìn thấy một khối finally dùng để làm một cái gì đó giống nhưTại sao tôi cần sử dụng cuối cùng để đóng tài nguyên?

FileInputStream f; 
try{ 
    f= new FileInputStream("sample.txt"); 
    //something that uses f and sometimes throws an exception 
} 
catch(IOException ex){ 
    /* Handle it somehow */ 
} 
finally{ 
    f.close(); 
} 

Câu hỏi của tôi là, nếu phạm vi f kết thúc bằng khối kèm theo, tại sao chúng ta cần phải đóng nó vào cuối cùng ?

+0

Trong trường hợp của bạn, phạm vi 'f' không kết thúc với khối try –

+0

@Oli Charlesworth: Đây rõ ràng là một ví dụ có thể đọc được. –

+0

Tạo tham chiếu tệp không ném ngoại lệ (hoặc tạo một xử lý tệp), để tham khảo trong tương lai. –

Trả lời

18

Vì thu gom rác thải là không phải điều tương tự như dọn dẹp tài nguyên.

Ví dụ, nếu bạn có đối tượng kết nối JDBC nằm ngoài phạm vi, không có tín hiệu nào được gửi đến máy chủ cơ sở dữ liệu để cho biết rằng các con trỏ và kết nối mở không còn cần thiết nữa. Nếu không có những thông điệp đó, cuối cùng bạn sẽ loại bỏ số lượng các con trỏ và các kết nối có sẵn cho bạn.

Tương tự với các tệp xử lý và bất kỳ tài nguyên nào khác. Dọn sạch sau bản thân mình.

+2

Vâng, tất nhiên. Nhưng tại sao 'cuối cùng'? –

+5

Bởi vì mã trong khối cuối cùng được đảm bảo được thực hiện, ngay cả khi một ngoại lệ được ném. – duffymo

+1

@Joe ví dụ hay. Nhưng không bao giờ trả lại một cái gì đó trong một khối cuối cùng nếu bạn có một khối catch mà ném một ngoại lệ. trong trường hợp đó, ngoại lệ của bạn sẽ không bao giờ bị ném ... tôi học cách này một cách khó khăn ;-) – Cygnusx1

6

Vâng, bạn đã đưa ra một ví dụ xấu - tôi nghi ngờ bạn có nghĩa là một cái gì đó như FileInputStream - nhưng lý do cơ bản là Java không có quyết toán xác định.

Phạm vi của biếnf kết thúc với khối nó khai báo trong (không phải là khối try), nhưng điều đó không có nghĩa là nhất thiết không có tham chiếu "sống" với đối tượng nữa - và thu gom rác sẽ không hoàn thành đối tượng cũng như không thu thập rác trong bất kỳ cách xác định nào.

Trừ khi bạn muốn rời khỏi tài nguyên treo xung quanh một khoảng thời gian tùy ý (và trì hoãn thu gom rác, vì finalizers yêu cầu thêm một bộ sưu tập trước khi bộ nhớ được phát hành cuối cùng), bạn nên đóng tài nguyên một cách rõ ràng.

Về cơ bản Java thực hiện không hỗ trợ RAII theo cách tương tự như C++; bạn không nên cố gắng sử dụng nó như thể nó là C++.

+0

Đã chỉnh sửa để phản ánh đề xuất của bạn: Tôi vừa mới có được bộ nhớ có thể mở rộng, vì vậy cảm ơn vì đã cho tôi một điều thực sự áp dụng : P –

0

Lý do là Java không đảm bảo rằng một đối tượng sẽ được thu thập rác ngay sau khi một tham chiếu cụ thể đến nó nằm ngoài phạm vi. Vì vậy, đối với các đối tượng tham chiếu đến các tài nguyên hệ thống hạn chế, chẳng hạn như một bộ mô tả tập tin, nó không đủ để chờ thu gom rác.

Lưu ý rằng, java.io.File không thực sự là một đối tượng như vậy.

1

vì cuối cùng được gọi là mọi lúc, ngay cả khi bạn nhận được ngoại lệ được nêu ra. khối cuối cùng đảm bảo với bạn rằng tệp/kết nối sẽ bị đóng.

0

Chúng tôi xử lý ngoại lệ bằng cách thử bắt cuối cùng, cuối cùng chặn mọi lần thực thi nhưng không đảm bảo bắt vì khối catch chỉ thực thi nếu ngoại lệ được truyền trong tham số khớp. Ví dụ, nếu chúng ta đã mở bất kỳ kết nối cơ sở dữ liệu nào thì chúng ta phải đóng nó trước khi rời khỏi, nó phải được thực hiện vào cuối cùng.

Các vấn đề liên quan