2012-01-09 29 views
5

Tôi có một phương thức được gán cho một đối tượng Set. Phương thức mà đại biểu yêu cầu rằng Set không chứa bất kỳ phần tử null nào. Tôi muốn check the precondition rằng Set không chứa các phần tử null sớm, theo phương pháp trước khi phái đoàn. Mã rõ ràng làm làm như vậy là thế này:Cách gọn gàng để kiểm tra xem Tập hợp có chứa một số không

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) { 
     throw new NullPointerException("plugIns"); 
    } else if (plugIns.contains(null)) { 
     throw new NullPointerException("plugIns null element"); 
    } 
    // Body 
} 

Nhưng điều này là không chính xác, bởi vì Set.contains() có thể ném một NullPointerException nếu Set thực hiện tự không cho phép các yếu tố null. Khi đó, việc bỏ qua NullPointerException trong trường hợp đó sẽ hoạt động but would be inelegant. Có cách nào gọn gàng để kiểm tra điều kiện tiên quyết này không?


Có lỗ hổng thiết kế trong giao diện Set không? Nếu triển khai Set có thể không bao giờ chứa giá trị rỗng, tại sao thay vào đó không yêu cầu để luôn trả về false? Hoặc có một vị từ isNullElementPermitted()?

+0

Nếu bạn có yêu cầu cụ thể như thế này, phân lớp 'Đặt' và không cho phép' null' đặt. Ngoài ra, tôi sẽ không sử dụng 'else' ở đây. –

Trả lời

4

Cách đơn giản nhất là liệt kê Tập hợp và kiểm tra các giá trị rỗng.

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) throw new NullPointerException("plugIns"); 
    for (PlugIn plugIn : plugIns) { 
    if (plugIn == null) throw new NullPointerException("plugIns null element"); 
    } 
} 
+0

Đơn giản, nhưng 'O (N)' phức tạp, điều này là xấu đối với kiểm tra điều kiện tiên quyết. – Raedwald

+0

Để báo giá khác: "Preoptimisation là gốc rễ của tất cả các điều ác". Bạn có chắc đây là một nút cổ chai hiệu suất? Với những gì bạn đang làm, tôi đoán rằng có một vấn đề kiến ​​trúc ở nơi khác. –

+0

Mối quan tâm của tôi là * không * tối ưu hóa sớm. Một giải pháp gọn gàng nên là mục đích chung và hiệu quả hợp lý. Mỗi khi ai đó sử dụng một 'HashSet' mà không có hiệu suất đo đầu tiên, và nhận được lợi ích của' Set.contains() 'nhanh, họ không tham gia vào việc tối ưu hóa sớm. http://programmers.stackexchange.com/questions/79946/what-is-the-best-retort-to-premature-optimization-is-the-root-of-all-evil. – Raedwald

3

Tạo một HashSet từ plugIns và kiểm tra sự tồn tại của null

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) throw new NullPointerException("plugIns"); 
    Set<PlugIn> copy = new HashSet<PlugIn>(plugIns); 
    if (copy.contains(null)) { 
     throw new NullPointerException("null is not a valid plugin"); 
    } 
} 
+0

Đơn giản, nhưng 'O (N)' phức tạp và tạo ra một đối tượng mới, điều này không tốt cho việc kiểm tra điều kiện tiên quyết. – Raedwald

+1

Bạn có bao nhiêu nghìn lần mỗi giây để quét tìm các trình cắm thêm mới không? ;) Theo kinh nghiệm của tôi, việc sao chép hoặc tạo bộ sưu tập mới hiếm khi là vấn đề hiệu suất. Có lẽ bạn nên ngăn chặn 'null' được thêm vào nơi' plugIns' đến từ (với tôi có vẻ như bạn đang sửa mã lỗi của người khác, trừ khi có một lý do hợp lệ cho sự tồn tại của một 'null'-plugin) – Matt

+0

Tôi không làm điều này để làm việc xung quanh mã lỗi. Tôi muốn làm điều đó bởi vì nó là tốt hơn để phát hiện lỗi sớm. Hãy tưởng tượng đây là một phương pháp API: chúng tôi sẽ không kiểm soát mã gọi điện, nhưng có thể muốn cung cấp chẩn đoán tốt. – Raedwald

2

Chỉ cần bắt NullPointerException nếu ném và bỏ qua nó:

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) { 
     throw new NullPointerException("plugIns"); 
    } 

    NullPointerException e = null; 
    try { 
     if (plugIns.contains(null)) { 
      // If thrown here, the catch would catch this NPE, so just create it 
      e = new NullPointerException("plugIns null element"); 
     } 
    } catch (NullPointerException ignore) { } 

    if (e != null) { 
     throw e; 
    } 
    // Body 
} 

Điều này tạo ra chỉ là một chi phí nhỏ nếu ném, nhưng nếu bạn không sử dụng ngoại lệ (đặc biệt là dấu vết strack), nó thực sự khá nhẹ.

+0

Bạn có nghĩ rằng các ứng cử viên NPE của bạn có nhiều ứng cử viên IllegalArgumentException hơn không? – Prakhar

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