2009-09-03 26 views

Trả lời

324

Có, nhà thầu có thể ném ngoại lệ. Thông thường điều này có nghĩa là đối tượng mới ngay lập tức đủ điều kiện để thu gom rác (mặc dù nó có thể không được thu thập trong một thời gian, tất nhiên). Có thể đối tượng "được xây dựng một nửa" để dính xung quanh, nếu nó được hiển thị trước đó trong hàm khởi tạo (ví dụ: bằng cách gán một trường tĩnh hoặc tự thêm vào một bộ sưu tập).

Một điều cần lưu ý về việc ném ngoại lệ trong hàm tạo: bởi vì người gọi (thường) sẽ không có cách nào để sử dụng đối tượng mới, nên phải cẩn thận để tránh lấy tài nguyên không được quản lý (tệp xử lý, v.v) và sau đó ném một ngoại lệ mà không giải phóng chúng. Ví dụ: nếu người xây dựng cố gắng mở một số FileInputStreamFileOutputStream và thành công đầu tiên nhưng thứ hai không thành công, bạn nên cố gắng đóng luồng đầu tiên. Điều này trở nên khó khăn hơn nếu nó là một hàm tạo lớp con ném ngoại lệ, tất nhiên ... tất cả trở nên phức tạp một chút. Nó không phải là một vấn đề rất thường xuyên, nhưng nó đáng xem xét.

+25

+1. Không ai thường nghĩ về ngoại lệ được ném bởi các lớp con. –

+1

@JonSkeet: ** Bạn có thể vui lòng cung cấp cho chúng tôi một số ví dụ về mã ** * nếu nó được hiển thị trước đó trong hàm tạo (ví dụ: bằng cách gán một trường tĩnh hoặc tự thêm vào bộ sưu tập). *? – Tarik

+3

@Tarik: Ví dụ mã sẽ làm chính xác điều đó - ví dụ: 'someStaticField = this;' hoặc 'someCollection.add (this)' trong một hàm tạo. –

31

Tuyệt đối.

Nếu hàm tạo không nhận được đầu vào hợp lệ hoặc không thể xây dựng đối tượng theo cách hợp lệ, nó không có tùy chọn nào ngoài việc ném ngoại lệ và cảnh báo người gọi.

7

Có.

Các nhà xây dựng không có gì khác ngoài các phương pháp đặc biệt và có thể ném ngoại lệ giống như bất kỳ phương pháp nào khác.

+0

Điều quan trọng trong tuyên bố của bạn là "phương pháp đặc biệt". Vì vậy, họ không giống như bất kỳ phương pháp khác. Việc ném một ngoại lệ từ một hàm tạo của lớp không phải là cuối cùng ** có thể ** tạo ra một lỗ hổng bảo mật, vì vậy hãy cẩn thận đặc biệt khi quyết định thực hiện điều này. Xem câu trả lời của @Billy ở trên, với trích xuất từ ​​Nguyên tắc mã hóa an toàn Java. –

11

Có, người xây dựng được phép ném ngoại lệ.

Tuy nhiên, hãy rất khôn ngoan trong việc chọn những ngoại lệ mà chúng phải là - ngoại lệ được kiểm tra hoặc không được chọn. Các ngoại lệ không được kiểm tra về cơ bản là các lớp con của RuntimeException.

Trong hầu hết các trường hợp (tôi không thể đưa ra ngoại lệ cho trường hợp này), bạn sẽ cần phải ném ngoại lệ đã kiểm tra. Lý do là các ngoại lệ không được kiểm tra (như NullPointerException) thường là do lỗi lập trình (như không xác nhận đủ đầu vào).

Lợi thế mà phiếu mua hàng ngoại lệ đã kiểm tra là lập trình viên bắt buộc phải loại trừ ngoại lệ trong mã instantiation của mình và do đó nhận ra rằng có thể không tạo được đối tượng đối tượng. Tất nhiên, chỉ có một đánh giá mã sẽ bắt thực hành lập trình nghèo nuốt một ngoại lệ.

76

Có, họ có thể ném ngoại lệ. Nếu vậy, chúng sẽ chỉ được khởi tạo một phần và nếu không phải là cuối cùng, sẽ bị tấn công.

Sau đây là từ Secure Coding Guidelines 2.0.

Trường hợp khởi tạo một phần của lớp không phải cuối cùng có thể được truy cập thông qua cuộc tấn công finalizer. Kẻ tấn công ghi đè phương thức hoàn thiện được bảo vệ trong một lớp con và cố gắng tạo một cá thể mới của lớp con đó. Nỗ lực này không thành công (trong ví dụ trên, kiểm tra SecurityManager trong trình tạo lớp của ClassLoader ném ra một ngoại lệ bảo mật), nhưng kẻ tấn công chỉ đơn giản bỏ qua bất kỳ ngoại lệ nào và chờ cho máy ảo thực hiện quyết toán trên đối tượng được khởi tạo một phần. Khi điều đó xảy ra, việc thực thi phương thức finalize độc ​​hại được gọi, cho phép kẻ tấn công truy cập vào điều này, một tham chiếu đến đối tượng đang được hoàn thành. Mặc dù đối tượng chỉ được khởi tạo một phần, kẻ tấn công vẫn có thể gọi các phương thức trên nó (do đó phá vỡ kiểm tra SecurityManager).

+1

Điều này có nghĩa là ném từ lớp không phải cuối cùng là một vi phạm an ninh? Đây có phải là vấn đề không? – kroiz

+1

Lưu ý rằng hướng dẫn này chỉ phù hợp nếu mã của bạn, hoặc có khả năng được sử dụng trong bối cảnh an ninh là quan trọng. Ví dụ, hầu hết mã Java được sử dụng trong các ngữ cảnh không có SecurityManager. –

0

Nhà xây dựng CÓ THỂ ném bất kỳ ngoại lệ nào. Nhưng nếu bất kỳ hàm tạo lớp con nào gọi là một hàm tạo lớp siêu mà đưa ra một ngoại lệ, thì trình tạo lớp con phải bắt giữ ngoại lệ hoặc ném nó.

+8

Một hàm tạo lớp con không thể bắt được ngoại lệ, vì sử dụng khối thử trước khi siêu() sẽ gây ra lỗi biên dịch ("gọi siêu phải là câu lệnh đầu tiên trong hàm tạo") –

10

Vâng, nó có thể ném một ngoại lệ và bạn có thể tuyên bố rằng trong chữ ký của các nhà xây dựng quá như trong ví dụ dưới đây:

public class ConstructorTest 
{ 
    public ConstructorTest() throws InterruptedException 
    { 
     System.out.println("Preparing object...."); 
     Thread.sleep(1000); 
     System.out.println("Object ready"); 
    } 

    public static void main(String ... args) 
    { 
     try 
     { 
      ConstructorTest test = new ConstructorTest(); 
     } 
     catch (InterruptedException e) 
     { 
      System.out.println("Got interrupted..."); 
     } 
    } 
} 
-1

có nó có thể ném một ngoại lệ như các phương pháp khác không

+1

Cảm ơn bạn rất nhiều vì câu trả lời chi tiết này, mặc dù câu hỏi này đã được trả lời bởi các bài viết tốt hơn nhiều rồi. – Tom

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