2012-02-06 37 views
11

Rõ ràng một trong những lệnh cấm lớn nhất của lập trình Java là null và ngoại lệ con trỏ null. Những mẫu thiết kế nào ở đó không thêm quá nhiều vào mã của bạn nhưng lại làm giảm vấn đề về ngoại lệ con trỏ rỗng không?Các mẫu thiết kế có trọng lượng nhẹ tốt để tránh null trong Java là gì?

+0

Chúng ta có thực sự cần mẫu để kiểm tra con trỏ không? Sử dụng một cái gì đó như commonsutil là không đủ? – kosa

+1

"Rõ ràng là một trong những lệnh cấm lớn nhất"? NullPointerExceptions là một trong các loại vấn đề dễ chẩn đoán nhất. –

+0

@thinksteep, nếu bạn làm điều đó rất nhiều và một mô hình tốt có thể được thiết lập, thì nó có lợi. Điều này đặc biệt đúng nếu cách nó thường được xử lý là tiết. – Joe

Trả lời

11

Null Object pattern. Nhìn vào số Optional từ google-guava library.

Wiki của họ có số article khi sử dụng và tránh các giá trị rỗng.

+0

Tôi biết google-ổi có rất nhiều món quà tuyệt vời. Tôi không biết nó giải quyết vấn đề này. – Joe

+0

Mô hình đối tượng Null có thể làm giảm bớt vấn đề về ngoại lệ con trỏ rỗng bằng null như thế nào? – UmNyobe

+0

@UmNyobe: Nếu bạn có một đối tượng thay vì null, bạn không thể nhận được một NullPointerException. –

4

Các mẫu thiết kế tốt nhất của tất cả - Kiểm tra Không-Null Idiom

if(obj != null) { 
    ... 
} 
+2

Chắc chắn không phải là mô hình tốt nhất. Kiểm tra điều này: 'object.get(). DoSomething(). DoMore(). StillProcessing() .epep(). GotIt()' (: – Marcelo

+0

Đó là một mô hình ổn nhưng không có nhiều thiết kế-bit là nó?:) –

+2

Tôi thấy rất nhiều mã sử dụng thành ngữ này, và nó thường làm tôi rùng mình - trừ khi có một "khác" liên kết với "if", tôi có xu hướng nghĩ rằng chúng ta đang chuyển sang lãnh thổ "không xác định hành vi". – DaveH

3

Chỉ cần làm quen với không trở về đối tượng null trên phương pháp của bạn.

public MyObject bohemianRhapsody(){ 

    try { 
     if(isThisTheRealLife()) 
      return new MyObject("is this just fantasy"); 
     else 
      return new MyObject("caught in a landslide, no escape from reality"); 
    } catch(ExampleCatchableException e){ 
     return new MyObject(""); // instead of return null 
    } 
} 

... 
System.out.println(bohemianRhapsody()); // will never print null 

Ngoài ra (loại) được gọi là Null-Object pattern.

+0

Trong mã của tôi, tôi vui vẻ ném bất kỳ ngoại lệ nào xảy ra. – UmNyobe

+0

Đây không phải là mẫu Null-Object. Có một sự khác biệt giữa một chuỗi rỗng và null. Mã gọi (bạn đã thực hiện công khai này sau này) có thể rất hợp lý muốn đưa ra các quyết định dựa trên việc liệu những gì được trả về là null hay rỗng. –

+0

@GeorgeMauer, nó rất hợp lý có thể sử dụng kết quả trực tiếp trên giao diện - trong trường hợp nào, tốt hơn là hiển thị "null" hoặc không có gì? – Marcelo

3

Tại sao bạn muốn tránh ngoại lệ con trỏ null? Bắt null khi mong đợi một cái gì đó khác nó là một trong những dấu hiệu đầu tiên một cái gì đó là sai khi bạn viết mã. Những thứ như Null Object Pattern nên được sử dụng khi bạn chắc chắn rằng nó là đủ. Một trong những nhược điểm lớn nhất của mẫu thiết kế là lạm dụng của họ \ lạm dụng.

CHỈNH SỬA:

Tôi nghĩ cách tốt nhất để giảm trở lại null sẽ là tăng mức sử dụng ngoại lệ. Hãy suy nghĩ về một danh sách trả về một đối tượng null khi bạn cố gắng truy cập vào các phần tử tại chỉ số -1, bạn sẽ sử dụng những thứ như

if(list.get(-1).equals(nullObject))

mà thậm chí còn tồi tệ hơn. Tôi tin rằng nó là tốt hơn để nâng cao một ngoại lệ khi các đối số là bất ngờ hoặc không tương thích.

+0

Các ngoại lệ được kiểm tra khác thích hợp hơn với các con trỏ null. Tôi không thích con trỏ null bởi vì chúng chỉ ra điều gì đó sai, nhưng chúng làm vào lúc RUN-TIME. Một cái gì đó giống như mô hình đối tượng Null là tốt hơn, bởi vì mã của bạn đang theo dõi lỗi và có thể cung cấp một giải thích hợp lý cho vấn đề. – Joe

2

Tôi đoán đó là vấn đề về hương vị, nhưng tôi sẽ nói rằng những lệnh cấm lớn nhất của các ngôn ngữ như Smalltalk/Objective-C là chúng KHÔNG có null và AREN'T bất kỳ NullPointerExceptions nào. Tôi không phải là một fan hâm mộ của "mô hình đối tượng Null", trên thực tế tôi ghét nó với niềm đam mê như tôi thấy nó làm cho xử lý sự cố và tìm lỗi khó khăn hơn nhiều mà không có bất kỳ lợi ích thực sự. Null có ý nghĩa (thường là xấu) và không nên được coi như bất kỳ trạng thái chung nào khác.

Giống như đã được đề cập trong chủ đề này, NPE thực sự mạnh mẽ và cách tốt để nắm bắt các lỗi cú pháp hoặc mã hóa sớm và if (obj != null) là khá đơn giản. Nếu ứng dụng của bạn bắt đầu tạo NPE trong thời gian chạy, bạn đã làm điều gì đó sai và bạn cần sửa nó. Đừng cố gắng che giấu ngoại lệ, sửa chữa bất cứ điều gì nó là gây ra ngoại lệ.

+0

Ngoại lệ con trỏ rỗng là một ngoại lệ không được kiểm soát. Vì vậy, vấn đề là bạn sẽ không biết vấn đề cho đến khi chạy. Nó là tốt hơn là mã của bạn được viết để giải quyết không có giá trị cho một cái gì đó ở nơi đầu tiên. – Joe

+0

Tất nhiên. Đó là lý do tại sao bạn kiểm tra null-ness. Những gì tôi thấy đáng sợ mặc dù, là khi một giá trị có thể được null mà không gây ra một phản ứng rõ ràng và thích hợp (như một NPE). Toàn bộ "null cũng là một đối tượng" ý tưởng trong Smalltalk/Obj-c Tôi thấy chỉ đơn giản là kinh khủng. Null không phải là một giá trị, nó là null. – pap

+1

Nhưng những gì về một đối tượng null mà gói gọn rằng có một lỗi và thậm chí ném ngoại lệ kiểm tra khi nó được sử dụng sau khi nó được thiết lập. Vấn đề với việc kiểm tra tính rỗng, là chúng ta là con người và có thể quên làm điều đó. Null cơ bản phá vỡ mô hình đối tượng Java. Nếu bạn không cảm thấy cần một ngôn ngữ nắm tay bạn và nhắc bạn làm mọi thứ, bạn sẽ làm việc hiệu quả hơn trong một ngôn ngữ có cách gõ nhẹ hơn Java. – Joe

2
"something definetly not null".equals(maybeNullVar) 

vs

maybeNullVar.equals("something definetly not null") 
1

Những phương pháp này (xem thêm commons Apache -lang) có thể giảm gánh nặng kiểm tra null trong các trường hợp xử lý chuỗi bằng cách đóng gói chúng trong các phương thức tha t giữ ý nghĩa ngữ nghĩa của mã:

public static boolean isBlank(final String str) 
{ 
    return (str == null) || str.isEmpty(); 
} 

public static boolean isNotBlank(final String str) 
{ 
    return !StringUtils.isBlank(str); 
} 

public static boolean isEqual(final String s1, final String s2) 
{ 
    if (s1 == s2) { return true; } 
    if ((s1 == null) || (s2 == null)) { return false; } 
    return s1.equals(s2); 
} 

public static boolean isNotEqual(final String s1, final String s2) 
{ 
    return !StringUtils.isEqual(s1, s2); 
} 
1

Bạn không phải sử dụng bất kỳ mẫu thiết kế nào.

Chỉ cần khởi tạo biến trong quá trình khai báo.

ví dụ:

List<String> names = new ArrayList<String>(); 
Map<String,String> pairs = new HashMap<String,String>(); 
Các vấn đề liên quan